Loomwork: The Framework That Builds Everything
Every site in this portfolio - including the one you’re reading - runs on Loomwork. I built it after scaffolding the same Astro project one too many times.
The Problem
I kept building sites. Johnny Solarseed, FlashMAWB, OpenBaseline, this portfolio - each one started the same way: scaffold Astro, set up content collections, configure Cloudflare, build a header and footer, write the same CSS reset, wire the same dark-mode toggle.
After the fourth time the pattern was obvious. What I wanted wasn’t an abstraction exercise, it was an extraction: take the pieces identical across every site and make them a living upstream I can pull from with git merge loomwork/main, not a starter template I copy once and forget.
What I Built
An open-source Astro publishing framework. Content collections with typed schemas, ten built-in themes with dark mode, five page templates, a mobile PWA editor, and zero-config Cloudflare deployment. Fork the repo, edit one config file, push to GitHub, and the site is live in about 30 seconds.
The core decision is a clean split between framework files and site files. Framework files (layouts, components, global CSS, content schemas) are maintained upstream and merge cleanly because you never edit them. Site files (config, site.css, homepage, header, footer, content) are yours, and upstream never touches them. Pulling a framework update into a running site is one command, not an afternoon of conflict resolution. That is the difference between a framework and a starter you forked once and can never update.
Ten themes, each a standalone CSS file that sets custom properties on :root, no PostCSS and no Sass and no compile step. Switch by changing one string in the config. Five templates (Default, Landing, Guide, Tool, Longform) selected from frontmatter. A floating reader-controls panel gives visitors dark mode, font size, content width, table-of-contents style, and zen mode, all persisted in localStorage. And a PWA editor at /mobile that reads and writes MDX through the GitHub REST API from your phone, with credentials encrypted at rest via AES-GCM.
Tech Stack
- TypeScript
- Astro 5
- MDX
- React
- IndexedDB (offline drafts)
- localStorage (reader preferences)
- Cloudflare Pages
- GitHub REST API
- Zod (schema validation)
- DOMPurify (XSS)
- Web Crypto API (PBKDF2 + AES-GCM)
How It Works
The CSS cascade is deliberate. global.css sets defaults at :where(:root) (zero specificity), theme CSS loads at normal :root, and site.css loads last and wins by source order, so a site author can override anything without fighting specificity.
Theme loading uses an inline document.write() in <head>: a script reads the saved theme from localStorage, resolves the file from a registry baked into the page, and emits the <link> synchronously. The browser treats that output as render-blocking, so the page never paints with the wrong theme, not even briefly, with a <noscript> fallback for JS-disabled users.
Content is Zod-validated. The build fails if frontmatter doesn’t match the schema, so broken metadata never ships to production.
What Made It Hard
Getting the framework/site split clean enough that upstream merges never conflict. Guaranteeing zero flash of the wrong theme without a build step. And passing a full security audit on a tool that stores GitHub credentials in the browser and loads user-supplied theme and font URLs - sixteen of eighteen findings resolved, zero critical or high remaining.
The Throughline
Loomwork is the layer underneath everything else here. Every site I build exercises it, and every pain point feeds back in - the theme-switching bug I hit on this very portfolio became a framework fix. It is the clearest example of a solo engineer shipping and maintaining a real open-source tool by building it for actual use, not hypothetical users.
Status
Active and in production. Loomwork 2.1 powers every site in this portfolio plus external sites on the framework. The mobile editor is temporarily disabled while security hardening wraps up; all code-level fixes are complete and re-enabling is the next step. Near-term roadmap: Playwright E2E tests, GitHub Actions CI, visual regression testing. The repo, a demo site, and a verification site are all live.