# Coffee Edition
**A two-page newspaper, written overnight from your own notes, waiting on your printer in the morning.**

*Issue 001 and its RADAR page (now Fresh Ink), as the printer left them at 10:00 on 17 October 2026. Nobody pressed print. The story of how it was built: [erolsen.dev/writing/coffee-edition](https://erolsen.dev/writing/coffee-edition).*
You keep notes in a folder. Every night a Claude routine turns the next one into an issue, GitHub Actions lays it out like a newspaper and checks every page, and a Raspberry Pi Pico W on your Wi-Fi prints it at the time you chose. Your computer can stay off.
| Front page | Results page |
|---|---|
|  |  |
*The sample issue, written from the included note on the Raven paper (EverMind AI, arXiv 2609.33439, CC BY 4.0).*
**Fresh Ink, if you follow AI.** With `"radar": true` in `printer.json`, every issue gets one to four more pages at the back, laid out like a newspaper's front page and inside pages: 5 to 17 new AI methods, models and tools from the night before, picked from Hugging Face (daily and trending papers, new models), arXiv's new submissions, GitHub trending and eleven AI lab blogs, with Hacker News and four AI newsletters as signals. Each story says what the method is, how it works and when to use it, gives one number, and many carry a chart redrawn from the source's own table. A QR code under each story opens its paper or code. Every number and every chart value is checked against its source before the push.
| Fresh Ink, front page | An inside page |
|---|---|
|  |  |
*Pages 1 and 2 of the Fresh Ink sample (`edition/fixtures/fresh-ink.edition.json`), from the night of 22 October 2026.*
## How it works
```mermaid
flowchart LR
N["notes/
your notes"] --> R["Claude routine
writes the issue at night"]
R -->|"inbox/date.edition.json"| A["GitHub Actions
lays out, checks, converts"]
A -->|"queue branch"| P["Pico W
holds it until 07:30"]
P -->|"IPP over Wi-Fi"| PR["Your printer"]
P -->|"printed"| L["log/prints.md"]
```
1. **The writer.** A [Claude routine](docs/routine.md) runs a few hours before the print time. It picks the next unprinted note, reads it, writes the issue as a small JSON file following [edition/STYLE.md](edition/STYLE.md), builds it once to be sure it fits, and pushes it.
2. **The press.** GitHub Actions lays the issue out in headless Chrome with fonts that ship in the repository, paginates it into three columns, and checks the result: every line inside its column, at most four pages, and the printed PDF holding every character the layout had. It then converts the PDF into what your printer takes (PDF, PWG raster or JPEG) and puts it on the `queue` branch.
3. **The courier.** A [Pico W](docs/pico.md) polls the queue every five minutes. It holds each issue until its print time, finds the printer on your network and streams the job to it, then reports back so the print log says "printed".
Nothing on the internet reaches into your home network: the Pico only makes outgoing requests, like a phone. Details: [docs/architecture.md](docs/architecture.md).
## What you need
- **A Raspberry Pi Pico 2 W or Pico W** (tested on a Pico 2 W with MicroPython 1.28), a USB data cable and a phone charger.
- **A network printer** on the same 2.4 GHz Wi-Fi that accepts PDF, PWG raster or JPEG over IPP. Most AirPrint printers do; [docs/printers.md](docs/printers.md) shows how to check. A4 paper.
- **A GitHub account**, for your private copy of this repository and its Actions.
- **A Claude plan with Claude Code routines**: Pro, Max, Team or Enterprise.
- **On your computer**, for the setup: Python 3.9+, Node 22+, Chrome or Chromium, poppler (`pdftoppm`, `pdfinfo`, `pdftotext`) and `mpremote`.
## Set it up
The quickest way: make your copy (step 1), open it in Claude Code and paste [SETUP_PROMPT.md](SETUP_PROMPT.md). Claude walks you through the rest and stops before anything you should do yourself.
By hand:
1. **Make your copy.** Click **Use this template** → **Create a new repository**, and choose **Private**: your notes and your print log live there. Clone it.
2. **Check the tools.** `node edition/test.mjs` and `python3 scripts/test_nightly.py` should end with all cases passing.
3. **Your time.** In `printer.json`, set `timezone` (like `Europe/London`) and `edition_print_time` (like `07:30`), and `"nightly": "dry-run"`.
4. **Your printer.** Find its address and run `python3 tools/printer_info.py