Independent civic reporting

The public record is only the beginning.

TownReporter is a civic newsroom you run yourself. It watches meetings, money, contracts and public records — then keeps digging when something changes, disappears or doesn’t add up. A human still decides what ordinary reporting prints; selected approved routine notices use fixed templates and approved sources.

Repository release: 0.6.34 — beta. Direct beta tag: 0.6.34. Stable Windows acquisition remains 0.6.30. Deployment is a separate operator step; current capabilities and remaining work are distinguished below.

Watch Cheap, deterministic City sites, PrimeGov packets, YouTube catalogs. Fetch, hash, notice what moved. No model required until you ask for leads.
Investigate Variable, costs tokens Dark Desk. Competing hypotheses, the whole tape, trails that were dead until new evidence. It never prints.
Human The human gate Hold, kill, or put ordinary reporting on the paper. Captions are not minutes. Names may be wrong. You are the check; approved routine notices use fixed templates and approved sources.

Same three jobs on every story. The model does not get a masthead.

MIT licensed Node 22 Codex or Claude · API keys optional Self-host email + password Ordinary reporting is human-reviewed

What you actually get

A paper on the front, a working desk behind it

These are real product screenshots, not mockups. The Command Center and Dark Desk show current local development fixtures in the Fable Direction A layout: the desk has a main queue column and a Dark Desk, Follow-ups and wire rail. The workbench and Paper setup show development examples; the public paper and Server images are historical Longmont screens from 29 August. Their old Leave as editor header link now lives as Give up the desk on the Server page.

The TownReporter front page
The paper. Reporting sources alongside stories. No tracker, no third-party font, nothing loaded from anywhere but this machine.
The editor’s desk
The desk. The queue, Dark Desk and the wire, with one line at the top saying what actually needs you.
The story workbench
The workbench. A named model choice fixes one provider for the whole run; notes on the left never print, and Publish is still the only gate.
Dark Desk
Dark Desk. Three piles, nothing deleted, and no publish button anywhere on the page.
The Server page
Historical Server page (0.5.1). The Windows package reports its own app, database, queue and local response. Tunnel and watchdog status require a separately configured host.
Set up the paper
Paper setup. Name the publication and city, choose the local clock, seed the watch list, and tell meeting discovery which channels and title phrases belong to this town.

Capabilities

Pick the model everywhere, and the desk stays readable

Pick the model everywhere

One registry

Story, Scan and Dark Desk now all show the same Writing model picker — Automatic, Codex Terra, Codex Sol, Claude Opus or Local model — each one reading from a single provider registry instead of four files that had to agree by hand.

Readable for real eyes

Dark mode, fixed

The desk has checked theme-token contrast, and nothing on the desk renders below a 14px floor. A new Text: Normal / Large toggle sits next to Light/Dark in the header for anyone who wants it bigger still.

Set how long a model may take

Server page

Each writing model on the Server page now has its own Time per call, editable between 10 seconds and 60 minutes with the shipped default shown beside it and a Reset — so a slow local model finally gets the room it needs.

The idea

Most local coverage dies in the packet

The agenda is public. The five-hour tape is public. The staff report is public. Almost nobody reads them, and the one story that does get written is often a rewrite of the announcing source.

TownReporter is built for the other job: watch the civic record, follow what it doesn’t say, keep a copy when it vanishes, and put a reported story in front of an editor. The Longmont edition is the working proof — city council, planning, NextLight, St. Vrain Valley Schools, Boulder County, PrimeGov, the city channel, Longmont Public Media.

It is not the Times-Call, not the city, and not a replacement for either. It is a newsroom you can clone.

Two rooms

The paper is public. The desk is not.

The paper

Anyone

Stories and eligible owner-approved routine notices. Sources shown. Compare versions when a cited record moved. Corrections in the open. RSS. About and How we report say the same thing this page says, on the masthead.

The desk

Signed-in editors

Watch list, scan, queue, workbench, reporting notes, research memo, Dark Desk. First account is owner. A second identity is not auto-granted editor. Notes never print.

How it works

Watch, then follow, then a human gate

  1. Watch

    A list of civic sources — city, council, PrimeGov, planning, utilities, schools, county, the YouTube tapes. Starting point, not a fence.

  2. Detect

    A scan fetches those pages, hashes them against the last snapshot, and flags what changed, what disappeared, and what failed to appear when it usually does.

  3. Follow

    With public-source research selected, the desk asks what the announcing source leaves unexplained, then follows attachments, names, contracts, parcels, prior meetings.

  4. Preserve

    Significant captures are stored. If a record later vanishes, the captured version remains, and the article says so.

  5. Investigate

    Dark Desk is the recursive lane. Competing hypotheses. The whole tape. Trails exhausted until new evidence reopened them. It does not print.

  6. Write, then gate

    Drafts are reported stories, not recaps. Ordinary reporting is held, killed or published by a person; approved routine notices use fixed templates and approved sources. Every material claim should be checkable against a document you show.

  7. Credit

    When a story hangs on another newsroom’s reporting, name them and link the exact story, not a homepage. Stay on the workbench while Draft with AI runs — the form fills when the pass lands.

