paulserban.eu

Portfolio Edition

Paul Serban

AI & full-stack engineer · agentic platforms · distributed systems

← Back to portfolio

Featured

Local Traefik Dev Stack

Production-like HTTPS across four apps on one machine

Role: Solo builder

  • #astro
  • #docker
  • #mkcert
  • #traefik
  • #typescript

Problem

Four monorepo frontends each wanted their own dev port; cross-site navigation broke, and nothing matched the real production domain topology.

Approach

Traefik reverse proxy with mkcert TLS, per-app local.Dockerfiles, and env-driven cross-domain navigation that mirror the production subdomains one-for-one.

Outcome

One `docker compose up` boots the full system at local.*.paulserban.eu on ports 80/443.

apps
4
ports_exposed
80 + 443
cert_trust
mkcert
View code

Problem

prj--personal-portfolio--v3 ships four separate frontends - Astro portfolio, Astro blog, Astro news-feed, and a Vite/React quiz PWA - deployed in production as their own subdomains: paulserban.eu, blog.paulserban.eu, news-feed.paulserban.eu, and quiz.paulserban.eu. Run locally the plain way, each app instead gets its own dev port. That breaks in three concrete ways: the shared SiteSwitcher header links point at real production URLs even in dev, nothing exercises HTTPS the way the deployed sites do, and cross-domain behaviour - cookies, CORS, mixed content - simply doesn't exist when everything lives on localhost:PORT. Bugs that only show up once sites are split across real domains were invisible until deploy.

Approach

I treated local development like a miniature version of the production domain layout: Traefik terminates TLS on ports 80 and 443, redirects HTTP to HTTPS, and routes by Host header to the right container - so the local topology matches the production one subdomain-for-subdomain instead of port-for-port.

Browser ──► Traefik (:443, TLS) ──► portfolio (:4321)
              │                  ──► blog      (:4321)
              │                  ──► quiz      (:5180)
              │                  ──► news      (:4321)
              └── HTTP :80 -> HTTPS redirect

Why mimic production domains instead of just using ports

Running four apps on localhost:4321, :4322, :5180, etc. hides an entire class of bugs that only exist once sites are split across real, independent subdomains:

Matching the subdomain shape, not just the port numbers, means these issues get caught while iterating locally instead of after a deploy.

Outcome

A single docker compose up --build boots the full system. Developers hit real domain names on standard ports, cross-site navigation and HMR work the same way they will in production, and HTTPS behaviour matches production closely enough to catch mixed-content, cookie-scope, and CORS issues early. Setup guides for macOS and Debian live in _docs/infrastructure/.

Part of Personal Portfolio v3

This Traefik stack is the local-dev counterpart to the real domain layout of Personal Portfolio v3, a TypeScript pnpm monorepo that ships four frontends from one SQLite artifact. Related pieces of the platform: