Custom HTML block
The Custom HTML block lets you paste arbitrary HTML into a post or page. The HTML is rendered as-is at publish time — no sanitisation by default, no transformation. It's a power-user escape hatch.
The block is provided by the flexweg-blocks must-use plugin (always-on).
When to use it
- Third-party embeds that aren't provided by the built-in embed providers (e.g. Instagram, TikTok, CodePen, JSFiddle)
- Custom widgets — Stripe checkout buttons, Calendly inline embed, Mailchimp signup forms
- Override default layout for one specific post (e.g. inserting a custom diagram, a magazine-style pull-quote)
- Microdata / Schema.org that the theme doesn't emit by default
- iframes to other sites you want to embed
For commonly-needed HTML patterns (videos, tweets, multi-column layouts), use the dedicated blocks instead — they're easier to edit and more accessible.
Inserting
/custom html in the inserter, or /html. The block inserts empty.
Editing
Click the block — the right sidebar's Block tab opens with a CodeMirror editor (syntax-highlighted, line numbers). Type or paste your HTML.
The CodeMirror editor supports:
- Full keyboard shortcuts (Cmd+A select all, Cmd+/ comment, Cmd+F find)
- Cmd+Enter for fullscreen mode — opens a modal with the editor at full window size for working on long blobs
- Bracket matching, auto-indent, tag matching
The Custom HTML block displays a rendered preview in the editor (not just the source). So you see the visual result inline as you edit — handy for tuning styles.
What gets rendered
Whatever you paste. No sanitisation — <script> tags work, <iframe> works, <style> works, custom CSS classes work.
This is a deliberate power-user choice. The publisher's standard markdown rendering does sanitise via DOMPurify (strips <script>, dangerous attributes, etc.), but Custom HTML blocks bypass that — they're treated as opaque HTML strings.
Security implications
Because the HTML isn't sanitised:
- A malicious
<script>in a Custom HTML block runs on every visitor's browser - An XSS-vulnerable third-party embed can steal cookies, redirect to phishing pages, etc.
- A self-XSS (you paste something an attacker tricked you into pasting) compromises your site
Only paste HTML from sources you trust:
- ✓ Official embed code copied from a service's "share" UI (YouTube, Stripe, Calendly, …)
- ✓ HTML you wrote yourself
- ✗ HTML someone DM'd you "just paste this in your CMS"
- ✗ HTML from a forum / random web page without auditing first
If you use the CMS to host comments or guest contributions where third parties can paste HTML — restrict the Custom HTML block via plugin (write a post.html.body filter that strips <script> from custom-html blocks unless the post's author is admin).
Markdown round-trip
The Custom HTML block is stored in the post's markdown as:
<div data-cms-block="core/custom-html" data-attrs="<base64-encoded-{html: '...'}>"></div>
The HTML you typed is base64-encoded inside data-attrs to survive markdown processing (otherwise tiptap-markdown might mangle it during round-trip). At publish time, the publisher's filter replaces the marker with the decoded HTML.
Common use cases
Embed code from a service
Most services (Stripe, Calendly, Mailchimp, etc.) provide a snippet:
<!-- Calendly inline widget -->
<div class="calendly-inline-widget" data-url="https://calendly.com/..." style="min-width:320px;height:700px;"></div>
<script type="text/javascript" src="https://assets.calendly.com/assets/external/widget.js" async></script>
Paste it into the Custom HTML block. Both the <div> and the <script> are preserved at publish.
Custom CSS (inline style)
You can scope a CSS override to one post:
<style>
.pricing-table { border: 1px solid #ccc; }
.pricing-table td { padding: 12px; }
</style>
<table class="pricing-table">
…
</table>
The <style> is local to the page (only this post has the rules).
For site-wide CSS overrides, use flexweg-custom-code instead — it injects to every page.
Iframe to an external site
<iframe src="https://my-tool.example.com/preview" width="100%" height="600" frameborder="0"></iframe>
Browsers respect frame-ancestors / X-Frame-Options on the embedded site.
What you can't do
- Server-side includes (SSI) — the public site is static. No
<!--#include-->etc. - PHP / JS runtime evaluation — no PHP runs on Flexweg. Client-side JS works (it runs in the visitor's browser), but anything server-rendered must be done by the embed provider.
- Reference local files via PHP-style paths — e.g.
<img src="<?php echo bloginfo('template_directory'); ?>/foo.png">doesn't work. Use absolute URLs or relative paths from the published page's location. - JavaScript that reads admin / user data — your visitors don't have admin sessions; trying to call Firebase from the public site fails (no auth).
Continue
- flexweg-blocks — full plugin reference
- flexweg-custom-code — site-wide injection (alternative for global tweaks)
- Embeds — built-in providers (use these when applicable)