Server Architecture
Both anthonymicallef.ca and antonretro.com run from a single server on DigitalOcean. A custom nginx configuration routes incoming requests to the correct application based on the domain, while a single Next.js deployment handles rendering for both sites.
The stack is intentionally minimal. A single 2GB DigitalOcean Droplet running Ubuntu hosts nginx, Node.js, WordPress (via PHP-FPM and MariaDB), and the Next.js application managed by PM2 in cluster mode with two instances. For a solo developer, the operational overhead of a microservices approach or a managed container platform is not justified.
- nginx as the reverse proxy: routes anthonymicallef.ca and antonretro.com to the same Next.js port with different middleware paths, and CMS admin routes to WordPress via PHP-FPM
- PM2 in cluster mode (2 instances): auto-restart on crash, memory ceiling of 512MB per process, log rotation, and startup script registration so processes survive server reboots
- WordPress on a staging subdomain with the REST API exposed for headless consumption by Next.js
- MariaDB for WordPress data, configured for the read-heavy CMS workload
- Redis on-server for WordPress REST API response caching, reducing repeat database queries
- DigitalOcean Spaces as the media CDN, keeping binary assets off the Droplet entirely
Deploy Pipeline
The deploy is a PowerShell script that runs locally and handles the full release cycle: building the Next.js app, creating a tarball of the build output, uploading to the server via SCP, extracting the archive, running dependency installs if the package lock changed, and restarting PM2. A typical code-only deploy completes in under 30 seconds using the -Quick -SkipPublic flags.
The decision to keep the deploy as a local script rather than a CI/CD pipeline was deliberate. CI/CD introduces a pipeline to maintain, credentials to manage in a third-party system, and a layer of abstraction between the developer and what is actually happening on the server. For a solo operator, a transparent local script is faster to iterate on and requires no external services.
Multi-Domain Routing
Next.js middleware (proxy.ts) inspects the incoming Host header on every request and rewrites paths based on domain context. The portfolio site and the Anton Retro site share a single codebase, a single build, and a single running process while delivering entirely different UI themes and content.
Tradeoffs
Running two production sites from one process means a deployment that breaks Next.js takes both sites offline simultaneously. The mitigation is a fast deploy pipeline with a tested rollback procedure: keeping the previous build on the server so a rollback is a single PM2 restart command. The simplicity of the architecture makes debugging fast enough that this tradeoff is acceptable.