Why a typed-blocks blog beats WYSIWYG
You write an article, you click bold, you paste an image, you publish. Three months later, you want that same content in a newsletter and an RSS feed, and that's where it falls apart: `<span style>` tags slapped in from Word, a table that breaks on mobile, a duplicated h1 that wrecks your SEO. The problem isn't your editor — it's that you store free HTML instead of storing data.
At Zylior we treat every article as a list of validated typed blocks, not an HTML soup. That changes everything: a single piece of content renders to a web page, an email and plain text, without ever breaking. Here's why this model beats WYSIWYG, with the technical detail.
WYSIWYG stores HTML, and HTML drifts
A WYSIWYG editor produces an HTML string that you stash in your database. The catch: that string is unconstrained. Nothing stops an orphan `<div>`, a `style="font-family:Calibri"` pasted from Word, an `<h1>` in the middle of the body, or a tag that's never closed. You don't see it in the editor — it "fixes" it silently on display — but the day you pull that HTML out of its context (email, mobile app, API), it breaks.
- Parasite inline styles: a copy-paste from Word/Notion injects `mso-*`, hardcoded colors, `<o:p>`. Your theme no longer controls anything.
- Invalid structure: duplicated `<h1>`, `<h3>` with no `<h2>` parent → hierarchy broken for SEO and screen readers.
- HTML that doesn't survive email: Gmail strips half your tags, your `<figure>` becomes unreadable.
- No re-render guarantee: the same HTML rendered by two engines (web vs mail client) gives two different results.
An article = validated data, not markup
The alternative: you never store HTML, but an array of typed blocks, each with a known shape validated at write time. A paragraph is `{type:"p", text}`; a section heading is `{type:"h2", text}`. Inline is restricted to a whitelist (`bold`, `italic`, https links). Anything that doesn't fit the schema is rejected on save, not "tolerated on display".
{
"meta_title": "Blocs typés > WYSIWYG",
"blocks": [
{ "type": "p", "text": "Accroche en **gras** et [un lien](https://zylior.com)." },
{ "type": "h2", "text": "Une section" },
{ "type": "list", "ordered": false, "items": ["Item 1", "Item 2"] },
{ "type": "callout", "tone": "tip", "text": "Un encadré." }
]
}
From there, you validate with a schema (Zod, JSON Schema, whatever): `type` in the enum, `text` capped at N characters, `items` an array of strings, `tone` in `{info,warn,tip}`. An invalid article cannot be saved. You move the rigor from display to write time — where an error costs an error message, not a page broken in prod.
One content, three guaranteed renders
This is the real operational win for a solo founder. Because a block is semantic data ("this is a heading", "this is a list") and not markup, you write one renderer per target and each block knows how to render anywhere:
- Web: `h2` → `<h2 class="...">` with your design system, `code` → syntax highlighting.
- Email: the same `h2` → an inline-styled HTML table compatible with Gmail/Outlook; the forbidden types can't even show up.
- Plain text / RSS / LLM: `h2` → `## Title`, `list` → markdown bullets. Perfect for summarizing an article for an agent or feeding a digest.
- JSON-LD: you automatically derive `articleBody`, `headline`, `wordCount` from the blocks, without parsing any HTML.
Preview = published, and SEO genuinely under control
With free HTML, your preview often uses a different rendering engine than prod (the editor vs the site): what you see isn't what ships. With typed blocks, the preview calls exactly the same web renderer as publication. Zero surprise: if the preview looks right, the published version is identical. On the SEO side, because the structure is guaranteed, you control what WYSIWYG lets drift: a single `h1` (derived from `meta_title`, never in the body), a consistent `h2`/`h3` hierarchy, a `meta description` capped at 140-160 characters, a clean `canonical`, and an `Article`-type `JSON-LD` derived mechanically from the blocks. Your markup is valid by construction, not by hope.
To be honest, it's not free: you maintain your renderers and the editor is more constrained than an "anything goes" WYSIWYG (no magic Word paste). For a SaaS portfolio blog where you want reliability and multi-channel, it's the right trade-off. Concretely, to get started: define an enum of types (`p`, `h2`, `h3`, `list`, `code`, `callout`, `quote`), write a schema that rejects everything else, wire up a web renderer and a text renderer (email comes later), and point your preview at the prod web renderer. You'll have a blog where the preview never lies, where the same article ships in a newsletter without rework, and where your SEO is correct by default — not through manual vigilance.
The newsletter
By subscribing you agree to receive the Zylior newsletter. One-click unsubscribe in every email.