Personal site for dbtlr.com — a calm, typography-led dark-mode portfolio and blog. Built as a fully static site with Astro 6 and Tailwind 4, deployed to Cloudflare Workers static assets.
No client framework ships: the only browser JS is a ⌘K search palette and code-copy
buttons (src/scripts/). Code blocks are highlighted at build time with Shiki using a
custom theme mapped to the design tokens.
- Node 24
- pnpm (the package manager — never npm; pinned via
packageManagerinpackage.json)
pnpm install
pnpm dev # local dev server with HMR
pnpm build # static build to ./dist
pnpm preview # serve the built ./dist locally
pnpm check # astro check (type checking)Work happens on feature branches and lands through pull requests:
feature branch → PR to main → preview deploy → merge to main → production
- PR previews (
.github/workflows/preview.yml): every PR againstmainrunspnpm check+pnpm build, thenwrangler versions uploadpublishes an ephemeral version of thedbtlr-comWorker without touching production. The preview URL is posted (and kept updated) as a comment on the PR. - Production (
.github/workflows/deploy.yml): pushing tomainruns the same checks andwrangler deploy, publishing thedbtlr-comWorker that serves dbtlr.com.
Both workflows use Node 24 + pnpm and require CLOUDFLARE_API_TOKEN and
CLOUDFLARE_ACCOUNT_ID repository secrets.
Run before pushing — these are exactly what CI runs:
pnpm check && pnpm buildastro.config.mjs Astro config — Shiki theme + code-block chrome transformer
wrangler.jsonc Cloudflare Worker (static assets from ./dist)
src/
pages/ routes — home, about, projects, writing, feed.xml, search.json, 404
layouts/Base.astro shared page shell
components/ SectionHead, PostRow
content/ Markdown content collections (projects/ populated; writing/ pending)
content.config.ts collection schemas (zod) — writing + projects
scripts/ vanilla JS — search.js (⌘K palette), copy.js (code copy)
styles/global.css Tailwind 4 theme tokens + component CSS
.github/workflows/ deploy.yml (production), preview.yml (PR previews)