EmVB
v0.2.1 is on npmfor EmDash CMS 1.2

Design on a canvas.Ship plain HTML.

Style Typography

Colour
Style
Weight

Pick a value: the selected heading restyles live, in CSS only.

EmVB puts a full visual editor inside the EmDash admin: layers, live styles, states, devices and a site-wide design system. Visitors get the markup and the CSS, not the builder.

  • React + Kumo editor in the EmDash admin
  • Plain HTML and CSS on the public site
  • Node + SQLite or Cloudflare + D1
The EmVB editor: Layers tree on the left, a page with three trip cards on the canvas, a selected card with its Style panel on the right.
The Northfold hero on a phone, with the navigation hidden and the buttons stacked.

Features

A real builder, not a block editor

EmVB covers what site builders expect from a visual editor, and keeps the output small enough to read.

01Build

Drag, drop, nest
Drop elements from the Add panel onto the canvas, then reorder and nest them in the Layers tree or with the keyboard.
Edit text in place
Double-click a heading or paragraph on the canvas and type.
Copy, paste, undo
Copy elements and styles between pages, and step back through up to 100 edits with Ctrl or Cmd + Z.
An icon library
Over 14,000 icons from Lucide, Font Awesome Free, Tabler and Remix, or upload your own SVG.
Synced sections and templates
A Section element renders a shared part live. New pages can start from a page template.

02Style

Four states
Normal, Hover, Focus and Active, each with its own styles, plus transitions between them.
Per device
Tablet (up to 1024 px) and mobile (up to 767 px) overrides, and hide on device.
Backgrounds
Images, linear, radial and conic gradients with up to 10 stops, overlays and background video.
Grid and flexbox
Flexbox and CSS Grid containers, with 1 to 12 columns and spans on the children.
Entrance animations
Fade, slide and scale in, with a delay. Reduced motion turns them off.

03Design system

Variables
Colours, fonts, font sizes and spacings, published as CSS custom properties.
Classes with a clear order
When two classes set the same property, the one lower in the list wins. Local styles still win.
Tag defaults
Set the look of every h1, paragraph or link once.
Staged until published
Site style changes wait as a draft until you press Publish styles, then reach every live page.
Import and export
Move a design between sites as JSON.

The Add panel

All 39 elements, grouped the way the editor shows them. Tab panels come with their Tabs.

Layout

  • Container
  • Section
  • Spacer
  • Divider
  • Theme section
  • Div Block
  • Flexbox
  • Grid
  • Tabs
  • Accordion
  • Accordion item

Content

  • Heading
  • Text
  • Label
  • Link
  • Button
  • List
  • Image
  • Icon
  • Video
  • SVG
  • Menu
  • Menu item

Dynamic

  • Post Title
  • Post Excerpt
  • Post Content
  • Post Image
  • Post Link
  • Post Date
  • Post Author
  • Loop
  • Pagination

Form

  • Form
  • Text input
  • Textarea
  • Select
  • Checkbox
  • Radio
  • Submit

Styling

Every style property, in every state, on every device

01States

Style the hover, not just the resting state

Pick Normal, Hover, Focus or Active above the style sections and edit as usual. EmVB writes the matching selector, with Focus mapped to :focus-visible.

  • Transitions between states, switched off under reduced motion
  • A dot on each state that has values
  • Works on elements and on classes

02Devices

Tune every breakpoint on the same canvas

Switch the canvas to Tablet or Mobile and every change becomes an override for that size. Desktop values stay where they are.

  • Tablet up to 1024 px, mobile up to 767 px
  • Hide on desktop, tablet or mobile
  • Overrides cascade down: desktop, then tablet, then mobile

03Site styles

One design system for the whole site

Variables, classes and tag defaults live in the Site styles drawer, next to the canvas. Changes wait as a draft until you press Publish styles, then reach every published page without republishing them.

  • Colour, font, font size and spacing variables
  • Classes with states; the lower class in the list wins
  • Design import and export as JSON
