Pick a crate of lager, shandy or cider and we will knock 50% off a box of crisps. Take the crate
How this is actually built

Python in, PHP arrays out, and a theme that provisions itself.

Five hundred pages are not written by hand and they are not held in a database. They are generated from Python into plain PHP arrays, committed as files, and read by a WordPress theme that creates its own pages on activation.

Six steps

The pipeline, end to end.

A family is a Python module

One file per pillar. It declares its pages as data — path, title, template, and a list of sections.

Sections are function calls

Ninety-odd builders. A hero is hero(…), a comparison table is compare(…), a rights register is register(…). Nobody writes markup.

A floor is enforced at write time

Every page needs at least seven sections. A thinner one raises rather than shipping, because a stub inside five hundred pages reads as neglect.

The build serialises to PHP

One file per family in inc/content, as a plain PHP array with a return statement. Readable, diffable, and editable by hand if anybody ever needs to.

The theme reads the array

A content loader maps a request path to an entry and renders the sections in order through one template part each.

The theme provisions itself

On activation it creates the WordPress pages, assigns the templates and builds the menus from a map. No manual setup, no import file.

The reasoning

Why each of those decisions was taken.

Generation rather than authoring

Consistency
Five hundred pages, one voiceA section builder cannot be styled inconsistently, because there is one implementation of each.
Refactoring
A change to a section type reaches every pageChanging how a comparison table looks is one file, not four hundred edits.
Structure
Every page has a shapeThe seven-section floor is checkable at build time rather than in review.
The cost
A build step, and a learning curveSomebody who wants to fix a typo has to know where the generator is. That is a real cost.

PHP arrays rather than a database

Diffable
Every content change is a diffWhich is the single largest practical advantage and the one nobody expects.
Deployable
Content ships with codeNo import, no migration, no staging database that has drifted from production.
Fast
An include, and an opcode cacheNo query, no join, no cache invalidation problem.
The cost
Editors cannot editThis is a demonstration build with no editors. On a real one it would need an admin layer, and that is not free.

Self-provisioning

Activation creates the pages
From the same arraysA fresh WordPress install becomes the whole site in one click.
Menus from a map
Declared, not clickedA five-hundred-page menu built by hand is wrong within a week.
Templates assigned automatically
By the template fieldNobody picks a page template in an admin screen, so nobody picks the wrong one.
Seven artefacts

What the build actually produces.

ArtefactWhat it isRoughly
inc/content/*.php One plain PHP array per family Twenty-four files
page-templates/page-*.php A thin wrapper per page type Around ninety
template-parts/sections/*.php One renderer per section type One per builder in the generator
assets/js/search-index.js The command palette index, generated at build One cached request rather than an inline blob on every page
assets/img/scenes/*.svg Generated illustrations Fifty base scenes, no photography, nothing licensed
bin/qa.php A static harness Page counts, template coverage, broken internal links, orphans and duplicate chapter numbers
bin/preview.php A static render harness Renders every page to flat HTML without WordPress, which proves the templates execute
Being honest about it

The thing this stack is bad at.

Editing. There is no admin interface for content, because the content is a file. Somebody who wants to change a sentence needs the repository, a Python environment and a build step, which is a perfectly reasonable requirement for a demonstration build and a completely unreasonable one for a business with a marketing team.

A real version would need a layer that lets a person edit a page without touching a generator, and that layer is not free — it is the point at which most of the advantages above start to be traded away one at a time.

The honest position is that generation is right for a site of this shape, produced this way, at this scale, by very few people. It would be the wrong answer for a newsroom, and it would be the wrong answer for anybody who needed to publish something at four o’clock on a Friday.

The stack

Four properties, one of them a weakness.

Generated

Python modules in, PHP arrays out.

Diffable

Every content change is a diff.

A seven-section floor

Enforced at build time, not in review.

Bad at editing

And this page says so rather than not.

Wondering

The stack, questioned.

Because it brings routing, templating, SEO plumbing, redirects and a hosting story that everybody already has. The content layer is replaced; the rest is genuinely useful.

Not as it stands. That is the main weakness of the approach and it is stated on this page rather than in a footnote.

Yes. One generated JavaScript file, cached once, shared by every page — rather than thirty-five kilobytes of index inlined into five hundred documents.

And the numbers behind the numbers.

Where every figure on this site came from, and which of them we are least sure about.

Next along the route

The numbers behind the numbers

Carry on
Basket Book the pub Plot a field Join the list Bother us

Snooping, briefly.

We use a small number of cookies to keep your basket upright and to work out which pages people actually read. We do not sell anything about you to anyone, because that would be a rotten way to behave.

Read the detail