How This Site Is Built
A static site with a headless CMS backend, an auto-rebuild pipeline, and no hosting fees beyond a single VPS.
Most personal sites are either fully static with no CMS, or they run a database-backed monolith like WordPress. This site takes a middle path: a headless CMS for content management and a fully static frontend that gets rebuilt automatically whenever something is published.
The Stack
The backend is Strapi v5, an open-source headless CMS running on a self-hosted VPS managed by PM2. All content — blog posts, projects, resume data — lives in Strapi and is exposed via a REST API. The frontend is Next.js 15 with output: 'export', which means the entire site is pre-rendered to plain HTML, CSS, and JavaScript at build time. There is no Node.js server running in production. Nginx serves the static files directly.
The Auto-Rebuild Pipeline
The interesting part is how content changes reach the live site. Strapi supports outbound webhooks that fire on publish events. A small Node.js webhook server listens for those events and does four things in sequence:
- Copies the latest uploaded media from Strapi into the frontend's public directory
- Clears the Next.js fetch cache
- Runs npm run build to regenerate all static pages with fresh content
- SCPs the output directory to the web server
The entire pipeline takes about 10–15 seconds from hitting Publish in Strapi to the live site updating.
Why Static Export
A static site has no attack surface beyond what Nginx exposes, scales trivially, and survives traffic spikes without breaking a sweat. The tradeoff is that content changes require a rebuild — acceptable for a personal site where real-time updates aren't needed.