The Site styles drawer on the Variables tab, with Export and Import on their own row under the title, eleven colour variables with usage counts, and font variables below.
Open full size
The Classes tab of the Site styles drawer, with the Button class open and its Normal, Hover, Focus and Active state tabs.
Classes tab

04Backgrounds

Layered backgrounds without custom CSS

Give any box an image from the media library, a gradient and a colour overlay on top. Or a background video.

  • Size, position and repeat for images
  • Linear, radial and conic gradients with up to 10 stops
  • Colours from variables, or as HEX, RGB or OKLCH

What visitors get

Built in the editor. Served as HTML and CSS.

Northfold is one EmVB page inside a header and footer from the Theme Builder. The only EmVB scripts it loads are for its popup and its tabs. The enquiry form uses the forms plugin’s script.

The published Northfold home page: a header with navigation and a hero photo of green ridges under the headline Walk the wild edges of the North.
The Northfold hero on a phone, with the navigation hidden and the buttons stacked.
The trip cards stacked into one column on a phone.

Real screenshots from the Node demo. Northfold is a made-up company; photos from Unsplash via Lorem Picsum.

Theme Builder

Headers, footers, templates and popups, shown where you say

Theme parts are built in the same editor. Display conditions include or exclude them for the entire site, the front page, a collection, a single entry, archives, taxonomy terms, search or the 404 page. The most specific part wins, and an exclude beats an include.

The Theme Builder list in the EmDash admin with a page template, a 404 page, a popup, a footer and a header, all published.
A popup theme part open in the editor; the settings panel shows an Include Entire site condition and an On click trigger for #get-guide.

12 part types

  • Header
  • Footer
  • Error 404
  • Search Results
  • Single Page
  • Single Post
  • Archive
  • Loop Item
  • Section
  • Page template
  • Popup
  • Float

Popup triggers

  • On page load
  • After a delay
  • On scroll
  • On click
  • On exit intent
  • After inactivity

Limit how often a popup shows and on which devices. Close and Escape return focus.

Floating bars and corners

A Float sits on the top or bottom edge, or in a corner. Visitors can close it until their next visit, with no cookie.

Dynamic content

Single, archive and loop item parts use Loop, Pagination and post elements: title, excerpt, content, featured image, link, date and author.

More of the editor

  • The hero heading being edited in place on the canvas: the text now reads Walk the wild edges of the North, together, in the heading's own font and colour.Open full size
    Double-click any text on the canvas to edit it in place.
  • The Pages VisualBuilder list in the EmDash admin: five pages with their paths, Published or Draft status and last-edited time, and a New page button.Open full size
    Pages: every EmVB page with its path and status, one click from the editor.
  • The EmVB editor in the EmDash dark theme, with the hero heading selected and its Typography section open.Open full size
    The editor follows the EmDash admin theme, light or dark.
  • A Grid element with three trip cards selected; the Content panel sets Columns to 3.Open full size
    CSS Grid containers, from 1 to 12 columns, with spans on the children.
  • An enquiry form on a dark green band, selected in the editor: bordered name, email, trip and message fields, a checkbox and a Send enquiry button, with the Trip enquiry form chosen in the Content panel.Open full size
    Form elements post to the EmDash forms plugin, with clean default fields you can restyle.
  • The published Northfold page with the route guide popup open over a dimmed hero.Open full size
    The same popup on the published page, opened by its click trigger.

Under the hood

From canvas to markup in four steps

  1. Edit

    A full-screen React and Kumo editor inside the EmDash admin. The canvas is a sandboxed iframe with scripts off.

  2. Store

    Each page is one JSON layout in the emvb_pages collection, checked against schema version 12 and the 512 KB limit before it is saved.

  3. Render

    On the server, the layout and the site design become HTML and CSS. Unknown element types render nothing.

  4. Serve

    The host’s Astro route places the result inside its own layout. Visitors download markup and styles.

