Open source · Self-hosted · MIT licensed

A civic newsroom you run yourself.

TownReporter watches your town’s public record: meetings, packets, minutes, money and contracts. It turns what it finds into leads and drafts for an editor. A person reads every ordinary story and presses Publish.

Built for a town that needs coverage and has one editor, not a newsroom. The working edition watches Longmont, Colorado.

The public record is only the beginning.

Repository release: 0.6.87, released October 29, 2026. Release notes · Changelog · GitHub

The TownReporter public front page: a masthead, a lead story, and a grid of recent local stories with sections.
The public paper. Stories show their sources. No tracker, no third-party font.
  • A person presses PublishScan, draft and Dark Desk never print by themselves.
  • It warns, never blocksEvery warning has an “anyway” button.
  • MIT licensedFree to use, change and run.
  • Self-hostedYour computer, your database, your archive.
  • Local or cloud modelsUse your own hardware or a subscription you already have.

What it is

A paper in front. A working desk behind it.

Most local coverage dies in the packet. The agenda is public, the five-hour tape is public, the staff report is public, and almost nobody reads them. TownReporter reads them, keeps a copy when something disappears, and puts a reported draft in front of an editor who decides what prints.

The paper · open to anyone

Stories, sources shown

Reporting and unsigned editorials, plus owner-approved routine notices such as Today in town. Every story lists the records it used. Corrections are public and dated. There is an RSS feed, a searchable archive, dark mode and reading sizes.

A published TownReporter story page with a headline, byline area, the story text and a list of sources.
The desk · signed-in editors

Today, Queue, Drafts, Published

Watch list and scan, a Queue of leads, a story workbench, Drafts, Opinion, Follow-ups, Dark Desk, Models, Server and Stats. The first account is the owner; others are invited by one-time link.

The editor desk home screen, Today, with the left navigation and the day’s work.

One editor

Keep a watch list of your city’s own sources. A scheduled scan files leads. You give a story direction, the AI drafts, you edit and publish.

Any town

No code edit or rebuild. The owner fills out Set up the paper: name, city, time zone, sources, meeting channels. The Longmont edition is the example, not a fence.

Your records, your rules

Open source under the MIT license. Your archive lives in your database. Reading the paper sends nothing to an outside host.

How it works

Watch, follow, preserve, then a human gate

The same six moves the paper describes on its own “How we report” page.

  1. WatchA list of civic sources: city site, council, agenda portal, schools, utility, meeting-video channels.
  2. DetectA scan fetches those pages, compares them with the last copy, and flags what changed, vanished, or failed to appear.
  3. FollowThe desk asks what the announcement leaves unexplained, then follows attachments, names, contracts and prior meetings.
  4. PreserveSignificant captures are stored. If a record later vanishes, the copy remains and the story says so.
  5. InvestigateDark Desk keeps competing hypotheses and open trails. It digs. It never prints.
  6. Write, then gateDrafts show their evidence. A person holds, kills or publishes ordinary reporting.
  1. SourcesWatch list, PrimeGov, YouTube
  2. ScanFetch, compare, file leads
  3. QueueLeads wait for you
  4. DraftDirection, then draft with its evidence
  5. CheckClaims judged, exceptions shown
  6. PublishA person presses it
  7. The paperSources and corrections public

Routine notices (library hours, recreation, community events, registration deadlines, waste collection) can print without an editor, but only from sources the owner approved and through fixed templates. The architecture drawings are in the manual.

How a meeting becomes a story

  1. Capture. The meeting recording is read and stored as an unchangeable transcript revision.
  2. A lead. Capture files a lead in the Queue with the transcript passages it used.
  3. Direction, then draft. You say which decision to cover; the draft cites the passages it actually used.
  4. Names are checked. A speaker nobody can confirm becomes “an unidentified speaker”.
  5. The gate. If a citation no longer matches the recording, the Publish bar warns you.

Captions are a map, not minutes. Packets and minutes are the official record.

Honest limits

  • Models invent facts, misattribute quotes and mangle names, especially from auto-captions. The checks narrow what you must read; they do not replace editing.
  • A vote count that is missing stays “unknown”, never zero.
  • YouTube can rate-limit a capture; a later pass tries again.
  • A city swap does not carry over the parsers written for Longmont’s own pages.

