dignuz

AmplyDigest

The newsletters and video channels you follow, summarised in one morning email.

You forward your newsletters to one address, and add the YouTube channels you follow. Every morning one email arrives with all of it summarised. I built it, and I run it.

01

How it's built

  • TypeScript
  • Turborepo
  • pnpm
  • Cloudflare Workers
  • Hono
  • Zod
  • Cloudflare D1
  • Drizzle ORM
  • R2
  • KV
  • Cloudflare Queues
  • Cron Triggers
  • Cloudflare Email Routing
  • postal-mime
  • Workers AI
  • YouTube Data API
  • Vercel AI SDK
  • Astro 5
  • Svelte 5
  • Tailwind 4
  • DaisyUI 5
  • Bits UI
  • Better Auth
  • Polar
  • Maileroo
  • Vitest
  • ESLint
  • Prettier
  • Husky
  • GitHub Actions

AmplyDigest is a full application, not a website: over 100,000 lines of code, and as many again in its own documentation.

  • Architecture: a Turborepo monorepo on pnpm workspaces, with two apps and one shared package of Zod contracts. The website works as a backend-for-frontend (BFF): the browser only ever talks to it, and it calls the API with a shared secret. The API is organised in vertical slices, one folder per feature and operation, with classes wired by constructor dependency injection, and every database query scoped to the signed-in user.
  • The API: TypeScript on Cloudflare Workers, with Hono. Requests are validated with Zod before they reach a handler.
  • Data: Cloudflare D1 (SQLite) through Drizzle ORM, with every schema change kept as a versioned migration. The original emails in R2. Cache and rate limits in KV.
  • Background work: Cloudflare Queues for every slow step, retrying what fails, with dead-letter queues for building and sending the digest. Cron Triggers run the daily digest, the clean-up, and recovery jobs that pick up anything that stalled.
  • Email in: Cloudflare Email Routing delivers newsletters straight into the Worker, with no mail server. The message is parsed with postal-mime, forwarded mail is traced back to its original sender, and Workers AI turns the HTML into Markdown.
  • Video: channels are found and followed through the YouTube Data API and the channels' own feeds.
  • The AI: summaries are written through the Vercel AI SDK, over a list of AI providers set in configuration. The list can be reordered or changed at any time, depending on how each provider behaves and the results it gives, without touching the code. Every AI call is metered against the account's plan.
  • The website: Astro 5, rendered on the server on Cloudflare, with Svelte 5, Tailwind 4, DaisyUI 5 and Bits UI.
  • Accounts, payments, mail out: passwordless sign-in by emailed link through Better Auth, rate-limited per address. Payments through Polar: checkout, the customer portal, and webhooks reconciled against the real state. The morning email goes out through Maileroo.
  • Quality: Vitest unit and integration tests, the integration tests running against a real SQLite database. ESLint, Prettier, and pre-commit hooks with Husky.
  • Shipping: GitHub Actions, with separate staging and production. Each deploy type-checks, lints and tests, applies the D1 migrations, deploys the API, checks its health, deploys the website, and checks again.

02

The trade-off

Nearly all of it runs on Cloudflare: the code, the database, the queues, the file storage and the cache. It is built to use what that platform does well, not to be portable. An app like this is made for the infrastructure it runs on, and it is not meant to move. For one person, that means one platform to deploy to and one place to look when something breaks.

Want something like this, built around how your business works?