layout.jsonstored
{  "id": "page-headin002",  "type": "heading",  "props": { "text": "Walk the wild edges of the North.", "level": 1 },  "style": {    "color": { "var": "white" },    "maxWidth": { "value": 860, "unit": "px" }  },  "devices": { "mobile": { "fontSize": { "value": 46, "unit": "px" } } }}
page.html + page.cssserved
<h1 class="emvb-heading emvb-e-page-headin002">  Walk the wild edges of the North.</h1>
.emvb-e-page-headin002{max-width:860px;color:var(--emvb-c-white)}@media (max-width: 767px){.emvb-e-page-headin002{font-size:46px}}

The hero heading of the Northfold demo, as saved and as published (line breaks added).

Performance and safety

Small output, strict input, lots of tests

Measured on the 0.2.1 release with the project’s own benchmark and test commands.

median server render of a 300-element page, p95 2.3 ms, against a 20 ms budget
1.1msbun run bench:render, 200 runs
of gzipped CSS for that 300-element page, against a 15 KB budget
995Bbun run bench:css
unit and component tests passing, none failing
2,323bun run test
seeded bugs on record, each one proven to make a test fail
1,518scripts/seeded-bugs.json
  • Validated on save and on read

    Every layout is checked against the schema before it is stored and again before it renders. Pages are capped at 512 KB and the design at 256 KB.

  • Sanitised output

    The HTML serializer escapes by construction, links pass a protocol allowlist and SVG is sanitised. The editor canvas is a sandboxed iframe with scripts off.

  • Role-checked writes

    Every write route needs an editor role or above. Logs carry ids and error codes, never page content.

  • Accessible by default

    Focus styles target :focus-visible, accordions are native <details>, and animations stop under prefers-reduced-motion.

Get started

Install it, or run the demo first

EmVB 0.2.1 is on npm as @perkyzz/emvb. Or clone the repository and try it on the Node demo; the Cloudflare demo with D1 and R2 runs with bun run demo:cf.

A

Add it to your EmDash site

bun add @perkyzz/emvb# or npm i; your site’s build compiles it

Then register emvb() next to your other EmDash plugins and add the public route. The guide covers both, plus forms.

Read the install guide

B

Run the demo locally

git clone https://github.com/PerkyZZ999/EmVB.git

bun install# Bun 1.4 and Node 24 are verified

bun run demo:node# http://127.0.0.1:4411

  1. Sign in with the dev-only bypass link below.
  2. Open Pages VisualBuilder and click Set up EmVB once.
  3. Click New page, edit the heading and Publish. It is served at /your-slug.

Just looking? Try the editor in your browser: no install, and your edits stay on your device.

FAQ

Questions people ask first

Does EmVB add JavaScript to my site?

Not to a normal page. A few small scripts load only where a page needs them: popups, floating bars, keyboard support for tabs (which already work with CSS alone) and Escape for menu dropdowns. Forms use the EmDash forms plugin’s own script.

Which EmDash version does it need?

EmDash CMS 1.0 to 1.2 (built and tested on 1.2). EmVB is a native plugin. It adds its own section to the admin sidebar with Pages VisualBuilder and Theme Builder.

Where does it run?

Anywhere EmDash runs. The repository has two demos: Node with SQLite, and Cloudflare Workers with D1 and R2. The same stored layout renders the same way on both.

Can editors break the site?

Layouts are validated against the schema on save and again on read, so a malformed page is refused rather than rendered. Size limits apply, SVG is sanitised, and only editors and above can write.

Can I move a design to another site?

Yes. The Site styles drawer exports the site design as JSON, and the other site imports it.

Is it on npm?

Yes: @perkyzz/emvb, version 0.2.1. It ships TypeScript source and your site’s build compiles it. The install guide covers the plugin entry and the public route.