Skip to content
Almanac

How to build a directory website with Astro, Cloudflare Workers, and D1

The full architecture behind this site — real full-text search, moderated submissions, an admin panel — on infrastructure that costs nothing until it grows.

By kpab

This site is a directory: a few hundred curated records, searchable, categorized, with public submissions and a moderation queue behind them. People ask how it is built, so this entry documents the architecture — and what it costs to run, which is the more interesting number.

The shape of the problem

A directory looks static but is not. It needs:

  • Search that actually works. Substring matching over titles stops being useful at about fifty entries. You want ranked full-text search over names, summaries, and tags.
  • A write path. Submissions arrive from strangers, which means spam protection, throttling, and a human approving every record.
  • An edit surface. Records rot. Somebody has to prune, re-categorize, and unpublish — comfortably, from a browser.
  • Speed everywhere else. The read path (browse, categories, detail pages) is 99% of traffic and should be served from the edge.

WordPress solves all four and costs you a VPS, a database server, and a lifetime of security updates. A static site generator solves only the last one. The middle path is what this site does.

The stack

Astro renders everything. Pages that never change between deploys — the blog you are reading, the about page — are prerendered at build time. Everything touching live data (browse, search, listing pages, the admin panel) is server-rendered on demand by the same codebase.

Cloudflare Workers runs that server code at the edge. There is no origin server, no container, no cold start worth mentioning.

Cloudflare D1 is the database — SQLite, replicated at Cloudflare’s edge. The killer feature for a directory is that D1 ships SQLite FTS5: real, bm25-ranked full-text search with prefix matching, as a SQL query. No Algolia subscription, no search microservice, no client-side index downloaded on every visit.

The search on this site is one prepared statement against an FTS5 table kept in sync by triggers. That is the entire search infrastructure.

The write path

Submissions go through three gates before a human ever sees them: a honeypot field, Cloudflare Turnstile, and a per-IP throttle backed by a small D1 table. What survives lands in a moderation queue inside the admin panel — approve, edit, or reject. The admin panel itself is server-rendered HTML forms with zero client-side JavaScript, locked behind a passphrase or Cloudflare Access SSO.

What it costs

Cloudflare’s free tier includes 100,000 Worker requests per day and a D1 allowance that a niche directory will not dent for a long time. This site’s bill so far: the domain name. That changes the economics of running a directory entirely — you can let one grow for a year before it owes you anything.

Build or buy

Everything above is buildable in a few focused weeks if you enjoy the plumbing. If you would rather start at the finish line: this site runs on Almanac, a commercial Astro theme that packages the whole architecture — search, submissions, moderation, admin panel, featured-slot monetization, three homepage layouts, and the docs to rebrand it for any niche.

It is $69 on Gumroad, and the demo you are evaluating is the site you are reading right now.

Buy this theme