Skip to content

brucehart/bhart-org

Repository files navigation

bhart-org

A Cloudflare Workers + D1 powered blog with Mustache templates, Markdown content, Google OAuth admin, and R2 media storage.

Features

  • Public pages: home, about, projects, news, work-with-me, contact, archive, and article detail pages.
  • Admin area: Google OAuth login, post/news create/edit/delete, tags, drafts, featured images, and scheduling.
  • Sprite-backed Codex article and news drafting from /admin/draft-article.
  • Markdown articles rendered server-side with RSS feed support.
  • Media library backed by R2 with metadata stored in D1.

Requirements

  • Node.js + npm
  • Cloudflare Wrangler CLI
  • Cloudflare account with Workers, D1, and R2 enabled

Local Development

Install dependencies:

npm install

Run the dev server:

npm run dev

Configuration

Wrangler

The Worker is configured in wrangler.jsonc with D1 and R2 bindings.

OAuth

Set the Google OAuth credentials:

wrangler secret put GOOGLE_CLIENT_ID
wrangler secret put GOOGLE_CLIENT_SECRET

If you need a fixed redirect URL (custom domain), set:

wrangler secret put GOOGLE_OAUTH_REDIRECT_URI

Authorized redirect URI examples:

  • https://<your-worker>.workers.dev/admin/callback
  • http://localhost:8787/admin/callback

Database

Apply migrations:

wrangler d1 migrations apply bhart-org

Seed an authorized admin user (replace values as needed):

wrangler d1 execute bhart-org --command "INSERT INTO authorized_users (id, email, name, is_active, created_at) VALUES ('<uuid>', 'you@example.com', 'Your Name', 1, '2024-01-01T00:00:00.000Z');"

R2

Create the media bucket if it does not exist:

wrangler r2 bucket create bhart-org

Images uploaded in the admin are stored in R2 and indexed in D1.

Codex Content Drafting

The admin drafting workspace at /admin/draft-article launches Codex inside a Fly.io Sprite and submits drafts through the existing Blog Automation API. Article mode uses /api/codex/v1/posts; news mode uses /api/codex/v1/news.

Required Worker secrets:

wrangler secret put CODEX_API_TOKEN
wrangler secret put SPRITES_API_TOKEN
wrangler secret put BHART_ARTICLE_AGENT_ALLOWED_EMAILS

Optional Worker vars are set in wrangler.jsonc:

  • BHART_ARTICLE_AGENT_SPRITE_NAME defaults to bhart-org
  • BHART_ARTICLE_AGENT_SPRITE_WORKDIR defaults to /home/sprite/bhart-org/main
  • BHART_ARTICLE_AGENT_CODEX_HOME defaults to /home/sprite/.codex-bhart-org
  • BHART_ARTICLE_AGENT_SPRITES_API_BASE defaults to https://api.sprites.dev

The Sprite needs the repo, dependencies, project-specific Codex auth at /home/sprite/.codex-bhart-org/auth.json, and /home/sprite/.config/secrets/codex.env containing CODEX_BHART_API_TOKEN and BHART_CODEX_API_BASE=https://bhart.org/api/codex/v1. Do not copy auth.json from another Sprite or project; create a fresh login inside this Sprite with mkdir -p /home/sprite/.codex-bhart-org && CODEX_HOME=/home/sprite/.codex-bhart-org codex login --device-auth.

Routes

  • / home page
  • /about about page
  • /projects projects page
  • /news news page
  • /work-with-me services page
  • /contact contact page
  • /archive archive page
  • /articles/:slug article page
  • /rss.xml RSS feed
  • /admin post list (requires login)
  • /admin/posts/new new post
  • /admin/posts/:id edit post
  • /admin/news/new new news item
  • /admin/news/:id edit news item
  • /admin/media media library
  • /admin/draft-article Sprite-backed Codex article/news draft workspace
  • /media/<key> media asset delivery (public)

Notes

  • The media list is sourced from D1. Existing objects in R2 are not shown until uploaded through the admin.
  • Images are served via /media/... and cached with long-lived headers.

Deploy

wrangler deploy

About

Personal blog built on top of Cloudflare Workers

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors