commit 661772795bb0a647fd26954fe6f6b21eac16018b Author: johnhkchen Date: Wed Oct 22 10:22:22 2025 -0700 Initial commit diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..cdfa24e --- /dev/null +++ b/.env.example @@ -0,0 +1,19 @@ +# Portfolio Infrastructure - Environment Configuration +# Copy this to .env and fill in your values + +# Database Configuration +DB_USER=directus +DB_PASSWORD=your_secure_database_password_here + +# Directus Admin Account +ADMIN_EMAIL=your_email@example.com +ADMIN_PASSWORD=your_secure_admin_password_here + +# Directus Security Keys (generate with: openssl rand -base64 32) +DIRECTUS_KEY=your_directus_key_here +DIRECTUS_SECRET=your_directus_secret_here + +# Public URL +# For local: http://localhost:8055 +# For Coolify: https://directus.yourdomain.com +PUBLIC_URL=http://localhost:8055 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2584d7e --- /dev/null +++ b/.gitignore @@ -0,0 +1,40 @@ +# Environment files with sensitive data +.env +.env.local +.env.production + +# Database backups and dumps (contain real data) +*.sql +database/*.sql +!database/schema/ + +# Uploads (user-generated content) +uploads/* +!uploads/.gitkeep + +# Extensions (if they contain sensitive config) +extensions/* +!extensions/.gitkeep + +# Docker volumes +postgres_data/ +directus_uploads/ +directus_extensions/ + +# Logs +*.log +logs/ + +# OS files +.DS_Store +Thumbs.db + +# IDE +.vscode/ +.idea/ +*.swp +*.swo + +# Temporary files +*.tmp +.cache/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..014adb6 --- /dev/null +++ b/README.md @@ -0,0 +1,216 @@ +# Portfolio Infrastructure - Directus CMS + +Shared infrastructure providing CMS and API services for all portfolio demos. + +## Purpose + +This repository contains the **infrastructure layer** for the portfolio platform: +- **Directus CMS**: Content management and API +- **PostgreSQL**: Database backend + +This is deployed **once** and provides services to multiple demo applications. + +## Architecture + +``` +┌─────────────────────────────────────┐ +│ Portfolio Infrastructure │ +│ Domain: directus.b28.dev │ +├─────────────────────────────────────┤ +│ ┌──────────────┐ ┌─────────────┐ │ +│ │ Directus │──│ PostgreSQL │ │ +│ │ CMS/API │ │ Database │ │ +│ └──────────────┘ └─────────────┘ │ +└─────────────────────────────────────┘ + │ + │ (consumed by demos) + ▼ + Demo Applications + ├─ portfolio-site + ├─ hackathon-project-1 + └─ hackathon-project-2 +``` + +## Directus Collections + +### Core Collections +- **profile**: Personal information (name, bio, etc.) +- **skills**: Technical skills and proficiencies +- **social_links**: Social media and contact links +- **posts**: Blog posts +- **work_projects**: Portfolio work items + +### Demo Registry +- **demos**: Catalog of all live demos + - name, description, tech_stack + - repo_url, live_url + - thumbnail, category + - built_at, is_featured + +## Quick Start + +### Local Development + +1. **Copy environment file**: + ```bash + cp .env.example .env + ``` + +2. **Edit .env** with your values: + ```bash + # Generate secure keys + openssl rand -base64 32 # for DIRECTUS_KEY + openssl rand -base64 32 # for DIRECTUS_SECRET + ``` + +3. **Start services**: + ```bash + docker compose up -d + ``` + +4. **Access Directus**: + - URL: http://localhost:8055 + - Email: (from ADMIN_EMAIL in .env) + - Password: (from ADMIN_PASSWORD in .env) + +### Coolify Deployment + +1. **Create new resource** in Coolify + - Type: Docker Compose + - Source: Git repository (this repo) + +2. **Set environment variables** in Coolify: + - `DB_PASSWORD`: Secure database password + - `ADMIN_EMAIL`: Your admin email + - `ADMIN_PASSWORD`: Secure admin password + - `DIRECTUS_KEY`: Generated key + - `DIRECTUS_SECRET`: Generated secret + - `PUBLIC_URL`: `https://directus.b28.dev` + +3. **Configure domain**: + - Domain: `directus.b28.dev` + - Coolify handles SSL/TLS automatically + +4. **Deploy** + +## Database Setup + +The database is initialized from `database/init.sql` on first run. This includes: +- Schema definition (tables, relationships) +- Initial collections setup +- Sample data (optional) + +### Backup Database + +```bash +docker compose exec postgres pg_dump -U directus directus > backup_$(date +%Y%m%d).sql +``` + +### Restore Database + +```bash +docker compose exec -T postgres psql -U directus directus < backup.sql +``` + +## Adding New Collections + +1. Access Directus admin UI +2. Navigate to Settings → Data Model +3. Create new collection +4. Define fields and relationships +5. Set permissions + +Collections are stored in PostgreSQL and persist across restarts. + +## Connecting Demos + +Demo applications connect to this infrastructure via environment variable: + +```yaml +# In demo's docker-compose.yml +environment: + DIRECTUS_URL: https://directus.b28.dev +``` + +## API Access + +Directus provides a REST API at: +``` +https://directus.b28.dev/items/{collection} +``` + +Example endpoints: +- `GET /items/posts` - List all posts +- `GET /items/demos?filter[is_featured][_eq]=true` - Featured demos +- `GET /items/profile` - Profile data + +See [Directus API docs](https://docs.directus.io/reference/introduction.html) for full reference. + +## Maintenance + +### Update Directus + +```bash +docker compose pull directus +docker compose up -d directus +``` + +### View Logs + +```bash +docker compose logs -f directus +docker compose logs -f postgres +``` + +### Restart Services + +```bash +docker compose restart +``` + +## Security Notes + +- **Never commit .env files** - they contain secrets +- **Database backups may contain PII** - handle carefully +- **Use strong passwords** for admin and database +- **Rotate keys periodically** (DIRECTUS_KEY, DIRECTUS_SECRET) + +## Troubleshooting + +### Directus won't start + +```bash +# Check PostgreSQL is healthy +docker compose ps postgres + +# Check logs +docker compose logs directus + +# Verify environment variables +docker compose exec directus env | grep DB_ +``` + +### Can't access Directus UI + +1. Check service is running: `docker compose ps` +2. Verify health check: `docker compose exec directus wget -O- http://localhost:8055/server/health` +3. Check Coolify domain configuration + +### Database connection issues + +```bash +# Test PostgreSQL connection +docker compose exec postgres psql -U directus -d directus -c "SELECT 1;" + +# Check database exists +docker compose exec postgres psql -U directus -l +``` + +## License + +This infrastructure is for personal portfolio use. + +## Related Repositories + +- [demo-portfolio-site](../demos/portfolio-site) - Main portfolio website +- (Other demo repositories as they're created) diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..71c9620 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,89 @@ +# Portfolio Infrastructure - Directus CMS +# Shared infrastructure for all portfolio demos + +services: + # PostgreSQL Database for Directus + postgres: + image: postgres:15-alpine + restart: unless-stopped + + environment: + POSTGRES_DB: directus + POSTGRES_USER: ${DB_USER:-directus} + POSTGRES_PASSWORD: ${DB_PASSWORD} + + volumes: + - postgres_data:/var/lib/postgresql/data + - ./database/init.sql:/docker-entrypoint-initdb.d/init.sql:ro + + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-directus}"] + interval: 10s + timeout: 5s + retries: 5 + + networks: + - directus + + # Directus CMS + directus: + image: directus/directus:latest + restart: unless-stopped + + depends_on: + postgres: + condition: service_healthy + + environment: + # Database + DB_CLIENT: pg + DB_HOST: postgres + DB_PORT: 5432 + DB_DATABASE: directus + DB_USER: ${DB_USER:-directus} + DB_PASSWORD: ${DB_PASSWORD} + + # Admin account + ADMIN_EMAIL: ${ADMIN_EMAIL} + ADMIN_PASSWORD: ${ADMIN_PASSWORD} + + # Security + KEY: ${DIRECTUS_KEY} + SECRET: ${DIRECTUS_SECRET} + + # Public URL - update for your deployment + PUBLIC_URL: ${PUBLIC_URL:-http://localhost:8055} + + # CORS - allow all origins for demo purposes + CORS_ENABLED: "true" + CORS_ORIGIN: "true" + + volumes: + - directus_uploads:/directus/uploads + - directus_extensions:/directus/extensions + + expose: + - "8055" + + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:8055/server/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + networks: + - directus + +volumes: + postgres_data: + name: directus_postgres_data + directus_uploads: + name: directus_uploads + directus_extensions: + name: directus_extensions + +networks: + directus: + name: directus + external: false diff --git a/uploads/.gitkeep b/uploads/.gitkeep new file mode 100644 index 0000000..e69de29