Field guide

From Article Builder to a live WordPress page

Building an article, deploying it through WordPress's native Custom HTML block, and surviving Hostinger's cache layer โ€” with every screenshot tucked behind the same "More detailed info" disclosure the tool itself uses.


Optional ยท About this page

Why are the screenshots hidden?

Short version: it keeps the page calm to scan. It does not make the page smaller to download.

More detailed infoLess info

Every screenshot on this page is baked directly into the HTML as inline image data โ€” the same self-contained approach article-builder.html uses for its own CSS, so the whole tool works from one file with no server. That means all twenty-three images are already part of the document the moment it's fetched; putting them behind a toggle doesn't remove a single byte from that transfer. If you're picturing a real website with separate image files instead, that version would save real bandwidth from hiding images โ€” this single-file version can't, because there's nothing left to fetch later.

What it does save: a closed <details> never lays out or paints its contents, and browsers generally skip decoding an image until it's actually going to be shown. So the first paint of this page only has to rasterize the one-line summaries โ€” the twenty-three screenshots stay un-decoded dead weight until you click. Fewer big images competing for the first frame, less scroll to get through, same file underneath.

Part 1

Build the article โ€” everything below happens inside article-builder.html, no server, no build step.

01

Open the tool

Double-click article-builder.html โ€” it runs entirely in the browser.

More detailed infoLess info

If instead you're hitting a hosted copy (e.g. a URL under deliberatelearners.com/tools/), it may sit behind basic-auth sign-in like the prompt below โ€” enter the credentials once and the builder loads as a normal page.

Browser basic-auth prompt for article-builder.html, empty
Sign-in prompt, empty
Browser basic-auth prompt for article-builder.html, filled in
Credentials entered โ†’ Sign in
02

Read the layout once

Three panels on the left feed one live preview on the right โ€” nothing saves until you click Done.

More detailed infoLess info

The stacked panels are Article Header, Add a Part, and Parts in this Article. The whole article lives in the page's memory until Done โ€” build article.html compiles it.

Full Article Builder layout with the three left-hand panels outlined
The three panels: header, part editor, article outline
03

Fill in the Article Header

Kicker, Title, and Dek map straight onto the pill, heading, and subtitle you'll see live.

More detailed infoLess info

Watch the live preview update field-by-field as you type โ€” it's the fastest way to catch a typo before it's buried in HTML. Reset / Erase only clears this panel, not the rest of the article.

Article header fields mapped with arrows to their live preview output
Kicker โ†’ pill, Title โ†’ heading, Dek โ†’ subtitle
04

Add your first part โ€” a Numbered Step

Zone 1 stays always-visible; Zone 2 stays hidden until clicked โ€” that's the whole model, one step at a time.

More detailed infoLess info

Leave Numbered step selected. Keep the Zone 1 summary to one sentence. Tick "Show an always-visible command line" only if the step has a literal command to run โ€” it renders as its own you type block regardless of whether the reader ever opens Zone 2.

Zone 2 (and every long text field) accepts light formatting: a blank line starts a new paragraph, **bold** and `code` work inline, ## makes a sub-heading, lines starting with - or * become a bullet list, 1. becomes a numbered list, a line starting with $ becomes a "you type" command, and a fenced ```โ€ฆ``` block becomes a "you'll see" output block.

When the part is ready, click Append to Article.

Numbered step form filled in with title, Zone 1, command line, and Zone 2
A complete "Numbered step" part, ready to append
05

Check the disclosure behavior before moving on

Click your own toggle right here, before it ever reaches WordPress.

More detailed infoLess info

After appending, the live preview shows the step collapsed behind a "More detailed info" toggle โ€” the exact component wrapping this very paragraph. Click it: it should relabel to "Less info" and reveal Zone 2. This show/hide interaction is the entire reason the tool exists, so get in the habit of testing every toggle you add.

Live preview of step 1 collapsed, showing the More detailed info toggle
Collapsed โ€” Zone 2 hidden
Live preview of step 1 expanded after clicking the toggle
Expanded โ€” toggle now reads "Less info"
06

Repeat for every remaining step

Fill the same form again per step; Done only compiles once every part is appended.

More detailed infoLess info

The form resets its fields after each append but keeps building the same article underneath. Skip the command-line checkbox on steps that don't need one. Done โ€” build article.html is what finally compiles everything, so don't click it until every step is in.

Second step form filled in, with an arrow pointing down to the Done button
Step 2 appended; Done waits until every part is in
Live preview showing two collapsed steps stacked
Two steps, both collapsed
Live preview showing two expanded steps stacked
Both toggles opened independently
07

