portfolio CMS migration
<- back to stuff i built
publishing system

portfolio CMS migration

A rebuild from Hostinger custom HTML into this Astro + Keystatic portfolio, built so homepage edits are structured and publishing blogs does not feel like a chore.

bigrah-portfolioview repository ->

tldr

I moved the portfolio off Hostinger custom HTML because editing the homepage and shipping posts was too manual. The current setup keeps homepage and work content in typed data, gives me a custom Keystatic CMS for blog and note drafts, and deploys through GitHub Actions to Cloudflare Workers.

the problem

The Hostinger version looked fine, but the operating model was wrong. Homepage edits meant touching static HTML, project updates had to be copied into hand-built sections, and publishing a blog post required too much context switching. The site needed a calmer loop: edit structured content, preview locally, publish through a CMS when useful, and let checks handle the deploy.

what it is

A rebuild from Hostinger custom HTML into this Astro + Keystatic portfolio, built so homepage edits are structured and publishing blogs does not feel like a chore.

why it is useful

It turns the portfolio into a maintainable publishing system. Homepage and project edits are small data changes, blog and note posts can be drafted through the custom CMS, drafts stay out of public pages and RSS, and every change follows the same check-build-deploy path.

architecture

Astro owns the page structure and prerendered public routes. TypeScript data files drive homepage, work, contact, and project content. Markdoc content collections store blog posts and notes, while Keystatic provides the admin UI with local editing in development and GitHub-backed storage in production. GitHub Actions runs the checks and build on main, then deploys the Cloudflare Worker. The build also emits RSS, sitemap files, llms.txt, and noindex Markdown twins for text-first clients and agents.

how it works

  1. Homepage, work, contact, and project sections live in typed data files instead of repeated Hostinger HTML blocks.
  2. Astro components render that data into the notes-style interface, so layout changes and content edits stay separate.
  3. Blog posts and notes can be written in the custom Keystatic CMS with title, slug, description, date, tags, SEO fields, cover image, and draft status.
  4. The CMS saves content as Markdoc files in the repo, so agents can still edit the same source when that is faster.
  5. Published entries feed the blog, notes, RSS, related-post logic, Markdown twins, and llms.txt index automatically.
  6. GitHub Actions runs check and build on main, then deploys the Cloudflare Worker without a manual Hostinger upload step.

implementation notes

  • Moved from hand-edited Hostinger HTML into a code-owned Astro repository.
  • Created structured data for navigation, roles, contacts, project tiles, and project detail pages.
  • Configured Keystatic for Blog posts and Notes, with local storage in development and GitHub storage in production.
  • Draft content is excluded from public pages, RSS, related posts, and generated static paths.
  • Generated canonical HTML pages plus Markdown twins marked noindex to avoid duplicate search results.
  • Kept old essay URLs as redirects while moving the site to the new route structure.
  • Cloudflare Workers serves the site, and GitHub Actions handles checks, builds, and deployment from main.

engineering decisions

  • Kept the old notes-app feeling from the Hostinger site instead of flattening it into a generic portfolio template.
  • Separated homepage content from presentation so changing a role, metric, project, or contact link does not mean editing markup.
  • Made the CMS serve the writing workflow while the homepage stays custom-coded and expressive.
  • Added an agent-readable layer because coding agents help maintain the site and need clean Markdown context.

stack

AstroTypeScriptKeystaticMarkdocAstro content collectionsCloudflare WorkersGitHub Actions