WP β Static Transform Playbook
Turn any WordPress page into a clean static HTML+JSON entry in minutes.
The 4-step workflow
1. Save WP page β 2. Extract β 3. Build β 4. Serve
(browser) (Python) (Node) (local)
Step 1 β Save the WP page from your browser
Open the WP URL in Firefox or Chrome. Hit File β Save Page As and choose "Web Page, Complete".
You get two things in the same directory:
Some-Page-Title.html
Some-Page-Title_files/ β local copies of all images, fonts, CSS
Put them in tmp/ (already gitignored).
Step 2 β Extract content
python3 wp-to-static.py tmp/ --out <slug> --layout <page|retro|corporate>
| Flag | Default | Use when |
|---|---|---|
--out slug |
derived from filename | always set this |
--layout page |
page |
standalone info/artist page |
--layout retro |
β | blog post for the dark retro feed |
--layout corporate |
β | full-company page (nav, hero, sections, footer) |
--lang de |
de |
language code |
--build |
off | auto-run npm run build after extraction |
Output: content/<slug>.json + images copied to public/assets/<slug>/
Step 3 β Review & tune the JSON
Open content/<slug>.json. The script is a best-effort extractor β check:
hero.bodyβ usually the first text block. Should be the intro paragraph, not a menu item.sectionsβ each h2 becomes a section. Delete footer/nav headings that leaked in.navβ for one-pager layouts, replace hrefs with#anchorrefs.imagesβ first image is usually the logo or hero shot. Delete tracking pixels if any slipped through.cta.hrefβ verify links still make sense on the static site.
For layout: retro you also need to set date, tags, and add the entry to content/posts.json:
// content/posts.json β append your extracted post object here
Step 4 β Build & preview
npm run build # Tailwind CSS + HTML generation
npx serve public/ # Local preview at http://localhost:3000
Layout β build.js mapping
layout in JSON |
build.js function | Output path |
|---|---|---|
retro |
buildPost() |
public/posts/<slug>.html |
corporate |
buildCorporatePage() |
public/corporate/index.html + sub-pages |
page |
(add buildPage() β see below) |
public/<slug>/index.html |
The page layout is generic β add a buildPage(cfg) function in build.js that reads any content/*.json with layout: "page" and renders a simple hero + sections template.
Adding a new site (end-to-end example)
# 1. Save https://onezeromore.com/en/artist-branko in browser β tmp/
# 2. Extract
python3 wp-to-static.py "tmp/artist-branko.html" \
--out artist-branko \
--layout page \
--lang en
# 3. Review
nano content/artist-branko.json
# 4. Build
npm run build
npx serve public/
# β http://localhost:3000/artist-branko/
Theme-specific extraction notes
| WP Theme | Heading class | Body class | CTA pattern |
|---|---|---|---|
| Enfold | av-special-heading-tag |
avia_textblock + itemprop="text" |
avia_iconbox_title inside <a aria-label> |
| Divi | et_pb_module_header |
et_pb_text_inner |
et_pb_button |
| Elementor | elementor-heading-title |
elementor-text-editor |
elementor-button-text |
| Astra/OceanWP | standard <h1>β<h3> |
.entry-content p |
.wp-block-button__link |
| Generic WP | <h1>β<h3> in <main> |
.entry-content |
.wp-block-button__link |
wp-to-static.py tries strategies in order β Enfold-specific first, then generic. For Elementor/Divi pages, add a targeted extraction block in extract_text_blocks().
Ollama AI enrichment (optional future step)
After extraction, pipe the raw text through Ollama for SEO:
ollama run qwen3.5:2b "Write a 155-char meta description for: <paste content>"
Or wire it into the build pipeline β see CLAUDE.md Β§AI enrichment when implemented.
Files produced by this workflow
content/<slug>.json β source of truth, commit this
public/assets/<slug>/ β copied images, commit these
public/<slug>/index.html β generated, do NOT commit (gitignored)