Compact Design: a JSON language models can write and Figma can import

작성자

카테고리:

← 피드로
DEV Community · Elliot Silver · 2026-08-14 개발(SW)
Cover image for Compact Design: a JSON language models can write and Figma can import

Elliot Silver

Don’t ask a model to speak Figma’s plugin API. Don’t ask it for CSS and hope a screenshot is a design.

I wanted a format a model can write, a schema can reject, and Figma can turn into native, editable frames.

That’s Compact Design.

It’s a small JSON language. @compact-design/core validates, normalizes, lints, and patches it. The Figma plugin is the first adapter. Core never depends on Figma.

Repo: github.com/Elliot727/compact-design

A card looks like this

{
  "canvas": {
    "id": "desktop",
    "name": "Desktop",
    "width": 1440,
    "height": 900,
    "fill": "#F8F5EE"
  },
  "nodes": [
    {
      "id": "card",
      "type": "FRAME",
      "x": 48,
      "y": 48,
      "w": 320,
      "h": 200,
      "fill": "#FFFFFF",
      "cornerRadius": 16,
      "layout": {
        "direction": "VERTICAL",
        "padding": 24,
        "itemSpacing": 12
      },
      "children": [
        {
          "id": "title",
          "type": "TEXT",
          "w": 272,
          "h": 40,
          "text": "A quieter kind of stay.",
          "font": { "family": "Arial", "style": "Bold", "size": 24 },
          "fill": "#23221E"
        }
      ]
    }
  ]
}

Enter fullscreen mode Exit fullscreen mode

Required on a node: w and h. type defaults to FRAME. IDs are generated if you omit them — give anything you’ll update later an explicit one.

Hex fills. HUG / FILL / FIXED. Angle gradients. Elevation presets. Variables, styles, components, prototypes, images. One current schema. No version soup.

This is the input API. Not Figma REST. Not a properties wrapper. Not 24px.

What the engine actually does

Compact Design JSON

@compact-design/core
schema → normalize → semantic checks → lint / patch

adapter

Figma today; another tool can implement the same language

Core is ordinary TypeScript. No figma.*, no plugin typings.

import { validate, normalize, lint, applyPatch } from "@compact-design/core";

const result = validate(input);

if (!result.valid) {
  console.log(result.issues);
} else if (result.document) {
  console.log(lint(result.document));
}

Enter fullscreen mode Exit fullscreen mode

Issues come back structured, which is the point if a model is in the loop:

{
  "valid": false,
  "issues": [{
    "severity": "ERROR",
    "code": "SCHEMA_VALIDATION",
    "path": "nodes[0].children[2].layout.direction",
    "message": "must be HORIZONTAL, VERTICAL, or GRID",
    "suggestion": "Use the allowed property type or enum from compact-design.schema.json."
  }]
}

Enter fullscreen mode Exit fullscreen mode

Schema and semantic errors block import. Lint does not. Lint is advisory: contrast, 44px targets, 4px spacing, missing Auto Layout, hard-coded colours, broken prototype destinations.

The plugin does not render a browser thumbnail. A thumbnail would lie about fonts, Auto Layout, masks, and effects. You get counts, matches, and the repair JSON instead.

Create, update, patch, export

Every imported canvas and layer stores its JSON id as plugin data.

• Create new refuses a canvas ID already on the page.
• Update matching IDs replaces matching canvases in place.
• Replace matching canvases rebuilds them from the document you just supplied.
• Export selection writes Compact Design JSON back out.

Full-document update is canvas-granular. A patch is node-granular. Failures roll back — the previous design is cloned first.

{
  "patch": {
    "operations": [
      { "op": "set", "id": "title", "set": { "text": "The same design.\nA different mood." } },
      { "op": "remove", "id": "old-badge" },
      {
        "op": "append",
        "parent": "card",
        "node": {
          "id": "note",
          "type": "TEXT",
          "w": 272,
          "h": 18,
          "text": "UPDATED WITH A JSON PATCH",
          "fill": "#B69B62"
        }
      }
    ]
  }
}

Enter fullscreen mode Exit fullscreen mode

set changes only what you list. Everything else stays put.

Try it

The package is not on npm yet. Build from the repo.

git clone https://github.com/Elliot727/compact-design.git
cd compact-design
npm install
npm run build

In Figma desktop: Plugins → Development → Import plugin from manifest… and pick plugins/figma/manifest.json.

Then paste examples/design-language-showcase.json. It should land as a finished product screen, not an API reference board.

Language docs, schema, and the other fixtures live next to it.

If you generate UI with a model, this is the format I’d actually trust.

MPL-2.0. github.com/Elliot727/compact-design

원문에서 계속 ↗