Inside the desk

What an editor actually uses

Screens from the running desk. Each links to the part of the manual that explains it.

Scan the sources, work the Queue

A daily scan reads your accepted sources and files leads. It reads the whole accepted pool, never-read sources first, and reports by name which sources it read, which are waiting and which were blocked. The Queue holds the leads: draft, hold, kill, or Undo, with keyboard shortcuts for each.

  • Scan scopes: General, one reporting beat, or a custom set.
  • Pages that refuse automated reads get one guarded browser try, then their RSS feed.
  • Subscribed newsletters enter the archive through a mailbox you set up.

Scan in the manual · The Queue

The Sources and scan screen showing the scan scope choices, a run summary with sources read, waiting and blocked, and the scan history.

A Queue of leads, and a Drafts list

Every lead arrives with the page or transcript that produced it. Open one, give it a story direction, choose a model, and draft. Draft selected runs up to five leads on one named model. The Drafts list shows each draft’s state and readiness, and the model behind it.

Editor’s guide

The Queue: a list of leads with source, section and status, and the bulk strip with the model picker.
The Drafts list showing each draft’s readiness, the model that wrote it and the time.

A story page that shows its evidence

The workbench keeps the lead, the draft, the checks and the sources side by side. The AI judges each claim against its pinned passage; you see the exceptions first and accept the rest with one button. The Publish bar lists every warning and reads Publish anyway in <section>. A person presses it.

The story workbench

The story workbench: lead, draft text, the checks tab and the Publish bar.

Find evidence, even by meaning

On any story, Find evidence searches the paper’s captured records by exact words and by Close in meaning. A third list, Our past stories close in meaning, finds earlier stories and uploaded files that relate to the one you are working on. It is on the editor desk only. Nothing it finds is added to a story’s text, and the public search box is unchanged.

The Find evidence panel on the Sources tab: a search for Oligarchy Ditch with 12 exact-word matches and zero close-in-meaning results, because the meaning index is not built yet.

Today in town

From calendars the owner approved, the paper prints a time-ordered list of the day’s events: time, name, place, and “Free” or “Sign up” when the data has it. With six or more events it groups them under Morning, Afternoon and Evening. Every run says in plain words why any item needs review. Ordinary stories never take this path.

The Today in town article: a dek with the number of events and a list of event blocks with times, names and places.

One model picker, on every AI screen

Wherever an AI does work, you see the same picker with the full list. Choose Automatic and the desk tries these in order, using the first that is ready, and moves only the unfinished call down the list if one fails:

  1. DeepSeek v4.1 Flash 1017 the paper’s default
  2. Local model whichever the computer has loaded
  3. Codex Sol 6.1 (balanced)
  4. Claude Sonnet 5.5

Gemini and the other Codex and Claude models stay available as named picks; Automatic never chooses Gemini. You can also add any OpenAI-compatible endpoint as a saved connection. After each draft the story page shows Last draft: <model>, <time>.

The model in the manual · Local models

The shared model picker with Automatic expanded, showing the order of models it tries.

Dark Desk: it digs, it never prints

Point it at a person, a document, a link, a rumor or a gap. It keeps competing hypotheses and trails that reopen when new evidence appears, and every theory carries what would kill it. Two dials set the work: Dig (how far it chases) and Nerve (how speculative it may be). It has no publish button; a finding can be sent to the Queue.

Dark Desk in the manual

Dark Desk: the file list on the left, the open file with its question, explanation, scope and findings.
The Dark Desk dials, Dig and Nerve, with plain descriptions of each setting.

Opinion, in the paper’s own voice

Give it a subject, a sentence or a link, and it drafts an unsigned editorial from a voice file you keep on your own disk, with a claims-and-sources appendix. It stays a draft until you publish it.

Opinion in the manual

The Opinion desk: the subject box, model picker, and a drafted editorial.

Run the paper: Server, Published, Paper setup

The Server page shows health, backups, models and the few buttons worth having. Published lists live stories and the public corrections. Paper setup is where an owner names the publication and the city, chooses the time zone and seeds the watch list.

The Server page · Published

