Skip to content

Building CashewMade.com

🌍 Context

Personal sites are common. Useful personal sites are rarer.

A one-page portfolio flattens everything into a highlights reel. A blog without structure turns into a content dump. Neither was what I wanted. What I wanted was a site that could hold serious project write-ups, rougher lab notes, and practical documentation for friends using the services I host — all without making any of those audiences wade through content that is not for them.

TL;DR

I built this as a lightweight publishing system for project write-ups, notes, and docs. Most of what lives here is text. The goal was to keep it structured, easy to maintain, and simple without losing the parts that matter.

👥 Audiences

These audiences are all reading the same site, and they want different things:

  • Engineers — implementation detail, what actually broke, and what I would change
  • Hiring managers — how I think through architecture, decisions, and trade-offs
  • Hobbyists — practical ideas they can reuse without needing the full backstory
  • Users on hosted services — clear instructions and troubleshooting, not an accidental lecture

Why one site?

I am one person, and these pages are really different angles of the same story. One structured site made more sense than splitting into separate places and making people piece me back together.

⛳ Constraints

A few requirements shaped decisions early:

  • I maintain this alone — operational overhead needs to stay low
  • The content is text-heavy: documents, notes, write-ups — not a web application
  • Hosting should be cheap and not require babysitting
  • New pages should fit the system without forcing a structural redesign every few months

The goal was a design that is deliberate where it matters, boring everywhere else, and easy to keep moving without adding unnecessary complexity. The easier it is, the more likely it keeps getting used.


⚙️ Technical Architecture

☁️ Stack

This site does not need user accounts, server-rendered state, a writable database, or a live backend. The value is not in the features but in the content and structure — a static architecture is the right fit.

  • Zensical: Documentation-style static site framework
  • Cloudflare Workers: Edge delivery for static assets and Worker runtime
  • GitHub: Source control and CI/CD trigger

Zensical

Zensical is a documentation-oriented static site framework — the successor to MkDocs Material — that gives you strong navigation and content-structure defaults without requiring you to build any of that from scratch.

It fits this site because the content behaves like documentation: it is hierarchical, navigation-heavy, and needs structure more than rich interactivity. The source stays as plain Markdown files in Git — portable, reviewable, and not coupled to any editor or publishing tool. It also has Google Analytics integration.

About MkDocs Material

MkDocs Material entered maintenance mode in November 2025, committing to critical bug and security fixes for 12 months but no active development. For a new site that needs to stay low-maintenance long-term, Zensical was the better bet.

Cloudflare Workers

Cloudflare Workers handles delivery. The choice was mostly about operational fit:

Compare to GitHub Pages

GitHub Pages was the obvious alternative — simpler and well-understood. I chose Workers because the domain was already on Cloudflare, Cloudflare's edge network has better global performance and uptime than GitHub's CDN, the branch preview workflow is tighter, and the platform leaves room for lightweight edge logic later without migrating the delivery model. For someone starting from scratch, GitHub Pages would be the faster path.

🔄 Deployment Flow

The deployment flow is a lightweight CI/CD pipeline with no manual steps after a push:

  1. Edit Markdown or config locally
  2. Preview with the repo scripts
  3. Push to GitHub
  4. GitHub triggers a Cloudflare build through Git integration
  5. Cloudflare deploys the Worker and static assets
  6. The production branch updates the live domain; other branches get preview URLs
sequenceDiagram
    participant Author
    participant GitHub
    participant Cloudflare

    Author->>Author: Edit Markdown
    Author->>Author: Preview locally
    Author->>GitHub: Push changes
    GitHub->>Cloudflare: Trigger build
    Cloudflare->>Cloudflare: Deploy Worker
    Cloudflare-->>Author: Production site or preview URL

Not using the homelab?

I like self-hosting, but a personal website depending on whether I am debugging the rack at 1 a.m. is a fun way to build character, not reliability. Managed delivery was the right call here.


🗂️ Content Structure

Three-Level Hierarchy

The site uses a three-level model: Tab → Section → Page.

Level Purpose
Tab Separates broad content domains — sets audience expectations before a page loads
Section Groups related material within a tab — keeps navigation manageable as content grows
Page Delivers the actual write-up, note, or guide

The tab level is where audience separation happens. Someone opening Projects is looking for architecture decisions. Someone opening Services wants instructions. That framing is established immediately, before they reach any content.