Meetings

Three records of the same night

Packet

PrimeGov JSON + PDFs

The catalog is an API, not a crawl of a login wall. Agenda, packet, and minutes are separate documents. YouTube titles join the matching meeting.

Tape

City channel + Public Media

Full timestamped transcript, not a slice. Upcoming livestreams stay listed with no fake captions and are rechecked. Sister channel fills a gap. Month must match.

Minutes

The official action

Captions are a map. Names may be wrong. Quotes need a check. Minutes not posted after 36 hours is a catalog note — a reason to look, not a story by itself.

Install

Install on Windows. Create your paper. Choose a writing model.

Download the Windows installation ZIP from the release assets, extract it, and open Install TownReporter.cmd. It provisions private prerequisites and persistent storage, then checks that the server is ready. Bring an available AI account or endpoint. The installation target is under an hour; the release records measured timings and limits.

Windows beta download · 0.6.34 Latest stable Windows Installation guide

Prefer source setup? Windows, macOS and Linux instructions follow. Public hosting is separate from a local installation.

# Node 22+, then:
git clone https://github.com/scottconverse/TownReporter.git
cd TownReporter
npm install
npx playwright install chromium
cp .env.example .env
# API keys optional — local and signed-in CLI paths supported
npm run dev
# http://localhost:8080/login — create the owner account

Playwright Chromium is for Show transcript and JS civic sites (Municode). PrimeGov packets still work without it — they are a JSON API.

Pick per story. Every Queue row and the story workbench put a model picker beside Draft with AI. Automatic uses your configured gateway when set; otherwise it tries Claude Opus, then Codex Terra, before the job starts, then keeps that provider for every pass unless Automatic moves to the next ready provider after an eligible failure. Named choices never fall back.

Set up a writing model opens help under every Queue, workbench and Opinion picker: installation links, sign-in on the server's account, and reload/retry steps. Opinion also explains its required voice file. Nothing installs or signs you in automatically.

Claude Code strips its coding settings for news calls. Codex deliberately keeps the signed-in Windows user’s native configuration and full available access: search, shell and files, browser/computer tools, apps, plugins, hooks, skills, rules and multi-agent capabilities. TownReporter does not replace them with a read-only sandbox.

Zen MiMo and Local Qwen were removed from the picker (2026-09-02). 0.6.10 brought back Local model. The desk now discovers individual models on LM Studio, Ollama and llama.cpp; a configured LLM_BASE_URL is also supported. Codex and Claude reuse their signed-in CLI sessions and check readiness before enqueue.

Prefer a gateway? Any OpenAI-compatible /v1/chat/completions endpoint works with three LLM_* vars — LiteLLM, Bifrost, Helicone, MLflow, Kong, Ollama, OpenAI or OpenRouter. It becomes the forced Story Automatic provider and the configured provider for Scan and Dark Desk.

Opinion offers Claude and the local model. Automatic and Claude Opus both mean Claude Opus through your signed-in Claude Code session, which reads the editorial voice by file path and keeps its tool-free writing boundary; Local model is offered too, through local discovery or configured LLM_BASE_URL. Codex is not offered for editorials: its model declines to write a piece that takes a position on a local policy question, so it stays on the Story picker. A refusal, assistant note, implausible headline or incomplete body is marked failed and never becomes a draft.

Unset DATABASE_URL and you get embedded PGLite. Fine for a look. Data dies when the process stops. A newsroom wants Postgres.

The manual · Editor’s guide · Operator setup · README

Your city

The Longmont edition is the example, not a fence

Create the owner account and TownReporter opens Set up the paper. Enter the masthead, city, timezone, contact links and starting sources. Add the city’s meeting-video channels and the title phrases its clerks use. Save, and the public paper and newsroom follow those database settings immediately.

No file edit or rebuild. The same form stays under Server → Paper setup. If the city uses PrimeGov, add its exact public portal to the watch list. Full notes are in the operator setup.

Status and limits

What this is not

Drafts are AI-assisted. Models invent facts, misattribute quotes, and mangle names — especially from auto-captions. TownReporter does not fact-check for you. You are solely responsible for everything that appears on the paper. This is not a substitute for professional journalism, not legal advice, and not the city.

Start a paper for your city

Install it, create the owner, and fill in one screen. The Longmont edition is the working example; your database holds your paper’s identity and sources.