Why rectangles?

The mental model behind m0saic

// what is m0

m0 is a layout language. A single string describes how rectangles subdivide inside a canvas — no pixels, no coordinates, just structure.

2(F,3[F,F,F])→
// two columns, left gets 70%
10(>,>,>,>,>,>,F,>,>,F)

// three equal rows
3[F,F,F]

// nested: 2 columns, right split into 3 rows
2(F,3[F,F,F])

// gap between two tiles
5(F,>,>,-,F)

// overlay: content layered on top
2(F,F){F}

The language is small. () split columns, [] split rows. F claims a tile, > donates space forward, - marks empty space, and {} layers content on top. That’s the entire surface.

// why not css?

CSS is a layout solution for the browser. Flexbox, Grid, and absolute positioning solve responsive, interactive UI. m0 solves a different problem.

No floating point
m0 uses only integer arithmetic. A 3-column split of 1920px produces columns of exactly 640, 640, 640 — not 640.000001. When pixels don’t divide evenly, remainders are distributed outside-in to keep the layout balanced. No rounding errors, no sub-pixel drift.
String-native
Layouts are plain strings. Concatenate, template, store, diff, and version them like any other text. Every language already has the tools — m0 piggybacks on string composition.
Infinitely composable
Any tile F can be replaced with any valid m0 expression — one character or thousands. 2(F,F) becomes 2(3[F,F,F],F) by swapping one token. No special API — just strings.
Portable
The same m0 string means the same pixel-exact rectangles wherever it is parsed. The reference implementation is JavaScript; the spec is small enough to port to any language in an afternoon, and the paper is written so you can.
Deterministic
Same string + same resolution = same rectangles. No layout engine quirks, no browser differences, no reflow. Parse it today, parse it in five years — identical output.
Low implementation bar
Any language with integer arithmetic and string concatenation can build a valid m0 library. No graphics stack, no layout engine, no dependencies — and it immediately reads and writes every .m0 file out there.

The trade-off: a bare m0 string does not reflow. It describes one canvas, exactly. Adapting to a canvas is the template’s job — a template derives its geometry from the size it is asked for, so the same template renders 16:9, 9:16 and 1:1 with a different string each time, and every one of them is deterministic. When your output is a rendered frame, that beats dynamic reflow.

// throw away the timeline

Traditional video tools organize content on a timeline. Layers stack vertically, clips stretch horizontally. Time is the primary axis.

TIMELINE
time →
→
GEOMETRY
space

That works for editing. But for generating video programmatically — bar charts, dashboards, data visualizations, social media templates — time is the wrong abstraction. The hard part isn’t sequencing clips. It’s placing content in space.

m0saic uses geometry as its base. m0 is the geometry solution.

Instead of a timeline, you describe a layout. Each rectangle becomes a content slot. Fill the slots with images, videos, text, colors — or another layout, or a whole template. Frames are composited onto a final canvas based on the m0 geometry, and the engine hands the result to ffmpeg.

Time is just another property of how that static rectangle behaves — enable at 2s, fade in over 500ms, hold for 3s, fade out. The rectangle itself is absolute. Everything else is configuration.

Traditional video scales horizontally — more clips on a longer timeline. m0saic scales vertically through composition. A dashboard is a layout that nests calls to opinionated templates (bar-graph, donut, leaderboard), each of which returns its own m0 geometry and sources to fill those rectangles. That is what the Compose surface in Mosaic Web builds and what a .mosaicx file stores. Complexity grows through depth, not duration.

// rectangles → video

Here’s a real example. The @m0saic/alpine/bar-graph/v1 template takes data and renders an animated bar chart. One CLI call:

$ npx m0saic make @m0saic/alpine/bar-graph/v1 \
  -w 1920 -h 1080 \
  --props '{"values": [72, 45, 88, 31, 66], "orientation": "vertical", "preset": "dark"}' \
  -o bar_chart.mp4
1920 × 1080... chars

Same template, same data, different resolution. The template maps data to geometry. The geometry maps to pixels. ffmpeg renders the output. No timeline, no manual placement — and if you would rather see it than type it, Make in Mosaic Web runs the same template against a live preview and hands you this command.

// where this fits

m0saic is not a video editor. It’s a video compiler.

Batch rendering
Generate 1,000 variations of a template with different data. Each run is a CLI call with different props.
Cron jobs
Render a daily dashboard video from live data. Schedule it, forget it.
CI/CD pipelines
Generate preview videos on every commit, deploy video assets alongside code.
Cross-platform output
Same template renders 16:9 for desktop, 9:16 for mobile, 1:1 for social. The layout adapts, the data stays the same.
Pick, tweak, render
Open a template in Make, edit its props against a live preview, press Make. No code — the template is the program, the props are the only input.
Agents writing templates
A template is a typed TypeScript function with a verify loop. Hand a coding agent the starter repo and a sentence; it ships a template that renders. See templates by agent.

A traditional editor is an interactive tool whose output depends on the hands on it. m0saic is interactive too — Make, Layout and Compose are all live — but the output never depends on the hands: the same template, props and canvas give the same pixels from the CLI, from Mosaic Desktop, or from a browser tab.

// the model

template→m0 string→rectangles→engine→ffmpeg→output
→A template takes props and the canvas size and generates its own m0 geometry from them — the layout is computed, not drawn.
→That layout string divides the frame into rectangles.
→Each rectangle is a content slot with exact pixel bounds, and the template fills each one with a source.
→The engine turns that document into a render: it plans the work, renders nested layouts into their own intermediates, splits a big frame into chunks and stitches them back, composes the filter graph and the exact ffmpeg commands for each pass, manages the workspace those passes share, and writes the sidecars that describe what it did. It is the same engine in the CLI and inside Mosaic Desktop, and what Mosaic Web hands your render to.
→ffmpeg renders the final output.

That’s why rectangles. They’re the atom of visual composition — simple enough to reason about, powerful enough to express any grid-based layout, and deterministic enough to compile.

// install the language

m0 is open and versioned on its own. The parser, the formats, and the spec are all public — you can build on the language without m0saic at all. The language is the bottom of a stack of open packages that runs up through the template libraries; only the render engine and the apps are closed. The Open Core page lays the whole stack out.

npm install @m0saic/dsl

// ready to type it yourself?

The interactive course in Mosaic Web walks the string one character at a time on a live canvas — no install, no account.

Learn the language →