toilville.com: generated patterns are a content skeleton — fidelity gaps vs the design #102
Labels
No labels
priority
P1
priority
P2
priority
P3
priority
P4
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Toilville/toilville-design#102
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The toilville.com design is now wired into the deck → ForgeBlock → WP FSE
pattern pipeline (#101, merged). Colour is fully tokenised — the export's 508
raw hex literals are gone and CTAs bind to real palette slugs.
But the generated patterns are a token-bound content skeleton, not a rendering
of the design. This issue is the visual evidence, so the call on how far to
take it is yours.
In every image below: left = the design source, right (terracotta border)
= what
build_surfaces.pygenerates today.1. Inline
<em>is displaced to the end of the headingThe hero reads "Governance should be a , not a plugin. primitive".
_collect_text()concatenates the element's own text before recursing intochildren, so emphasised runs inside a heading get moved to the end.
2. Feature bullets reduce to bare en-dashes, and card grids flatten
On Home: the Rituals/Spelwork feature lists become three empty
–paragraphs,and both the 2-up product cards and the 3-up belief cards collapse into one
linear column. No
column_setorfact_setis detected anywhere.Also visible: the RITUALS and SPELWORK logo marks are dropped (no
mediablock).3. Rituals — the Wish/Steward/Ritual triad and the ritual-in-progress demo
The three-column model and the stepped demo both flatten. CTAs survive.
4. Spelwork — terminal block and intent-registry console
The CLI quickstart loses its terminal framing; the console mockup's sidebar +
table become a paragraph run.
5. News — post list loses its structure
Date / title / category become three separate paragraphs per entry, with the
category rendering as an uppercase mono label. No post-list structure, no
actions detected.
6. Contact — the form doesn't survive at all
Name / Work email / Organization / "Interested in" / "What do you need to
prove?" and the Send button are all lost. The footer sitemap flattens.
What the fix looks like
All of these are fixable without changing the converter — it already has an
explicit grammar that beats its heuristics (
_build_labeled). That's how theCTAs were fixed in #101: annotating 16
<a>elements withdata-block="button"and their containers withdata-block="actions"wasenough to produce real
wp:buttons.The same applies here:
data-block="column_set"on the grid containersdata-block="fact_set"withdata-label/data-valuedata-block="media"on the logo wrappersdata-block="fact_set"or a post-list mapping<em>_collect_text()Two things genuinely need a decision rather than annotation:
forgeblock.ymlhasinputas an element, but thepattern renderer has no form mapping. And the submission handler belongs in
the WordPress/plugin layer, not this repo (submodule rules). Options: hand-author
the form as a theme pattern, or use a form plugin and keep only the markup here.
toilville-fsetemplates anyway, these patterns are fine as contentscaffolding and the annotation pass isn't worth it. If they're meant to be the
actual page output, the annotation pass is real but bounded work.
Also worth knowing
spelwork'swp-style.jsonresolves to an empty palette — its paths usecolor.primary, which isn't a token key — so its generated patterns carry nocolour at all.
tctdresolves 1 of its entries. Unrelated to this design, butit's the same mechanism and probably wants its own fix.
Evidence + render harness:
docs/reviews/toilville-site-fidelity-2026-09-09/on branch
docs/toilville-site-fidelity-evidence.Correction — I missed a layer, and it changes the fix
Peter pointed out that this is a three-layer transform, not two. I only
accounted for two:
.dc.htmlcanvasMedia/Decks/templates/toilville/*.forgeblock.jsontoilville/*blocksToilville_Rituals/wordpress/rituals-wp/blocks/Layer 3 already exists — 12 blocks — and the theme already composes them.
toilville-fse/templates/front-page.htmlis currently:So the real defect is narrower and different from what I wrote above:
forgeblock_pattern.pymaps layer 2 → core Gutenberg (wp:paragraph,wp:heading,wp:group,wp:buttons). It has no knowledge oftoilville/*.That is why the right-hand column in every screenshot is flat — it isn't that
the design information was lost, it's that it was rendered through primitives
instead of through the blocks that carry the design.
It also means the
landing.php#101 generates duplicates and degrades whatfront-page.htmlalready does correctly.Most of the "gaps" above are the wrong diagnosis
data-blockannotation is not the fix for most of them. The blocks already havethe right shape:
toilville/hero-homeeyebrow,headline1,headline2,body,cta1*,cta2*,prooftoilville/products-grid+product-cardtoilville/joinband-ctatoilville/spelwork-herotoilville/spelwork-pipeline+pipeline-stagetoilville/spelwork-ctatoilville/spelwork-governance-triadtoilville/wish-formspec="contact",formTitle,buttonText,successMessage,serviceOptionswp:queryTwo specific retractions:
<em>) is not a blocker.hero-homehasheadline1/headline2as separate attributes — the two-line split is structural in theblock, so the emphasis problem doesn't arise on that path at all.
belonged elsewhere. Wrong —
toilville/wish-formalready exists with exactlythe design's fields, including the "Interested in" options and the success
message.
What is genuinely still missing
No block yet for: Rituals hero, the Wish/Steward/Ritual triad, the
ritual-in-progress stepped demo + history, the Spelwork CLI terminal, the
intent-registry console, and "Who we are". Roughly 8 of ~15 section types are
covered.
The blocks are built for the previous site. Their defaults are the old
positioning (
"Made by hand, on purpose","Four tools, one grammar."), not"Governance should be a primitive, not a plugin."The blocks carry their own off-token palette, including the terracotta that
#99 just corrected:
plus
#7394c8×21,#0e0e0e×17,#471f12×16,#587c6d×10,#c66c5a×6.They mix
var(--wp--preset--color--*)with raw hex. So the same tokenisationwork this repo just did needs doing in
rituals-wp.Sorry for the misdirection — the screenshots are still accurate as evidence of
current output, just not as a diagnosis.
Updated screenshots — now rendered through the real
toilville/*blocks#104 (the layer-2→3 emitter) and toilville_rituals#366 (the hero
emphasisattribute) are both in. Here is the same five-page comparison again.
Left = design source. Right (green border) = the generated pattern run
through the blocks' own
render.php.These are much closer to real WordPress output
The earlier set styled the core-block markup with a hand-written stylesheet. This
set actually executes each block's
blocks/<name>/render.phpwith theattributes the pattern carries — only
wp_kses_post,esc_*,get_block_wrapper_attributesandrest_urlare shimmed. It then wraps theresult in the CSS variables WordPress emits from
toilville-fse/theme.jsonpresets, plus every
blocks/*/style.cssverbatim.Not real: WordPress itself, the theme's header/footer template parts, and the
core-block stylesheet (a small stand-in). Faithful preview, not production.
The displaced
<em>is fixedRoot cause was in the converter, not annotation:
handle_data()concatenatedevery text run of a node into
.textregardless of position, so<h1>a <span>b</span> c</h1>flattened to"a c b".Nodenow keeps anordered
partsinterleave, and the heading records which run carries theaccent.
Home
The hero is now a real
toilville/hero-home: eyebrow, accented headline, body,both CTAs, art panel. The closing CTA is a real
toilville/joinband-cta. Alsorecovered here: "Let's build it." — my #101 annotation had promoted the
enclosing
<div>todata-block="actions", which silently swallowed theheading and body copy. Landing went 47 → 49 blocks.
Everything between the hero and the CTA is still core-block flat.
Spelwork
toilville/spelwork-hero+toilville/spelwork-cta.Rituals, News, Contact — unchanged, deliberately
No hero block exists for these surfaces, and the adapters fall through to core
blocks rather than borrowing another page's hero.
What the new shots make obvious
The blocks are styled for the previous site. Look at the Home hero: the
design is sentence-case and tight;
hero-homerenders it uppercase with adifferent type ramp, and carries an art panel (
hands.svg) and a star "proof"line that the current design doesn't have. Retargeting the copy defaults
(#366) didn't touch the layout, and that's the next real decision — it's a
design call, not an engineering one.
Coverage is still 4 blocks of ~15 section types. Hero and closing CTA on two
surfaces. Still no block for: Rituals hero, the Wish/Steward/Ritual triad, the
ritual-in-progress demo, the CLI terminal, the intent-registry console, "Who we
are".
products-grid/product-card/wish-formadapters needcolumn_setand form detection in the converter first.
toilville/wish-formstill isn't wired up — it exists and fits the Contactpage exactly (
spec="contact",formTitle,serviceOptions,successMessage), but nothing emits it yet, so Contact is still flat.Two corrections from earlier in this thread
#cc5c37, 0× canonical" count was a plain grep that didn'tdistinguish fallbacks. They are all
var(--wp--preset--color--primary, #cc5c37), so the blocks do referencethe preset and already rendered the corrected
#c05734. Only the fallbackliteral was stale; #366 updates it.
all
render.phpfiles passphp -l. That closes the caveat on #366.Harness + images:
docs/reviews/toilville-site-fidelity-2026-09-09/after/ondocs/toilville-site-fidelity-evidence(#103).Migrated to the current design
The last set showed the blocks rendering the previous site's layout —
uppercase headline, art panel, star proof. That's now fixed. Same comparison,
third pass.
Left = design. Right (green) = the generated pattern through the real
render.php+ block CSS.The Home band is close: hero with the accent run inline, the
[ 01 ]index onthe heading's baseline, and both product cards tinted by product with their
feature lists intact.
What changed
toilville_rituals#366 — layout migration:
hero-homeis a single column on a warm-to-white wash with the sun marktop-right, sentence-case at
clamp(44px, 6vw, 82px)/1.02/-0.03em. Thetwo-column art layout and the stars are gone;
proofstill works but rendersnothing when empty.
products-gridis the "What we make" band — primary-container wash, monoindex on the heading baseline, auto-fit grid.
product-cardgainsfeatures,linkLabel/linkUrlandrituals/spelworkmodes. It is now dynamic (render.php,savereturns null) — a static block whose markup changes trips WordPress's
"unexpected or invalid content" check on saved posts; a dynamic one
re-renders.
class-site-blocks.phpnow decidesrender_callbackby whethera block ships a
render.phprather than assuming children are static.toilville-design#105 — two converter fixes and an adapter:
<ul>/<ol>→fact_set. Lists fell through to a recurse that walkschildren only, so an
<li>'s own text was dropped and the decorative<span>—</span>was all that survived. That was the(--)bug.<img>→ image block. It was being dropped, taking the product logos withit — and the logo URL is the only thing that says which card is Spelwork.
Without it both cards came out terracotta.
_products_gridadapter emits the band asproducts-grid+ oneproduct-cardper card.toilville-design#106 —
primary-container/secondary-containerWP presetslugs, so the band tint is a token rather than a literal.
Also worth noting
The harness itself was under-reporting: it only matched self-closing block
comments, and
products-gridwraps InnerBlocks. Its section chrome wasrendering fine and simply wasn't in my screenshots. Fixed.
Still open
so the converter doesn't treat them as actions and they don't reach the
adapter. The block renders them when given
linkLabel; nothing supplies it.but
product-cardhas nologoattribute and the SVGs aren't in the plugin.those surfaces, and
toilville/wish-formstill isn't wired to Contact.Images:
docs/reviews/toilville-site-fidelity-2026-09-09/migrated/on #103.Ready for sign-off — rendered from
mainin both reposEverything below comes from merged code, not branches:
toilville-design@main— the generated patternsToilville_Rituals@main— thetoilville/*blocks and their CSSLeft is the approved design canvas. Right is what
toilville-fse+rituals-wpactually produce today.Home
Hero and the "What we make" band both track the design: accent run inline, sun
mark,
[ 01 ]index on the heading baseline, both cards tinted by product withtheir feature lists.
Spelwork
spelwork-hero+spelwork-cta. The middle sections still fall back to coreblocks.
Rituals
News
Contact
What ville is signing off on
Ready: Home hero, the products band, the closing CTA, and the Spelwork hero
and CTA — all rendering through
toilville/*blocks with token-bound colour.Zero raw hex reaches the page; the palette comes from
theme.jsonpresets.Not ready, and visible above: Rituals, News and Contact are still core-block
flat. There is no hero block for those surfaces, so the adapters deliberately
fall through rather than borrow another page's hero. Also missing: per-card
links, the product logos, and
toilville/wish-formwired to Contact.So this is a partial migration. Home and Spelwork are close to the design;
the other three pages are structured content, not the design.
Deploying
Two pieces, and they must go together — the theme's
front-page.htmlcomposesblocks that live in the plugin:
Theme —
rsyncperudg/products/wp-themes/README.md:Bind-mounted, so it is live immediately with no container restart.
Plugin — the
Deploy rituals-wpworkflow (workflow_dispatch), targetwordpress, activatetrue.Order matters. Deploy the plugin first. The theme's front page references
toilville/hero-home,toilville/products-grid,toilville/testimonialandtoilville/joinband-cta; if the theme lands first those render as missingblocks.
One thing to check on the live site after deploying:
product-cardchangedfrom a static-save block to a dynamic one. That is the safe direction — a
dynamic block re-renders instead of tripping "unexpected or invalid content" —
but any page that already embeds a product card should be opened once to
confirm.
Still open
#103 carries every image in this thread, including these. It is still
unmerged, so if that branch is deleted the screenshots in all four comments
break.
⚠️ Images above are broken — working links here
#103 merged (as #107) and its branch was deleted, so every image in the four
comments above now 404s: they pointed at
raw/branch/docs/toilville-site-fidelity-evidence/….The files are all on
mainnow. Ville — read this comment, not the onesabove.
Sign-off set —
mainin both reposLeft is the approved design canvas. Right is what
toilville-fse+rituals-wpproduce today.Home
Spelwork
Rituals
News
Contact
What you're signing off on
Ready: the Home hero, the "What we make" band, the closing CTA, and the
Spelwork hero and CTA — all rendering through
toilville/*blocks withtoken-bound colour. No raw hex reaches the page.
Not ready, and visible above: Rituals, News and Contact are still
core-block flat. There is no hero block for those surfaces, so the adapters
deliberately fall through rather than borrow another page's hero. Also missing:
the per-card links, the product logos, and
toilville/wish-formwired toContact.
So this is a partial migration — two of five pages match the design; the
other three are structured content.
Deploying
Two pieces, and the plugin must go first — the theme's
front-page.htmlcomposes blocks that live in the plugin, so if the theme lands first they render
as missing blocks:
Deploy rituals-wpworkflow (workflow_dispatch), targetwordpress, activatetrue.rsync -av --exclude='.git' wp-themes/toilville-fse/ toilville-forge:/opt/spelwork/wordpress/themes/toilville-fse/(bind-mounted, live immediately, no restart).
After deploying:
product-cardmoved from a static-save block to a dynamicone. That is the safe direction — dynamic re-renders instead of tripping
"unexpected or invalid content" — but open any page that already embeds a
product card once, to confirm.
Earlier sets, for the record
Coverage, in numbers — this is NOT 1:1 with the design
To be unambiguous before sign-off. Counting Gutenberg blocks in the generated
patterns on
main:toilville/*blocksBy design section, 5 of ~20 are covered by a real block:
hero-homeproducts-grid+ 2 ×product-cardfront-page.htmluseswp:queryhere)joinband-ctaspelwork-herospelwork-ctawp:queryis arguably correct here)toilville/wish-formexists and fits exactly, but nothing emits itWhy Home looks better than it is: the hero and products band dominate the
screenshot. Everything below them on that page is flat paragraphs.
What 1:1 would need
ritual-in-progress demo, the CLI terminal, the intent-registry console, "Who
we are", "What we believe".
wish-form→ Contact,testimonial,verdict-card,pipeline-stage.them as plain anchors, so they never reach the adapter) and the product logos
(the image block survives and picks the card tint now, but
product-cardhasno
logoattribute and the SVGs aren't in the plugin).So what is deployable today
The Home hero and products band, the closing CTA, and the Spelwork hero and CTA
— those match the design and are token-bound. The rest is structured content
in the right order with the right copy, styled by the theme rather than by the
design.
That is a real improvement over what is live, and it is safe to deploy. It is
not the design. Worth deciding explicitly which of those two you are approving.
Every design section now renders from the vocabulary
Rendered from
mainin both repos. Left is the approved canvas; right is whattoilville-fse+rituals-wpproduce.Home
Rituals
The full ritual demo now renders: window chrome, steward avatar,
step 3 of 5pill, five steps with correct markers and trailing meta, and the signed history
timeline.
Spelwork
Terminal with command/output tinting, and the console with its dark rail,
selected item, typed table columns and pulsing attestation dot.
News
Contact
What changed since the last set
Everything is now driven by the universal ForgeBlock vocabulary, with the
WordPress client deciding how each block looks. That was the correction Peter
called for: ritual blocks are universal, clients render them.
Copy reaching rendered HTML: 98% — Home and Rituals 100%, Spelwork 98%,
News 94%, Contact 92%. The remainder is contractions inside excerpts.
One thing I want on the record
The plan said to emit the demo's history as
lineage_entry. I didn't, andreverted that work.
lineage_entryhas a CI-enforced contract —mode,consent_tier,hash,lineage_id,timestamp_msall required. Itis a signed, tiered, identified provenance record. The design's history rows are
a depiction of provenance on a marketing page, carrying no lineage id and no
hash. Emitting them as
lineage_entrywould have meant inventing signing datafor a website, or relaxing a governance contract to fit a mockup.
It uses
statusfor the steps (exactly the UDG enum, exactly the design's threestates) and
fact_setfor the history. No new vocabulary block was needed —only
status.meta, for the trailing detail, declared and type-checked.Known gaps
./rituals-logo.svg, relative to the deck template directory, which resolvesto nothing once WordPress serves the pattern — and the files are not in the
plugin's asset store. The client suppresses them with a comment rather than
emitting a broken
<img>. Closing it means shipping the five SVGs intoblocks/_shared/assets/and resolving them server-side.were not split out. In WordPress they are
parts/header.htmlandparts/footer.htmlin the theme.blocks. Visible above.
Deploying
Two pieces, plugin first — the theme's
front-page.htmlcomposes blocksthat live in the plugin, so a theme-first deploy renders them as missing:
Deploy rituals-wpworkflow (workflow_dispatch), targetwordpress,activate
truersync -av --exclude='.git' wp-themes/toilville-fse/ toilville-forge:/opt/spelwork/wordpress/themes/toilville-fse/Post-deploy:
product-card,verdict-cardandpipeline-stageall moved fromstatic-save to dynamic blocks. That is the safe direction — a dynamic block
re-renders instead of tripping "unexpected or invalid content" — but any page
already embedding one is worth opening once.
Sign-off renders — the fidelity round (full pages)
A correction first. The renders I posted earlier in this thread were cropped at 2600px and made with a preview that flattered production, so most of what was wrong below the fold never showed. They also still showed Home's product cards after a change of mine had broken them. This set is full-length, rendered the way WordPress will actually lay the pages out.
(Separately: every image earlier in this thread went 404 when its branch was deleted after merging. That's restored.)
Left is your canvas. Right is what ships, rendered from the open PRs.
Contact, after sending. The canvas shows both states at once. The site shows the form, then swaps in the confirmation:
What changed since the last set
Known differences — your call
To ship
Merge toilville_rituals #390, then the toilville-design branch
feat/fidelity-round. The renders themselves are ondocs/signoff-renders-2026-09-11. #123 and #379 are already in.The two toilville-design PRs aren't open yet: Forgejo returns
500 Internal Server Errorwhen creating a PR in this repo right now (three attempts each, including a docs-only one). Both branches are pushed and merge cleanly ontomain; I'll open them once it recovers.Deploy the
rituals-wpplugin first (Deploy rituals-wp, targetwordpress, activate), then the theme. Then create four pages with the slugsrituals,spelwork,newsandcontact. They can be empty; the theme's templates render them.ville — does this read as your design?
Update — before/after, and one font decision
The mono face changed. DM Mono is gone. It was never a Toilville decision: it arrived in a bulk token expansion and spread from there. Peter chose the system monospace, which is SF Mono on Apple and Consolas on Windows. Every eyebrow, tag, breadcrumb and form label below uses it. The renders in my previous comment still show DM Mono; their layout is unchanged.
Before/after, three columns per page: your canvas, then what
mainships today, then what the PR ships. The middle column is what deployingmainas it stands would put on the site:Where it stands
500 Internal Server Errorfor every PR creation in that repo, including a docs-only one. The branch is pushed and merges cleanly:feat/ship-the-pages. The renders are ondocs/signoff-renders-2026-09-11.feat/ship-the-pages.The known differences listed in my previous comment still stand. They're yours to call.
The design PRs are open: toilville-design #126 (the pages, and the system mono) and #127 (these renders). toilville_rituals #391 is merged, so #126 is the last merge before deploy.
The
500was a stale lock left on the server's copy of this repo by an interrupted git write. It's cleared; nothing else was affected.