alex.bularca.me — personal dev blog (Astro, Cloudflare Workers static assets, Forgejo Actions)
  • TypeScript 49.2%
  • Astro 32.4%
  • JavaScript 9.5%
  • CSS 8.9%
Find a file
Alex Bularca 8e5e02ed71
All checks were successful
deploy / deploy (push) Successful in 58s
chore(analytics): null-guard consent buttons
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-13 11:27:03 +03:00
.forgejo/workflows fix(ci): smoke test must not close the pipe early (grep -q EPIPE) 2026-09-11 17:14:22 +03:00
public chore(analytics): null-guard consent buttons 2026-09-13 11:27:03 +03:00
src feat(analytics): opt-in consent card; GA4 loads only after consent; honour GPC/DNT 2026-09-13 11:21:13 +03:00
.gitignore chore: scaffold Astro 7 project with pinned toolchain 2026-09-11 14:33:20 +03:00
.nvmrc chore: scaffold Astro 7 project with pinned toolchain 2026-09-11 14:33:20 +03:00
.prettierignore chore: scaffold Astro 7 project with pinned toolchain 2026-09-11 14:33:20 +03:00
.prettierrc chore: scaffold Astro 7 project with pinned toolchain 2026-09-11 14:33:20 +03:00
astro.config.mjs feat(seo): sitemap lastmod from post dates 2026-09-11 17:04:02 +03:00
lighthouserc.cjs chore(content): drop hello-world placeholder; figures fit the text column; Lighthouse picks the first built post 2026-09-11 16:14:47 +03:00
package-lock.json feat(seo): JSON-LD for site, person and posts; richer titles and article meta 2026-09-11 16:57:09 +03:00
package.json feat(seo): JSON-LD for site, person and posts; richer titles and article meta 2026-09-11 16:57:09 +03:00
README.md feat(analytics): opt-in consent card; GA4 loads only after consent; honour GPC/DNT 2026-09-13 11:21:13 +03:00
renovate.json ci: preview and deploy workflows, renovate config 2026-09-11 15:27:31 +03:00
tsconfig.json chore: scaffold Astro 7 project with pinned toolchain 2026-09-11 14:33:20 +03:00
vitest.config.ts chore: scaffold Astro 7 project with pinned toolchain 2026-09-11 14:33:20 +03:00
wrangler.jsonc feat: wrangler static-assets config and response headers 2026-09-11 15:10:09 +03:00

alex.bularca.me

Personal dev blog. Astro static site deployed to Cloudflare Workers static assets by Forgejo Actions. Design spec lives in personal-infra/docs/superpowers/specs/2026-09-11-dev-blog-design.md.

Writing a post

  1. Create src/content/posts/YYYY-MM-DD-my-slug.md with frontmatter: title, date, description, tags (optional), draft (optional, default false).
  2. Commit on a branch, open a PR. CI posts a preview URL that includes drafts.
  3. Merge to master. CI deploys to https://alex.bularca.me (drafts excluded).

No local tooling is required to publish. For live preview: npm ci && npm run dev.

Scripts

npm run build · npm run build:preview (includes drafts) · npm run check · npm test · npm run format:check · npm run lint:links · npm run lint:perf · npm run preview (real Worker locally)

Secrets (Forgejo → Settings → Actions → Secrets)

Name Source of truth
CLOUDFLARE_API_TOKEN Vault (rivendell) secret/cloudflare/blog-deploy key api-token
CLOUDFLARE_ACCOUNT_ID Vault (rivendell) secret/cloudflare/blog-deploy key account-id

Nothing else reads them. To rebuild: read from Vault, paste into Forgejo repo secrets.

Gotchas

  • Node 22 is required (system Node 23 fails Vitest's engine check); CI runs Node 22.
  • Do not remove vite.build.assetsInlineLimit: 0 in astro.config.mjs — inlined component scripts are blocked by the CSP (script-src 'self') and the theme toggle/contents rail silently stop working.
  • Astro 7 strips newline whitespace between an expression and a sibling element; write {' '} where a visible space is needed.
  • Analytics: GA4 loads only after opt-in via the consent card (public/ga.js + ConsentBanner.astro); choice stored in localStorage analytics-consent; footer 'cookies' link resets it; GPC/DNT browsers are never asked and never tracked.