diff --git a/README.md b/README.md index c017c0e..f8e2bc6 100644 --- a/README.md +++ b/README.md @@ -139,3 +139,61 @@ ### Architecture - **mysql**: Database storage for articles, logs, and application data Both app containers use the same Docker image but with different commands (`web` or `queue`). Environment variables are passed from your `.env` file to configure database access and Lemmy integration. + +## Development Setup + +For local development with Podman: + +### Prerequisites + +- Podman and podman-compose installed +- Git + +### Quick Start + +1. **Clone and start the development environment:** + ```bash + git clone + cd ffr + ./docker/dev/podman/start-dev.sh + ``` + +2. **Access the application:** + - **Web interface**: http://localhost:8000 + - **Vite dev server**: http://localhost:5173 + - **Database**: localhost:3307 + - **Redis**: localhost:6380 + +### Development Commands + +**Load Sail-compatible aliases:** +```bash +source docker/dev/podman/podman-sail-alias.sh +``` + +**Useful commands:** +```bash +# Run tests +ffr-test + +# Execute artisan commands +ffr-artisan migrate +ffr-artisan tinker + +# View application logs +ffr-logs + +# Open container shell +ffr-shell + +# Stop environment +podman-compose -f docker/dev/podman/docker-compose.yml down +``` + +### Development Features + +- **Hot reload**: Vite automatically reloads frontend changes +- **Database**: Pre-configured MySQL with migrations and seeders +- **Redis**: Configured for caching, sessions, and queues +- **Laravel Horizon**: Available for queue monitoring +- **No configuration needed**: Development environment uses preset configuration diff --git a/app/Http/Middleware/HandleInertiaRequests.php b/app/Http/Middleware/HandleInertiaRequests.php new file mode 100644 index 0000000..303786e --- /dev/null +++ b/app/Http/Middleware/HandleInertiaRequests.php @@ -0,0 +1,42 @@ + + */ + public function share(Request $request): array + { + return array_merge(parent::share($request), [ + // + ]); + } +} \ No newline at end of file diff --git a/docker/dev/podman/.env.dev b/docker/dev/podman/.env.dev new file mode 100644 index 0000000..f0df808 --- /dev/null +++ b/docker/dev/podman/.env.dev @@ -0,0 +1,62 @@ +APP_NAME="FFR Development" +APP_ENV=local +APP_KEY=base64:YOUR_APP_KEY_HERE +APP_DEBUG=true +APP_TIMEZONE=UTC +APP_URL=http://localhost:8000 + +APP_LOCALE=en +APP_FALLBACK_LOCALE=en +APP_FAKER_LOCALE=en_US + +APP_MAINTENANCE_DRIVER=file +APP_MAINTENANCE_STORE=database + +BCRYPT_ROUNDS=12 + +LOG_CHANNEL=stack +LOG_STACK=single +LOG_DEPRECATIONS_CHANNEL=null +LOG_LEVEL=debug + +DB_CONNECTION=mysql +DB_HOST=db +DB_PORT=3306 +DB_DATABASE=ffr_dev +DB_USERNAME=ffr_user +DB_PASSWORD=ffr_password + +SESSION_DRIVER=redis +SESSION_LIFETIME=120 +SESSION_ENCRYPT=false +SESSION_PATH=/ +SESSION_DOMAIN=null + +BROADCAST_CONNECTION=log +FILESYSTEM_DISK=local +QUEUE_CONNECTION=redis + +CACHE_STORE=redis +CACHE_PREFIX= + +REDIS_CLIENT=phpredis +REDIS_HOST=redis +REDIS_PASSWORD=null +REDIS_PORT=6379 + +MAIL_MAILER=log +MAIL_HOST=127.0.0.1 +MAIL_PORT=2525 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null +MAIL_FROM_ADDRESS="hello@example.com" +MAIL_FROM_NAME="${APP_NAME}" + +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET= +AWS_USE_PATH_STYLE_ENDPOINT=false + +VITE_APP_NAME="${APP_NAME}" \ No newline at end of file diff --git a/docker/dev/podman/Dockerfile b/docker/dev/podman/Dockerfile new file mode 100644 index 0000000..f990236 --- /dev/null +++ b/docker/dev/podman/Dockerfile @@ -0,0 +1,51 @@ +FROM docker.io/library/php:8.4-fpm + +# Install system dependencies +RUN apt-get update && apt-get install -y \ + git \ + curl \ + libpng-dev \ + libonig-dev \ + libxml2-dev \ + zip \ + unzip \ + nodejs \ + npm \ + default-mysql-client \ + && docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd \ + && pecl install redis \ + && docker-php-ext-enable redis + +# Install Composer +COPY --from=composer:latest /usr/bin/composer /usr/bin/composer + +# Set working directory +WORKDIR /var/www/html + +# Install Node.js 20.x (for better compatibility) +RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ + && apt-get install -y nodejs + +# Copy composer files and install PHP dependencies +COPY composer.json ./ +RUN composer install --optimize-autoloader --no-scripts + +# Copy package.json and install Node dependencies +COPY package*.json ./ +RUN npm install + +# Copy application code +COPY . . + +# Set permissions +RUN chown -R www-data:www-data /var/www/html \ + && chmod -R 755 /var/www/html/storage \ + && chmod -R 755 /var/www/html/bootstrap/cache + +# Copy and set up container start script +COPY docker/dev/podman/container-start.sh /usr/local/bin/container-start.sh +RUN chmod +x /usr/local/bin/container-start.sh + +EXPOSE 8000 5173 + +CMD ["/usr/local/bin/container-start.sh"] \ No newline at end of file diff --git a/docker/dev/podman/container-start.sh b/docker/dev/podman/container-start.sh new file mode 100755 index 0000000..d1a669d --- /dev/null +++ b/docker/dev/podman/container-start.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# Copy development environment configuration +cp /var/www/html/docker/dev/podman/.env.dev /var/www/html/.env + +# Install/update dependencies +echo "Installing PHP dependencies..." +composer install --no-interaction + +echo "Installing Node dependencies..." +npm install + +# Generate app key if not set or empty +if grep -q "APP_KEY=base64:YOUR_APP_KEY_HERE" /var/www/html/.env || ! grep -q "APP_KEY=base64:" /var/www/html/.env; then + echo "Generating application key..." + php artisan key:generate --force +fi + +# Wait for database to be ready +echo "Waiting for database..." +while ! mysql -h db -u ffr_user -pffr_password --connect-timeout=2 -e "SELECT 1" >/dev/null 2>&1; do + echo "Database not ready, waiting..." + sleep 1 +done +echo "Database connection established!" + +# Run migrations and seeders +php artisan migrate --force +php artisan db:seed --force + +# Start Laravel development server in background +php artisan serve --host=0.0.0.0 --port=8000 & + +# Start Vite development server +npm run dev -- --host 0.0.0.0 + +# Wait for background processes +wait \ No newline at end of file diff --git a/docker/dev/podman/docker-compose.yml b/docker/dev/podman/docker-compose.yml new file mode 100644 index 0000000..1c8d461 --- /dev/null +++ b/docker/dev/podman/docker-compose.yml @@ -0,0 +1,77 @@ +services: + app: + build: + context: ../../.. + dockerfile: docker/dev/podman/Dockerfile + container_name: ffr-dev-app + restart: unless-stopped + working_dir: /var/www/html + environment: + - APP_ENV=local + - APP_DEBUG=true + - APP_KEY=base64:YOUR_APP_KEY_HERE + - DB_CONNECTION=mysql + - DB_HOST=db + - DB_PORT=3306 + - DB_DATABASE=ffr_dev + - DB_USERNAME=ffr_user + - DB_PASSWORD=ffr_password + - REDIS_HOST=redis + - REDIS_PORT=6379 + - QUEUE_CONNECTION=redis + - CACHE_DRIVER=redis + - SESSION_DRIVER=redis + - VITE_PORT=5173 + volumes: + - ../../../:/var/www/html:Z + - /var/www/html/node_modules + - /var/www/html/vendor + ports: + - "8000:8000" + - "5173:5173" + depends_on: + db: + condition: service_healthy + redis: + condition: service_started + networks: + - ffr-dev-network + + db: + image: docker.io/library/mysql:8.0 + container_name: ffr-dev-db + restart: unless-stopped + environment: + - MYSQL_DATABASE=ffr_dev + - MYSQL_USER=ffr_user + - MYSQL_PASSWORD=ffr_password + - MYSQL_ROOT_PASSWORD=root_password + volumes: + - db_data:/var/lib/mysql + ports: + - "3307:3306" + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "ffr_user", "-pffr_password"] + timeout: 5s + retries: 5 + interval: 3s + start_period: 30s + networks: + - ffr-dev-network + + redis: + image: docker.io/library/redis:7-alpine + container_name: ffr-dev-redis + restart: unless-stopped + ports: + - "6380:6379" + networks: + - ffr-dev-network + +networks: + ffr-dev-network: + driver: bridge + +volumes: + db_data: + driver: local \ No newline at end of file diff --git a/docker/dev/podman/podman-sail-alias.sh b/docker/dev/podman/podman-sail-alias.sh new file mode 100755 index 0000000..07b90ed --- /dev/null +++ b/docker/dev/podman/podman-sail-alias.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# Podman aliases for Laravel Sail compatibility +# Source this file to use Sail commands with Podman +# Usage: source docker/dev/podman/podman-sail-alias.sh + +# Create docker alias pointing to podman +alias docker='podman' + +# Create docker-compose alias pointing to podman-compose +alias docker-compose='podman-compose' + +# Sail wrapper function that uses podman-compose +sail() { + if [[ -f docker/dev/podman/docker-compose.yml ]]; then + podman-compose -f docker/dev/podman/docker-compose.yml "$@" + else + echo "โŒ Podman compose file not found at docker/dev/podman/docker-compose.yml" + return 1 + fi +} + +# FFR-specific helper functions +ffr-test() { + echo "๐Ÿงช Running FFR tests..." + podman exec ffr-dev-app php artisan test "$@" +} + +ffr-artisan() { + echo "๐Ÿ”ง Running artisan command..." + podman exec ffr-dev-app php artisan "$@" +} + +ffr-logs() { + echo "๐Ÿ“‹ Showing FFR application logs..." + podman-compose -f docker/dev/podman/docker-compose.yml logs -f app +} + +ffr-shell() { + echo "๐Ÿš Opening shell in FFR container..." + podman exec -it ffr-dev-app bash +} + +echo "โœ… FFR Podman aliases set up for Laravel Sail compatibility" +echo "๐Ÿณ 'docker' โ†’ 'podman'" +echo "๐Ÿ”ง 'docker-compose' โ†’ 'podman-compose'" +echo "โ›ต 'sail' โ†’ uses podman-compose with dev configuration" +echo "๐Ÿš€ FFR-specific commands:" +echo " 'ffr-test' โ†’ run tests" +echo " 'ffr-artisan' โ†’ run artisan commands" +echo " 'ffr-logs' โ†’ view application logs" +echo " 'ffr-shell' โ†’ open container shell" \ No newline at end of file diff --git a/docker/dev/podman/start-dev.sh b/docker/dev/podman/start-dev.sh new file mode 100755 index 0000000..29681b8 --- /dev/null +++ b/docker/dev/podman/start-dev.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +# Podman development environment startup script for FFR + +set -e + +echo "๐Ÿš€ Starting FFR development environment with Podman..." + +# Check if .env exists +if [ ! -f .env ]; then + echo "๐Ÿ“‹ Creating .env file from .env.example..." + cp .env.example .env + echo "โš ๏ธ Please update your .env file with appropriate values, especially APP_KEY" +fi + +# Check if podman-compose is available +if ! command -v podman-compose &> /dev/null; then + echo "โŒ podman-compose not found. Installing..." + pip3 install --user podman-compose + echo "โœ… podman-compose installed" +fi + +# Start services +echo "๐Ÿ”ง Starting services..." +podman-compose -f docker/dev/podman/docker-compose.yml up -d + +# Wait for database to be ready +echo "โณ Waiting for database to be ready..." +sleep 10 + +# Check if APP_KEY is set +if grep -q "APP_KEY=base64:YOUR_APP_KEY_HERE" .env || grep -q "APP_KEY=$" .env; then + echo "๐Ÿ”‘ Generating application key..." + podman exec ffr-dev-app php artisan key:generate +fi + +# Run migrations and seeders +echo "๐Ÿ—ƒ๏ธ Running database migrations..." +podman exec ffr-dev-app php artisan migrate --force +echo "๐ŸŒฑ Running database seeders..." +podman exec ffr-dev-app php artisan db:seed --force + +# Install/update dependencies if needed +echo "๐Ÿ“ฆ Installing dependencies..." +podman exec ffr-dev-app composer install +podman exec ffr-dev-app npm install + +echo "โœ… Development environment is ready!" +echo "๐ŸŒ Application: http://localhost:8000" +echo "๐Ÿ”ฅ Vite dev server: http://localhost:5173" +echo "๐Ÿ’พ Database: localhost:3307" +echo "๐Ÿ”ด Redis: localhost:6380" +echo "" +echo "๐Ÿ“‹ Useful commands:" +echo " Stop: podman-compose -f docker/dev/podman/docker-compose.yml down" +echo " Logs: podman-compose -f docker/dev/podman/docker-compose.yml logs -f" +echo " Exec: podman exec -it ffr-dev-app bash" +echo " Tests: podman exec ffr-dev-app php artisan test" \ No newline at end of file diff --git a/incr-docker b/incr-docker new file mode 120000 index 0000000..c0798f0 --- /dev/null +++ b/incr-docker @@ -0,0 +1 @@ +../incr/docker \ No newline at end of file diff --git a/package.json b/package.json index afdc724..9843b30 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,9 @@ }, "devDependencies": { "laravel-vite-plugin": "^1.0", - "vite": "^6.0" + "vite": "^6.0", + "@tailwindcss/vite": "^4.0.0", + "tailwindcss": "^4.0.0", + "tailwindcss-animate": "^1.0.7" } } \ No newline at end of file diff --git a/vite.config.js b/vite.config.js index 7b6cb94..fb1c8f3 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,8 +1,10 @@ import { defineConfig } from 'vite'; import laravel from 'laravel-vite-plugin'; +import tailwindcss from '@tailwindcss/vite'; export default defineConfig({ plugins: [ + tailwindcss(), laravel({ input: [ 'resources/css/app.css',