Polotno
Design Format

Design Format

The canonical Polotno design format: the JSON shape every Polotno design uses. Validate, normalize, and type it anywhere with the @polotno/schema package, or against the published JSON Schema.

The Design Format is the JSON shape every Polotno design uses: the same object store.toJSON() produces and store.loadJSON() accepts. It's a flat, readable document: top-level width / height / dpi, a fonts array, and a pages array whose children are typed elements (text, image, svg, line, figure, gif, video, table, group).

You can work with this format without running the editor. The @polotno/schema package gives you TypeScript types, default values, validation, and a language-neutral JSON Schema: everything you need to generate, validate, or transform designs on a server, in an edge function, or inside an LLM pipeline.

npm install @polotno/schema

What it's for

  • Validate a design before saving it, or when accepting it over the wire.
  • Normalize partial or hand-authored JSON into a complete, canonical document (defaults filled in).
  • Guide LLM output: give the JSON Schema to a model as context, then validate what comes back.

Validate

import { validateDesign } from '@polotno/schema';

// json from store.toJSON(), a converter, or an LLM
const result = validateDesign(json, { mode: 'canonical' });
if (!result.valid) {
  console.error(result.errors); // [{ path, message }, …]
}

Use mode: 'partial' to allow missing defaults, or mode: 'canonical' to reject unknown keys. assertValidDesign(json) throws instead of returning a result. The exported designSchemaLenient / designSchemaCanonical implement the Standard Schema interface (zod, Valibot, Effect Schema, …).

Normalize (fill defaults)

import { normalizeDesign } from '@polotno/schema';

const complete = normalizeDesign(partial); // fills defaults, strips unknown keys
store.loadJSON(complete);

Normalize is idempotent for current-format input. It migrates older schemaVersion documents up first, and it leaves render-derived values (such as text auto-height) for the editor to compute. A design with no schemaVersion counts as the oldest format, so write the current version in new JSON.

Types

import type { Design } from '@polotno/schema';

const design: Design = store.toJSON();

Also exported: Page, Element, TextElement, and every other type in the format.

JSON Schema & LLMs

A language-neutral JSON Schema (draft 2020-12) ships with the package: validate from any language, or give it to a model as context and validate what comes back before rendering:

import schema from '@polotno/schema/design.schema.json' with { type: 'json' };
import { validateDesign } from '@polotno/schema';

// `schema` as context for the model, not as a strict response schema
const design = await model.generate({
  system: JSON.stringify(schema),
  prompt,
});

if (validateDesign(design, { mode: 'partial' }).valid) {
  store.loadJSON(design);
}

Strict structured-output modes do not accept this schema as published, because its objects are open and most fields are optional.

To generate designs with an agent, use the polotno-design skill: it writes the JSON, validates it, renders a proof and exports the files.

Field reference

Every type in the format has a generated reference page with all properties, types, and defaults:

Browse the full list in the sidebar. For the complete package API, see the @polotno/schema README on npm.

@polotno/schema is part of the Polotno SDK. Production use requires a valid Polotno subscription. The format is pre-1.0, so expect additive changes. The current schemaVersion is the default shown on the Design page.

On this page