Personal portfolio and blog platform.
petterson.dev/
├── apps/
│ ├── portfolio/ # Next.js portfolio website
│ │ └── src/
│ │ ├── app/ # Pages
│ │ ├── components/ # UI components
│ │ ├── hooks/ # React hooks
│ │ └── lib/ # Utilities
│ │
│ └── blog/ # Payload CMS
│ └── src/
│ ├── collections/ # Content types
│ └── globals/ # Site settings
│
├── docker-compose.yml # Production
├── docker-compose.dev.yml # Development
└── Caddyfile # Reverse proxy
- Portfolio: Next.js 15, React 19, Tailwind CSS
- Blog: Payload CMS 3, PostgreSQL
- Proxy: Caddy (auto SSL)
cp .env.example .envdocker compose -f docker-compose.dev.yml up --build| Service | URL |
|---|---|
| Portfolio | http://localhost:3000 |
| Blog Admin | http://localhost:3001/admin |
Hot reload is enabled - changes to src/ are reflected immediately.
docker compose -f docker-compose.dev.yml downdocker compose up -d --build| Service | Container | Description |
|---|---|---|
| Caddy | caddy-proxy | Reverse proxy, SSL |
| Portfolio | petterson-portfolio | Main website |
| Blog | petterson-blog | Payload CMS |
| Database | petterson-db | PostgreSQL |
# Logs
docker compose logs -f
# Rebuild
docker compose up -d --build
# Stop
docker compose downPOSTGRES_USER=blog
POSTGRES_PASSWORD=your-password
POSTGRES_DB=blog
PAYLOAD_SECRET=your-secretGenerate secrets:
openssl rand -base64 32 # PAYLOAD_SECRET
openssl rand -base64 24 # POSTGRES_PASSWORD