Simon Willison Built a Newsletters Page by Voice: Codex and GPT-6 Astra in an Hour
Simon Willison launched a Newsletters page on his blog, with an archive of all his newsletters, and built almost all of it by voice. In the ChatGPT desktop app, in the Codex tab, he spent half an hour dictating the task to GPT-6 Astra High while he cooked dinner. The model wrote a Django model, a migration, templates and four data imports. Another half hour went on reviewing the pull request and making edits by text. • Voice lets you work on development alongside other activities. • Details, logs and code samples are more efficient to paste as text. • The author does not consider voice mode his primary way of working.
AI-processed from Simon Willison; edited by Hamidun News
Simon Willison, a creator of Django and one of the most prominent practitioners of LLM-assisted development, has launched a Newsletters page on his blog: an index of all his newsletters, both the free weekly one on Substack and the monthly one for sponsors. GPT-6 Astra High wrote almost all of the code in the voice mode of Codex, inside the ChatGPT desktop app. The dictation took about half an hour, while Willison cooked dinner. Another half hour went on review and edits from the keyboard.
Half an hour at the stove
He started the session with a text command, "Start dev server and open in browser." That put a local preview of the blog on screen, so he could follow progress visually. Then he clicked "Start new voice chat." It is not the microphone button but the one next to it on the right. He set the laptop up in the kitchen, and the work began.
The task was a typical Django one: a new model, a migration, a view, templates and several import functions. Willison was confident the model could handle it, so his brief came out conversational, with "um"s and self-corrections. He first said newsletters were not needed on tag pages, the index or the date archives, then changed his mind about dates: if a newsletter went out on September 19, it should appear on that day's page.
Substack copies should not be indexed in search, since they duplicate blog material. Monthly issues contain unique content, and a month after they are sent, when they are opened to the public, they should show up in search. The model understood the requirements; Willison posted the full transcript in a Gist.
Every so often it asked clarifying questions and went off to edit the code.
What came out of it
The session produced:
- a new Django model, a migration and admin settings;
- four imports: recent Substack issues via RSS, the rest of the Substack archive via an undocumented API, published monthly issues from a GitHub repository, and the latest closed sponsors-only issue from a private repository;
- public pages at /newsletters/ and /newsletters/2026/;
- newsletters shown on day and month pages, but not on the homepage and not in tags;
- links: weekly issues point to Substack, while monthly issues have their own pages;
- integration with the site's search.
The model handled the Substack API on its own. It knew the /api/v1/archive path and tried it directly. It then ran a search to work out the pagination and found an article by Karen Spinner. The model also came up with the design of the index page. Willison tweaked it by voice, glancing at the preview from across the kitchen.
The imports were the part left unfinished. Astra suggested exporting the data from the local copy and uploading it to production, but the author wanted a mechanism like the one his other scripts use. Part of the data sits in a private GitHub repository, so a new API key was needed, and that meant sitting down at the keyboard.
Review and the limits of voice
After that, the workflow was standard: Codex created a branch and opened a pull request, and Willison read the diff in the GitHub interface. His main objection: in one import, the model called Git through subprocess. For a private repository, an API is more reliable, so he switched to text and asked the model to replace the approach. The additional commits in PR #719 include that replacement and small display fixes. Another half hour of text prompts, and the code went to production.
The author's main takeaway is unexpectedly sober: voice will not become a daily tool for him. OpenAI likes to show demos like this, for example at DevDay, and there they work. But once you get into details, it is faster to paste an example or an error message, or to select the relevant chunk of code, than to describe them in words. Then there is the shared office: he would not talk to a computer like this in front of colleagues.
The strength of this setup lies elsewhere. A visual preview, plus the ability to switch to the keyboard at any moment, makes voice mode far more useful than on a phone during a walk with the dog, where the output is mostly research and brainstorming. The practical takeaway for developers: voice is good for a first pass, where you need to explain intent and overall structure. Polishing, review and anything tied to exact code are better done in text. A task for testing the approach should be a typical one: a familiar framework, a clear data schema, and a local server for feedback. And pull request review remains mandatory: it was the review that caught the unnecessary Git call.
Build & Ship Production AI Apps with Vibe Coding
Join Zhemal Khamidun's hands-on Vibe Coding Intensive at hamidun.com/vibecoding — master Claude Code, Cursor, and autonomous agentic workflows.
The AI world, distilled — once a week
Seven stories that actually mattered, hand-picked. No noise, no reposts, no press releases.
Done! Check your inbox for a confirmation.