← Back to Projects

leptons1618@anishgiri.dev:~/projects/portfolio cat project.toml

Full-Stack 2026 Active development

Portfolio

Personal portfolio site for projects, case studies, and journal posts with a browser-based admin surface and AI authoring assistant. Content lives in Cloudflare D1, so publishing is a save rather than a commit.

category
Full-Stack
year
2026
status
Active development
stack
6 tools
highlights
5
write-up
5 min read

01Highlights

  1. 21 of 27 routes render per-request against D1 with no build step on content changes.
  2. Content stored as markdown with HTML derived on write, so nothing renders markdown per request.
  3. GitHub OAuth handled by a separate stateless Worker, keeping the token exchange isolated from the main site.
  4. Five automated checks gate the CI pipeline, covering type safety, content routing, schema trust boundaries, AI feature security, and OAuth token exchange.
  5. The admin assistant filters hidden and unpublished content from its corpus regardless of what the caller passes in.

02Built with

  • 01Astro
  • 02TypeScript
  • 03CSS
  • 04JavaScript
  • 05Cloudflare Workers
  • 06Cloudflare D1

03Case study

September 4, 2026 5 min read 876 words

Portfolio — A Site Where Publishing Is a Database Write

Content as rows instead of files, which makes publishing a save — and makes the write endpoint the most security-sensitive file in the repository.

The problem

The obvious architecture for a content site is markdown files and a deploy. It works until you want to fix a typo from a phone, reorder what leads the home page, or keep a draft only you can see — at which point every small edit means pushing to main and waiting on a build to check a sentence. Moving content into a database removes the waiting, but it also makes a single HTTP endpoint the trust boundary for the entire site, and that endpoint has to be the only path in.

The solution

Store every project, case study and post as a row in Cloudflare D1, rendered per request, with markdown converted to HTML on write so a page view is a read and nothing more. Funnel every write through one endpoint whose column identifiers all come from a source-defined allowlist, because a table or column name cannot be a bound parameter in SQL and a column that gets dropped silently is a save that reports success and loses work.

Outcomes

  • The project frontmatter form carries a completeness checklist with real thresholds — summary length, tag and stack counts, highlight counts, a repository link — and a live preview built from the same classes the real card uses.
  • AI edits are reviewed per field with individual Keep and Revert, and any manual edit to a marked field clears the mark.
  • Database constraint failures are translated into sentences naming the field and what to do, instead of surfacing raw SQL error text.

+3 more in the write-up

Inside the write-up

  1. A portfolio is a blog with worse defaults
  2. The part that turned out to be the actual work
  3. Markdown in, HTML already made
  4. Rows are read back in the shape they are written
  5. The admin knows what a good project page looks like
  6. Where the secrets are not
Read the full case study →