Manage the outline

Parts in this article lists every piece in order — reorder with the arrows, or delete with ×.

More detailed infoLess info

Each row is matched to its card in the live preview. Every row carries three controls: and swap a part with its neighbor (grayed out at whichever end doesn't apply), and × deletes it outright. Moving a part re-renders the live preview immediately — including step numbers, since a Numbered Step that moves past a Text block or Optional Section renumbers itself automatically.

A step tag that was explicitly restarted (see the next two steps below) shows a small next to its number in this outline — e.g. STEP 01 ↻ — so you can tell at a glance which "01" is the actual start of the article and which one is a deliberate restart further down.

The Parts in this Article outline showing up/down/remove buttons per row, and a restart badge on the last Step 01
Move buttons per row, plus the restart badge on the second "Step 01"
08

Add an Optional Section for asides

Same Zone 1 / Zone 2 model, but accent-colored by purpose โ€” like the aside above this list.

More detailed infoLess info

Switch Add a Part to Optional section for content that isn't a numbered step โ€” a troubleshooting note, a "why this matters" aside. It adds an Eyebrow label, a Section title, a one-line teaser (Zone 1), and an Accent color picker โ€” Neutral, Amber for "proceed with care," or Rust for "troubleshooting." Zone 2 holds the full write-up, hidden the same way as a step's detailed info.

Optional section form filled in with eyebrow, title, teaser, accent color, and Zone 2
An "Optional section" part with a Rust accent
Live preview showing the optional section collapsed with a colored left border
Collapsed, with its accent-colored rail
Live preview showing the optional section expanded with full content
Expanded โ€” same toggle mechanics as a step
09

Add a Text block for freeform prose

A third "Add a Part" tab — always visible, no title, no disclosure toggle, no card.

More detailed infoLess info

Not every part of an article is a numbered step or an aside — sometimes you just need a line of narrative between two steps, or an intro before the first one. Switch Add a Part to Text block for that: one textarea, parsed with the exact same formatting rules as a step's Zone 2 (headings, lists, bold, code, command blocks, and ![alt text](image url) for images), rendered directly into the article with no title field and no "More detailed info" toggle to click through.

It's also unstyled on purpose — no card, no border, no background — so it reads as plain body copy flowing between the boxed step and section cards around it, the way an intro paragraph or a closing note would in a normal article.

The Text block tab active, with a heading and bullet list typed into its textarea
The Text block tab — one textarea, same formatting rules as Zone 2
A Text block rendered unboxed between two numbered step cards in the live preview
Rendered unboxed, flowing between two step cards
10

Control step numbering across interruptions

Continue from the previous step by default, or explicitly restart at 01.

More detailed infoLess info

A Text block or an Optional Section can now sit between two Numbered Steps, which raises a question the builder used to answer for you silently: does the next step continue the sequence, or start a new one? Every step form has a Step numbering dropdown for this — Continue from the previous step (the default) keeps counting through whatever's in between, and Restart at 01 begins a fresh sequence right there, useful for something like a separate troubleshooting mini-list later in the same article.

This isn't cosmetic renumbering after the fact — the live preview, the exported HTML, and the outline's "STEP NN" tags all derive their numbers from the same one calculation, so whichever you pick is reflected consistently everywhere, immediately.

The Step numbering dropdown set to Restart at 01
Restart at 01, chosen on the step that should begin a new sequence
Live preview showing Step 01, a text block, Step 02, then Step 01 again after an explicit restart
01 → (text block) → 02 continues — then 01 again, explicitly restarted
11

Add images

A checkbox on the step (or optional section) form โ€” Media Library URL by default, with a fallback for embedding a file directly.

More detailed infoLess info

Images aren't a separate part type โ€” they're an optional field on whichever part they illustrate, the same way a step can optionally carry an always-visible command line. Check Add an image on a Numbered Step or an Optional Section, and two tabs appear: Media Library URL and Embed a file directly.

Add an image checked, Media Library URL tab active, with a URL pasted in
Media Library URL โ€” the default tab
Add an image checked, Embed a file directly tab active, showing the file picker
Embed a file directly โ€” the fallback tab

The builder doesn't host images itself โ€” a Custom HTML block just renders whatever markup you paste into it, so an <img> tag needs a URL WordPress can actually serve. In wp-admin, go to Media โ†’ Add New, upload the image, open it, and copy its File URL (something like https://yoursite.com/wp-content/uploads/2026/07/photo.jpg). Paste that URL into the Image URL field, and fill in Alt text โ€” it's required, not optional: the builder blocks Append until it's filled in.

This Media-Library route is the one to prefer: WordPress generates responsive sizes for it and the tag ships with loading="lazy", so it behaves like every other image on the site.

No Media Library access yet, or just prototyping? Switch to Embed a file directly and pick a local file โ€” the builder reads it with FileReader.readAsDataURL() and embeds it as a base64 data URI right inside the exported HTML, no upload step at all. Reach for this only when you have to, though. It skips WordPress's responsive sizing and loading="lazy" entirely โ€” there's nothing left to defer, the bytes are already sitting in the document โ€” and it means the image's full weight travels inside the Custom HTML block's saved content on every page load: the same "nothing is actually deferred" tradeoff as hiding a screenshot behind a toggle in a single self-contained file, except here it's living permanently in the database instead of a one-off page.

A step in the live preview showing a rendered image above its More detailed info toggle
Appended and rendered in the live preview, Media-Library-URL path
12

Build and grab the HTML

Done both downloads article.html and prints the same markup for a clipboard copy.

More detailed infoLess info

Once every step and section is in the outline, click Done โ€” build article.html. This triggers a download and prints the same markup into a Final HTML box โ€” use Copy to clipboard there if you'd rather not dig through your Downloads folder. The output starts with <!-- wp:html --> followed by a <style> block, your confirmation it's pre-shaped for a Gutenberg Custom HTML block โ€” no separate stylesheet to install.

Completed parts list with Done button and the Final HTML box beginning to appear
Done, with the outline finalized
Final HTML box showing wp:html comment and style tag, with Copy to clipboard highlighted
Copy to clipboard as an alternative to the download

Part 2

Get it into WordPress โ€” target the core Custom HTML block, built into Gutenberg since WP 5.0. The Elementor HTML widget some docs mention only matters if you already have Elementor Pro; skip it if you don't.

01

Open the downloaded file as text

Open article.html in a plain-text editor and copy everything โ€” the raw markup, not a rendered preview.

02

Add a Custom HTML block

In wp-admin, edit the page or post, add a block, and search "Custom HTML" โ€” a core block, no plugin required.

03

Paste the markup

Paste it all into that one block โ€” the <style> tag at the top has to travel with the markup it styles.

04

Sanity-check before publishing

Use the block's Preview tab, or the full page preview, and click the toggles once here too.

05

Publish, then verify on the live URL

Hard-refresh the live page and click a couple of disclosure panels to confirm they open and close.

Amber ยท proceed with care

Don't skip the live click-through

This project's history includes a toggle bug that only surfaced under specific timing conditions โ€” it looked fine in the editor and broke live. An editor preview is not proof.


Part 3

The Hostinger / LiteSpeed gotcha โ€” relevant if the site runs on Hostinger's managed WordPress hosting.

Hostinger's managed WP plans typically ship with LiteSpeed Cache active by default, and its default JS optimization settings โ€” minify, combine, and defer inline <script> execution โ€” are exactly the class of interference that breaks toggle logic. It's the same failure mode the project's own test suite exists to catch, just happening at the hosting layer instead of in the code.

Rust ยท troubleshooting

Two ways to stop LiteSpeed from touching the script

Pick whichever fits how much you rely on those optimizations elsewhere.

More detailed infoLess info
  • Per-page exclusion โ€” LiteSpeed Cache has a per-page "disable optimization" setting; exclude just this page or post from JS/CSS optimization.
  • Global opt-out โ€” turn off Minify JS, Combine JS, and Load JS Deferred site-wide, at least while testing, if you're not relying on them elsewhere.

After publishing, purge the LiteSpeed cache and re-test the live URL โ€” cached HTML/JS from before your fix will otherwise keep serving the broken version.


Part 4

Final verification checklist โ€” mirrors what test_static_articles.py checks locally, done visually here because that script only runs against local files, not live URLs.

Rust ยท troubleshooting

If a toggle doesn't behave

Match the symptom to the likely cause before you start guessing.

More detailed infoLess info
SymptomLikely cause
Toggle does nothing, no errorsLiteSpeed deferred or combined the inline script โ€” exclude the page or disable JS deferral
Works in editor preview, not liveCache serving an old version โ€” purge LiteSpeed and hard-refresh
Layout breaks only on phoneCheck the narrow-width (~380px) case specifically โ€” desktop and mobile use distinct layout logic