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 #anchor refs.
  • 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)