Project case study
Personal Portfolio & CMS
A static portfolio site with a headless admin panel that commits content directly to Git via the GitHub API.
RoleFull-stack engineer
DateJune 2026
Problem
Most portfolio sites are either fully static with no editing UI, or they rely on an external CMS that adds a database, a paid subscription, and a new vendor to maintain. I wanted full ownership of the content, a clean editing experience, and no separate database.
Architecture
The project is a monorepo with three parts:
- Portfolio — a static Astro site. Content lives in
.mdxfiles undersrc/content/. Astro builds to pure HTML at deploy time. - Admin panel — a separate server-rendered Astro app (SSR on Vercel). Provides a web UI for editing and deleting content.
- Shared schemas — a local package with Zod schemas and MDX serializers consumed by both apps.
How the editing flow works
The admin panel has no database. Every save is a Git commit.
When an editor submits a form, the API route parses the frontmatter with Zod, serializes it back to MDX, and calls the GitHub Contents API (createOrUpdateFileContents). The file SHA is passed with every write request so two concurrent edits produce a 409 conflict rather than silently overwriting each other.
In local development, the GitHub layer is replaced by direct filesystem reads and writes, so editing works without any credentials.
Key choices
- MDX as the data layer — content has a full Git history, no database to manage, and is portable.
- Separate apps — the portfolio stays fully static. The admin’s SSR runtime never touches the public bundle.
- Shared schema package — the frontmatter shape is defined once. The portfolio validates it at build time; the admin validates it before every write. They can’t diverge.
- JWT session cookie — simple stateless auth with a rate-limited login. No OAuth dependency.
What I kept simple
The admin writes directly to the main branch. A more complete setup would write to a draft branch and open a pull request for review. That would also add a preview deploy step. For a solo portfolio, the added complexity wasn’t worth it.
Result
Editing a project or article takes about ten seconds. The change lands in Git with a clean commit message, and the site rebuilds automatically on Vercel. No CMS subscription, no external database, no vendor lock-in.