The weekly digest
What the newsletter contains, what it will never contain, and the exact file an issue is.
A weekly summary of what entered the catalogue and what closes next. Every issue is also a page at /newsletter, permanently.
Subscribing
One address, no account, no card. Every message carries an unsubscribe link that works without signing in.
If what you want is narrower than everything — one applicant type, one state, one field — that is an alert rather than the digest, and it reports what changed rather than what exists.
What an issue may contain
Three rules, and they are enforced by the file format rather than by whoever writes the issue.
Every entry names a record. Each item carries the slug of a record in the catalogue and renders as a link to it. An issue cannot carry an opportunity you are unable to open, which is what keeps it a summary of the data rather than editorial copy about the sector.
Every figure carries the date it was taken. An issue is a photograph of a catalogue that moves. The counts in it describe the day they were counted, and the page says which day rather than recomputing them when you open it — a page that recomputed would silently rewrite an old issue every time someone read it.
Absence stays absence. A deadline or a ceiling the source did not publish renders as Not stated, not as a blank cell. A blank in an email is read as a zero exactly as a blank in a table is. See reading provenance.
Nothing in an issue is sponsored, paid for, or placed.
The file an issue is
An issue is one file in content/newsletter/, validated by the newsletter
collection in source.config.ts. That schema is the contract between whatever
generates a digest and the pages that render it; changing the shape means
changing it there, where both halves can see it.
---
issue: 1 # monotonic integer; the URL is the date, not this
date: "2026-09-12" # the day the issue covers up to, and its slug
windowDays: 7 # how far back the issue looks
dataAsOf: "2026-09-12" # when the counts were taken
title: "Issue 001"
description: "One quotable sentence about this issue."
counts:
newlyAdded: 0 # records linked inside the window
closingSoon: 0 # records closing inside the window
catalogueTotal: 0 # records in the catalogue on dataAsOf
sections:
- heading: "Newly added"
items:
- slug: "2026-dairy-plus-program" # must resolve to /grants/<slug>
title: "2026 Dairy Plus Program"
funder: "California Department of Food and Agriculture"
deadline: "2026-11-01" # ISO date, or null
amountMax: 1250000 # whole dollars, or null
note: "Ceiling qualified per unit" # optional; the source's wording
---deadline and amountMax are nullable rather than optional. Null means the
source did not state it, and the page prints Not stated; a zero or an empty
string would reproduce in an email the exact misreading the three absence
states exist to prevent.
A file missing any required field fails the build and names itself.
Where issues come from
The generation step is a pipeline concern and lives outside these pages. What
lives here is the contract above and the two routes that read it —
/newsletter and /newsletter/<date> — so a generated issue is
publishable the moment it is written, and an issue written by hand is subject
to exactly the same rules.