The Server page: health cards for the app, database and queue, backups and settings.
The Published screen with live stories and the correction controls.
Set up the paper: name, city, state, time zone and starting watch list.

Version 0.6.87 · October 29, 2026

What is new

New in 0.6.87: Dark Desk job cards stay current, model retries name the model that will run, and Send to Dark Desk opens a new file. The cards below describe the current release's main capabilities; the changelog has every change.

One picker, one ladder

The same full model list on every AI screen. Automatic walks DeepSeek, the Local model, Codex Sol 6.1 and Claude Sonnet 5.5. Gemini is a named pick only.

Find evidence

Search the paper’s evidence by exact words or by meaning, including its own past stories and uploaded files. Editor desk only.

Today in town

A time-ordered event list under Morning, Afternoon and Evening, with a named source, and a plain reason for every item that needs review.

Warns, never blocks

Publish anyway, Kill anyway, Hold anyway and Draft anyway, each written to an audit trail with who pressed it.

A rebuilt Dark Desk

A file selector, plain explanations, timed activity, a Decide menu, and Challenge the case as a saved job.

Evidence checks

The AI judges each claim; you review the exceptions. A draft with no recorded claims says “Not checked yet”.

More sources, more files

Subscribed newsletters, Excel, PowerPoint and LibreOffice files, RSS and Atom feeds, and sites that refuse automated reads.

A scan that reads it all

The daily scan reads the whole accepted source pool and reports sources read, waiting and blocked.

Steadier operations

Three-day backups on D:, a watchdog that waits for a slow start, and a server that says 503 until its database is current.

Trust

What you can count on, and what you cannot

The human gate

Ordinary stories reach the paper only after a person reviews them and presses Publish. A scan files leads. A draft fills a workbench. Dark Desk fills a file. None of those publish. Only routine notices from sources the owner approved, through fixed templates, can print without an editor.

Warns, never blocks

When a rule says an editor should stop, the desk shows the warning and a button that does what the editor asked, such as Publish anyway in <section>. The editor, the time, the warning and the target are written to the audit trail. A few true impossibilities, like an empty headline, stay refused.

Your data, your machine

MIT licensed and self-hosted. Reading the paper makes no request to any outside host: fonts are served from your machine and there is no analytics script. Working the desk does reach out: to the sites you watch, to the model you choose, and to public search. The manual lists exactly what leaves the machine.

Local or cloud models

Use a model on your own hardware (LM Studio, Ollama, llama.cpp), a signed-in Codex or Claude subscription, or any OpenAI-compatible endpoint. The AI CLIs run with shell, browser and plug-in tools switched off, and fetched pages are treated as evidence, never as instructions.

Read this first. Drafts are AI-assisted. Models invent facts, misattribute quotes and mangle names, especially from auto-captions. TownReporter checks names and evidence, but those checks do not replace editorial verification. Captions are not minutes. You are responsible for everything that appears on your paper. This is not a substitute for professional journalism, not legal advice, and not the city.

Install

Run it on your own computer

You bring an AI account or endpoint if you want drafts. Filing a lead and editing and publishing a story work without one.

Windows (recommended)

  1. Open the 0.6.87 release and download TownReporter-0.6.87-windows-x64.zip. Do not use the “Source code” archive.
  2. Extract it completely into a folder you will keep.
  3. Open Install TownReporter.cmd. It sets up a private database and the app.
  4. Open http://127.0.0.1:4388, create the owner account with the one-time setup code the installer prints, and fill out Set up the paper.
  5. Open Configure AI.cmd to choose a model, or use one you are already signed in to.

Each release also carries a .sha256 file for the ZIP and a .json file naming its exact source commit.

Windows installation guide

From source (Windows, macOS, Linux)

# Node 22 or newer, then:
git clone https://github.com/scottconverse/TownReporter.git
cd TownReporter
npm install
npx playwright install chromium
cp .env.example .env
npm run dev
# http://localhost:8080/login

With no DATABASE_URL it runs on an embedded database that is lost when the process stops: fine for a look, not for a newsroom. Use Postgres to keep an archive.

Operator setup · Self-hosting

GitHub Pages serves this landing page only. The newsroom is a Node application: run it on a computer or host that can run Node 22, Playwright Chromium and Postgres.