Why three levels and not two?

Two levels would work today. The section layer is there because content within a tab needs grouping as volume grows — without it, the Lab tab in particular would collapse into an unnavigable flat list. Section structure is cheap to add early and painful to retrofit later. Three levels holds up at ten times the content.

Tabs

Tab What lives here
Projects Architecture write-ups, decision-driven project pages
Lab Experiments, setup notes, rougher technical work
Services End-user documentation for hosted services
Blog Time-based or article-style writing

✅ Design Strengths

  • Decoupled content and delivery — No CMS state to sync, no database to back up. Plain files build to standard static assets; every change is a diff, every version is recoverable from Git, not tied to any delivery platform.
  • Structure scales ahead of content — The three-level hierarchy costs almost nothing today and avoids a painful retrofit later. New pages slot into existing sections without touching navigation.
  • Publishing loop stays out of the way — Markdown, push to Git, live in under two minutes. Lower friction means the system actually keeps getting used.
  • Platform leaves room to grow — Cloudflare Workers is an edge compute platform, not just a CDN. Redirects, dynamic OG images, auth, and Worker-backed search are all addable without changing the delivery model.
  • Failure scope is bounded — No runtime to crash, no database to corrupt, no background jobs to wedge. What can go wrong is mostly Cloudflare availability — acceptable for a personal site with no SLA.

🧭 Decision Log

Decision Alternatives considered Why this won
One site, not several Separate portfolio, blog, and service docs sites The content is related and the audiences overlap. Three half-maintained sites is worse than one structured one.
Static site Dynamic web app, CMS (WordPress, Ghost, Notion) The value is in content and structure, not runtime behavior. No accounts, no write operations, no need for a server tier.
Docs framework (Zensical) Custom stack, raw MkDocs Strong navigation and structure defaults without becoming the project itself. MkDocs Material's maintenance-mode status closed that door.
Cloudflare Workers GitHub Pages, Netlify Domain already on Cloudflare. Tighter preview workflow. Platform headroom for edge logic without migrating delivery later.
Git-based publishing Manual uploads, CMS editor Versioned changes are easier to test, review, and roll back. The repository stays the source of truth.

⚖️ Trade-offs

Dynamic features require deliberate add-ons. There is no server-side search, no real-time updates, no authenticated views out of the box. Adding any of those means layering a Worker function or an external service on top of the static model. The platform supports it — none of those features currently justify the complexity.

The workflow requires Git and Markdown. There is no CMS interface, no rich text editor, no way to publish without knowing both. Acceptable for a solo site; would break down immediately if a non-technical contributor needed to publish pages.

Cloudflare is a single point of control. DNS, domain registration, build pipeline, and CDN all run through one provider. Convenient, but an outage or policy change hits everything at once. For a personal site with no SLA that is a fine risk to accept — for a revenue-critical property, it would not be.

Build time grows with content. The current setup rebuilds the full site on every push. Builds are fast now, but there is no incremental step to fall back on as the page count grows.

Where this design breaks down

At team scale, or with contributors who are not comfortable in Git, the workflow becomes a bottleneck. A CMS layer or a web-based editor would be needed before this could be handed off to anyone else.


📈 Outcome

The structural choices have held up without requiring rework:

  • The tab model has absorbed new content across different types without navigation changes
  • Branch previews have caught layout issues before they reached production
  • The publishing loop is fast enough that a typo fix is live in under two minutes
  • The section layer has stayed legible as the page count has grown

The clearest signal

The system keeps getting used. Most personal projects get abandoned when the maintenance overhead outgrows the motivation. This one has not.

💭 Reflections

I designed the structure before writing a real page — tabs, sections, naming conventions. Knowing where a new page belongs before it exists has made adding content easier, and the model has not needed rework as the site has grown. There is a real argument for doing it the other way — start with a flat pile of content, find the groupings, then formalize — but I preferred to make those decisions once rather than mid-flight.

One thing I would revisit: user feedback

I implemented comments through Giscus, which maps discussions to GitHub Discussions. It works well technically, but requires a GitHub account and a third-party app authorization — a barrier that quietly excludes non-technical visitors. It is a known compromise.

What comes next:

Redirects, dynamic OG image generation, Worker-backed search, and lightweight auth for private pages are all on the table. None are on the roadmap yet — but the architecture is ready when they are.

Comments