Inspiration
How to build a procedurally generated local newspaper for a fictional town using Claude and Python
Tired of generic world-building? Use Claude and a simple Python pipeline to generate a daily local newspaper packed with eccentric town gossip, mundane arguments, and minor mysteries.
Updated 9/5/2026
Most procedural generation in games and creative writing focuses on the epic: massive star systems, sprawling fantasy dungeons, or continent-spanning histories. But there is a massive amount of narrative gold buried in the mundane. The absolute peak of world-building is not a list of ancient kings; it is the classifieds section of a tiny, highly suspicious rural newspaper.
If you want to build a truly alive fictional world, a daily local newspaper is a brilliant vehicle. Whether you are building a backdrop for a tabletop RPG, a text-based game, or simply want a bizarre, slow-burn narrative to read with your morning coffee, you can build a self-sustaining generator using Python and Claude.
Here is how to build a program that generates "The Mudbury-on-the-Wold Gazette"—complete with local politics, petty feuds, and slightly supernatural planning disputes.
The Architecture of a Generative Newspaper
If you simply ask an LLM to "write a fake newspaper," you will get a generic, chaotic mess that lacks continuity. To make this project work, we need a state engine. Our Python script will maintain a JSON file containing the "town state."
This town state tracks: Current date* in the fictional world. Key residents* (e.g., Mayor Thistlewood, Mrs. Gable of the allotment society). Ongoing storylines* (e.g., the missing public bench, the strange hum coming from the abandoned quarry). Recent events* (what happened in yesterday's edition).
Each time you run the script, it feeds the current town state into Claude, asks the model to generate the daily articles and update the storylines, and then saves the updated state back to disk.
Step 1: Setting Up the Town State
To start, we need to define our town. We will create a town_state.json file. Here is a baseline of what that looks like:
`json
{
"town_name": "Mudbury-on-the-Wold",
"current_day": 1,
"residents": [
{"name": "Mayor Arthur Thistlewood", "personality": "Defensive, obsessed with winning 'Best Kept Village'"},
{"name": "Mrs. Beatrice Gable", "personality": "Ruler of the allotment society, intensely suspicious of youth"},
{"name": "Dr. Alistair Finch", "personality": "Local conspiracy theorist, retired librarian"}
],
"ongoing_plots": [
{
"id": "quarry_hum",
"title": "The Mysterious Hum",
"description": "A low-frequency vibration is coming from the old quarry at night.",
"status": "unsolved",
"escalation_level": 1
}
],
"historical_events": []
}
`
Step 2: Designing the Generative Prompt
Now, we need a Python script to interface with the Claude API. If you run into issues setting up your environment or managing API keys, check out the Claude Support Site for troubleshooting guides.
We will write a prompt that forces the LLM to output both the newspaper text and the updated JSON state in a single call. This is best achieved using Claude's system prompt and structured XML-like tags. For a deeper understanding of system formatting, check out our glossary.
Here is how we structure the API call in our Python script:
`python
import json
import anthropic
Initialize Claude client client = anthropic.Anthropic()
Load our current state with open('town_state.json', 'r') as f: state = json.load(f)
prompt = f""" You are the sole editor and reporter of "The Mudbury-on-the-Wold Gazette", a parochial local newspaper. Here is the current state of the town: {json.dumps(state, indent=2)}
Generate today's edition of the newspaper (Day {state['current_day'] + 1}).
Include: 1. A front-page story regarding one of our active plots or a new trivial town dispute. 2. A 'Letters to the Editor' section showing petty disputes between our residents. 3. A classifieds section with weird items for sale.
You must also provide the updated 'town_state' JSON reflecting any new developments, plot escalations, or new residents introduced in this issue.
Format your response precisely like this:
<newspaper>
[Write the newspaper here using simple Markdown headers]
</newspaper>
<new_state>
[Insert the updated JSON here]
</new_state>
"""
`
Step 3: Parsing and Saving the Output
Once Claude returns the text, your Python script parses the output using simple string slicing or regular expressions. It writes the newspaper content to a clean markdown file (e.g., gazette_day_2.md) and overwrites town_state.json with the updated JSON state.
What makes this system tick is structural memory. If Mrs. Gable accuses Mayor Thistlewood of stealing her prize-winning marrow in Day 2, the JSON state will update to reflect their mutual hostility. When Day 3 runs, Claude will see that hostility in the residents array and naturally carry the feud forward in the next Letters to the Editor column.
Step 4: Making It Run on Autopilot
To make this a true daily experience, wrap your Python script in a simple shell script and set up a daily cron job on your computer or a basic cloud server.
Every morning, you will wake up to a fresh edition of your custom newsletter. One day, you will read about a minor controversy regarding the local duck pond; three days later, you will find out the ducks have formed an orderly picket line outside the town hall. By keeping the stakes incredibly low and the continuity incredibly tight, you will build a living, breathing community that exists entirely in a folder on your hard drive.
Keep going
Build something with the prompt generator, decode the jargon in the glossary, or compare the tools on our platform deep-dives.