Skip to content

Releases: vicmaster/framesmith

v1.5.2 — viewer live updates for bound repos

11 Jun 12:09
9a84781

Choose a tag to compare

The standalone viewer is now actually live. framesmith-viewer printed Watching ~/.framesmith for changes… but only watched the global store — never the bound repos' .framesmith/ dirs, where agents in a bound project actually write. The gallery stayed stale until a restart.

  • The watcher now covers every aggregation source: the global canvases dir, registry.json, and each registered repo's .framesmith/ recursively (per-project subdirs included). A repo bound while the viewer runs starts updating live too.
  • Crash-proof reloads: live watching can race an agent's half-written JSON — a corrupt/mid-write repo file now skips one reload pass instead of killing the viewer process.
  • Startup lists each watched bound repo, and every reload logs a line — "is it live?" is answerable from the terminal.
  • Also included from #101: the discoverability test guard + fully enumerated import-report docstrings.

With this, npx -p framesmith framesmith-viewer reflects agent writes within ~1–2 seconds, no restarts. npm i -g framesmith@1.5.2.

v1.5.1 — agent-facing docs for structural reconstruction

11 Jun 11:30
c8ccdbe

Choose a tag to compare

Docs-only patch. v1.5.0's structural reconstruction was fully documented in the README — but MCP agents don't read READMEs. This release puts it on the surfaces they do see:

  • Server instructions (loaded into every client on connect) now describe the structural layer — tables → proportional columns, grids from the computed template, centering, geometry clustering — and report.layout's contract: a stack-fallback entry means hand-fix that one container; everything else arrived structurally correct, so don't rebuild imported tables/grids by hand.
  • init GOTCHAS carry the same guidance.
  • canvas_import_html / canvas_import_url docstrings now cover all of Phase 18 (grid/centering/clustering were missing).
  • framesmith://guidelines gains an Importing from implementation section — the import workflow, the three report sections and what to do with each, the Tailwind-snippet runtime note, tokenMatch defaults, and auth hygiene.

No code changes; no behavior changes. npm i -g framesmith@1.5.1.

v1.5.0 — Structural reconstruction

11 Jun 11:16
44399e4

Choose a tag to compare

The import's layout layer. v1.4.0 made imports token-faithful (colors, fonts, icons, controls); v1.5.0 makes them structurally right — tables come back as columns, grids as rows-of-columns, centered cards centered. Born from a real dogfooding session on a Rails + Tailwind v4 admin screen (issue #92).

Phase 18 — Structural reconstruction (#92)

<table> → real columns. table/tr/td reconstruct as a vertical frame of horizontal row frames with proportional percentage cell widths derived from the computed boxes — a 4-column User Management table imports as 40/20/25/15%, with cell content (avatars, chips, select primitives) landing inside its columns. thead/tbody unwrap, <caption> becomes a text node, row bottom-borders become exact hairline dividers, colspan is handled free via box proportion, rowspan warns.

CSS grid → rows of proportional columns. The computed grid-template-columns (resolved px, even for fr tracks) drives reconstruction; numeric grid-column spans win over box-derived ones; single-track grids import as faithful stacks with no noise; irregular templates degrade honestly.

Centered content stays centered. margin: auto and max-width don't survive as computed "center" values — the importer now detects both: auto-margin children keep their real width with the parent gaining alignItems: "center", and max-width becomes the renderer's fluid width: "100%" + maxWidth idiom. This also fixed a latent v1.4.0 bug where wrapper-collapse silently dissolved flex-center wrappers (the classic sign-in shape).

Geometry clustering for everything else. Floats, inline-block grids, and unmodeled multi-column CSS reconstruct from computed bounding boxes alone — row bands with conservative consistency guards. A wrong reconstruction is worse than an honest stack: anything that looks multi-column but won't cluster consistently imports as a stack with a stack-fallback report entry and warning, and genuinely vertical content is never touched.

report.layout records how every container was reconstructed (table | grid | centered | geometry | stack-fallback) — the same honesty contract as snapped/literals/warnings.

Intent-mapper hygiene. Unresolvable $token refs produced by Tailwind class intent now revert to the computed value they overrode (ground truth) instead of warning — killing the bogus $collapse/$body-sm noise structurally; border-style keywords (border-collapse etc.) never reach the color branch.

Upgrading

npm i -g framesmith@1.5.0 (or let npx framesmith pick it up). No breaking changes; v1.4.0 canvases and tool calls work unchanged. Existing imports simply get better structure — re-import and compare.

Spec trail: docs/specs/PHASE-18-SPEC.md — PRs #93#98.

v1.4.0 — Faithful parity + import from implementation

10 Jun 15:48
abfb245

Choose a tag to compare

Two complete phases, born from a single real-world dogfooding session (issues #77 and #78): framesmith canvases now reproduce what ships — and can import what ships.

Phase 16 — Faithful parity (#77)

Fonts load by name. Set fontFamily: "Inter" in a typography token (or on a node) and the renderer resolves it from Google Fonts automatically — at token-write time plus a render-time backstop. Binaries cache under ~/.framesmith/fonts/ (offline + deterministic after first resolve); typography.body.fontFamily becomes the document default; unresolvable families degrade to the fallback stack with an explicit Font warnings item, never silently. set_fonts now accepts families: ["Inter"] and Google Fonts css2 stylesheet URLs.

Material Symbols. A second bundled icon set (3,800+) alongside Lucide: icon: "material:check", iconStyle: "outlined" | "rounded" | "sharp", -fill suffix for filled variants.

Input primitives. toggle, checkbox, radio, select are real node types with checked / disabled / value, styled from design tokens ($accent/$border/$bg-surface) with neutral fallbacks — no more faking controls from frames + ellipses.

Component structures. apply_structure now stamps component-kind scaffolds under any targetId, repeatably, with re-keyed IDs + an idMap: data-table, form-field, toolbar, stat-card, toggle-row. A high-fidelity table is one stamp instead of ~80 hand-placed nodes.

Also: fontVariationSettings for variable-font axes, letterSpacing/textTransform surfaced everywhere agents look, and Chrome-launch hardening (FRAMESMITH_CHROME_PATH / PUPPETEER_EXECUTABLE_PATH override + actionable launch errors).

Phase 17 — Import from implementation (#78)

canvas_import_html — paste a shipped component's HTML (+ optional CSS) and get an editable canvas: flex → frames, text runs with computed type props, <img> → image, inline SVGs → icon nodes when they match a bundled glyph, checkboxes/switches/selects → the input primitives with their live state. Flatten knobs (collapseWrappers / mergeTextRuns / dropInvisible / maxDepth).

Token re-mapping — the import is a token-driven design, not a pile of hex: Tailwind classes map to intent (bg-surfacefill: "$surface", gap-416; the v4 default palette is bundled, generated from the official oklch values by Chrome itself), and remaining literal colors snap to your design system — near-ties between tokens are reported and left literal, never guessed.

canvas_import_url — import a live page: viewport, component-level selector, waitFor for client-rendered UI, and auth headers/cookies for gated pages (used in a throwaway browser context, never persisted).

canvas_sync_from_url — drift detection: ephemeral re-import + pixel diff against the design-of-record → diff image + changePercent. An unchanged page diffs at exactly 0% — the import→render round-trip is pixel-deterministic — so design ↔ code divergence is a number you can gate CI on (pattern documented in the README).

Every import returns a mapping report (snapped / literals / scaleMatches / unmatchedFonts / unmatchedIcons / warnings) — lossy by design, honestly reported.

Upgrading

npm i -g framesmith@1.4.0 (or let npx framesmith pick it up). No breaking changes to existing tools; canvases from v1.3.0 work unchanged. New dependency: @material-symbols/svg-400. Fonts and icon recognition work offline after first use.

Full spec trail: docs/specs/PHASE-16-SPEC.md · docs/specs/PHASE-17-SPEC.md — PRs #79#91.

v1.3.0 — Cliché guardrails + Structured critique

24 May 14:49
75194a9

Choose a tag to compare

Two phases land in v1.3.0, both built spec-first (docs/specs/PHASE-12-SPEC.md, PHASE-13-SPEC.md).

✨ Phase 12 — Cliché & craft guardrails

canvas_evaluate now scores cliché, not just craft — the visual tells that read as machine-made, all detected on the scene graph (and confirmed against the render).

  • New cliche category (weight 15), each issue tagged with a tell:
    • default purple/indigo accent · gradient/glow overuse · fake browser/OS chrome (traffic-light dots) · the hanging eyebrow-beside-heading header · fabricated metrics/testimonials/logos (honest-content)
  • Mechanical autofixes via canvas_autofix — swap a known-default purple accent → neutral, delete a fake-chrome strip. Taste tells (gradients, hanging header, fabricated copy) are suggestion-only.
  • Genre-aware looseninggenre option / provenance preset relaxes intentional tells (e.g. material allows purple).

✨ Phase 13 — Structured critique & auto-revision

The LLM judge (opt-in mode:"llm") moves from one opaque number to a fixed multi-axis rubric, and can now close the loop.

  • Rubric: hierarchy · execution · specificity · restraint · variety — each 1–5 with a rationale; derived 0–100 overall.
  • Revision threshold: per-axis floor (default 3, FRAMESMITH_CRITIQUE_FLOOR) → needsRevision + failingAxes.
  • New canvas_revise tool: bounded judge → revise failing axes via batch_design ops → re-judge (≤3 passes); stops on pass / cap / no-improvement (reverts regressions) / apply-error.
  • Verdict stamping: metadata.critique + a compact entry on the per-project build log; viewer shows a verdict chip.

⚠️ Breaking change (experimental LLM mode only)

canvas_evaluate with mode:"llm" — the llmCritique shape changed: free-text strengths/weaknesses are replaced by the per-axis rubric (plus needsRevision / failingAxes). All heuristic categories and every other tool are unchanged.


npx framesmith            # or
claude mcp add framesmith npx framesmith

Full changelog: v1.2.0...v1.3.0

v1.2.0 — Agent onboarding & dogfooding fixes

23 May 20:36
dfc2bdc

Choose a tag to compare

This release closes #64 — an onboarding gap plus a batch of bugs found designing a feature end-to-end from a real agent session. All changes are additive; pre-1.2 canvases load unchanged (no migration).

Onboarding

  • Server instructions — framesmith now ships an MCP instructions block, so any client is oriented on connect (the Workspace › Project › Canvas model, the layered $token system, "read framesmith://guidelines first", and current gotchas) with zero tool calls.
  • New init tool — one idempotent call to start a session: binds the repo if needed, scaffolds the convention projects (Foundations + UI), and returns the live re-keyed IDs, a workflow cheatsheet, the gotchas, and the viewer URL. The fix for "binding re-keys IDs, so docs go stale instantly."
  • batch_design returns a { varName: nodeId } map — map your bound variables straight to created node IDs instead of counting result positions.

Fixes

  • A CSS-string gradient / shadows no longer crashes screenshot (structured form stays canonical; strings are accepted).
  • canvas_move on a bound repo now relocates the canvas file to the target project's directory.
  • canvas_evaluate no longer flags a contrast ratio that rounds to exactly 4.5:1 (rounded to 2 decimals for compare + display).
  • apply_preset preserves tokens inherited from the workspace/project design system instead of silently overwriting them (reported as preservedFromDesignSystem).
  • import_design_md now reads list / table / name: value token formats per section, honors explicit named spacing instead of injecting a default scale, and documents the accepted schema.

Docs

  • A "Sharp edges" section in framesmith://guidelines consolidating the operational caveats; louder canvas_bind re-key callout.

Install: npx -y framesmith · Upgrade: already on latest.

v1.1.0 — Design variety & anti-sameness

23 May 12:50
c45af44

Choose a tag to compare

Phase 11 makes framesmith deliberately vary page layouts instead of converging on the same hero-and-three-cards shape every session.

Highlights

  • Layout structure library — six named page scaffolds (marquee-hero, bento-grid, stat-led, editorial-longform, split-workbench, catalogue), each a partial scene tree of labeled placeholders. Distinct from color presets; they compose.
  • list_structures / apply_structure — pick a structure, get a placeholder skeleton to populate, render, and verify. Pass projectId to list_structures for a diversification signal.
  • Structure taxonomy — every scaffold is tagged on four independent axes (heroTreatment, density, rhythm, alignment), so "differs from last time" is computable.
  • Per-project build log — records the structure / preset / axes behind each canvas, in both the global store and repo-bound .framesmith/ dirs.
  • Diversification signalcanvas_create (and list_structures with projectId) surface recent work plus a "differ on ≥ 1 axis" hint when recent canvases converge. Advisory, never blocking.
  • Provenance — each canvas records what produced it, shown as a chip on the viewer detail page.

Upgrading from 1.0.0

  • Additive — no migration, no data risk. Existing canvases load unchanged (provenance is optional); build-log files are created lazily on first use. Forward- and backward-compatible.
  • Existing canvases simply have no provenance until you apply a structure/preset to them; their projects' diversification signal starts empty.
  • To get 1.1.0: update via npx framesmith@latest (or clear the npx cache) and restart your MCP client so it loads the new version.

Full changelog: v1.0.0...v1.1.0

v1.0.0 — framesmith

21 May 18:52
cff08b6

Choose a tag to compare

First public release. npx framesmith — an open-source MCP server that gives your AI coding agent a visual design canvas: sketch the UI, review it in a browser, agree on the design before any framework code gets written.

Formerly canvas-mcp — renamed to framesmith for v1.0.

Headline: your designs live in your repo

Canvases persist as open JSON in a .framesmith/ directory, checked in alongside your code — committable, diffable in code review, and self-contained on clone. The repo is the source of truth; no proprietary, encrypted store. Bind a workspace with canvas_bind and the server auto-detects it on startup.

What's in 1.0

  • Scene graph → HTML/CSS → Puppeteer screenshots — agents author via MCP tools, you review real browser renders.
  • Workspaces / projects and a Figma-style standalone viewer (read-only gallery across global + every bound repo).
  • Design systems with workspace → project → canvas token inheritance.
  • Responsive breakpoints (stack / wrap / fluid widths) with true reflow.
  • Evaluation — heuristic design scoring + optional LLM-as-judge, with auto-fix ops.
  • Repo-bound storage — deterministic JSON, asset externalization (.framesmith/assets/), external-change safety, viewer write-back.

Install

# Claude Code
claude mcp add framesmith -- npx framesmith

Works with any MCP client (Cursor, Windsurf, VS Code, Codex). See the README for per-client config.

MIT licensed.

v0.9.0 — Workspace-level design systems

17 May 16:02
7715d87

Choose a tag to compare

Tokens declared once, inherited everywhere.

The Coide use case finally clicks: set the design system once on the workspace, every canvas under it resolves $primary / $bg / $lg automatically.

canvas-mcp design tokens — v0.9.0 hero

Highlights

  • Workspace.designSystem + symmetric Project.designSystem — declare tokens once at the workspace level; projects can override.
  • Three-layer resolution at render: canvas.variables (override) → project.designSystemworkspace.designSystem → built-in defaults. Per-category merge — setting only colors doesn't reset spacing/radius/typography.
  • Six new MCP tools: workspace_set_design_system, workspace_get_design_system, workspace_apply_preset + symmetric project_* trio. Presets (dark, light, material, minimal) installable at workspace OR project level.
  • Shared getCanvasTokens(canvas) helper in src/workspaces.ts — every render path (MCP tools, viewer, evaluate, canvas_diff) routes through it. The docstring warns against the anti-pattern that bit us in #40.

Authoring story

// Once per workspace — brand colors set globally
workspace_set_design_system({
  workspaceId,
  variables: {
    colors: { primary: "#0066ff", bg: "#0a0a0a" },
    spacing: { sm: 8, md: 16, lg: 24 }
  }
});

// Every canvas under that workspace
batch_design({ canvasId, operations: 'I(parent, { fill: "$primary" })' });
// → resolves to #0066ff via workspace inheritance, no canvas-level redefinition

Bonus

  • Fix #40 — viewer / canvas_diff / evaluate were missed in the Phase 9 PR, leaving them with the old resolveVariables(canvas.root, canvas.variables) bypass. Caught while dogfooding the release page.
  • Dogfood #41scripts/build-phase9-showcase.ts composes a single-canvas hero that visually documents canvas-mcp's design system AND proves three-layer inheritance works end-to-end (canvas itself has variables: {} — every value resolves from workspace tokens). Plus reorganized canvas-mcp's own dogfood artifacts into Design system / UI / Releases projects following Figma + atomic design + Spotify Encore conventions.

Backward compatibility

All Phase 9 additions are opt-in:

  • Existing canvases without workspace/project designSystem render identically — the merge falls through to canvas.variables alone.
  • setVariables / getVariables / canvas-level apply_preset unchanged.
  • Workspace/Project JSON gain an optional designSystem field; older persisted entries without it load cleanly.

No migration needed.

What's next

Only Phase 10 (Ecosystem — image generation, HTTP transport, VS Code extension, Figma import, marketplace, plugins) remains for the v1.0 push.

v0.8.0 — Renderer expressiveness

17 May 12:55
296e10d

Choose a tag to compare

The renderer learned how to fade in, blur what's behind it, load a real typeface, draw a custom mark, and know which ancestor to anchor against.

Five primitives that expand what a canvas-mcp design can express. Every item came from a concrete Phase 7 slice-5 design moment the renderer couldn't render.

Phase 8 release page — five primitives, one quiet release

Highlights

  • Auto position: relative — frames automatically receive position: relative when a descendant uses position: absolute without a positioned ancestor. Fixes the slice-5a "absolute child escapes to body coordinates" bug. (#31)
  • Custom fontsset_fonts / get_fonts MCP tools. Renderer emits @font-face + <link rel="preconnect"> per origin + font-display: swap. (#32)
  • backdropFilter — structured object with blur / saturate / brightness / contrast. Both backdrop-filter and -webkit-backdrop-filter emitted for Safari. Legacy backdropBlur still works. (#33)
  • path node type — custom SVG marks via raw d + viewBox. Fill/stroke apply to the path element (not the wrapper). Tight character whitelist on d. (#34)
  • Animations — structured animation field referencing built-in keyframes (fadeIn, slideUp, slideDown, scaleIn). @keyframes auto-emitted only when referenced. Structured transition ready for future hover/JS state changes. (#35)

Bonus

  • Inline style escape fix" and & in CSS values now HTML-escape correctly. Found while dogfooding the release page with fontFamily: '"Inter", system-ui, sans-serif' (the inner " was prematurely closing the outer style="..." attribute). (#36)
  • Dogfood release page — single-canvas hero composed via canvas-mcp itself, exercising every Phase 8 primitive. Reproduce with npx tsx scripts/build-phase8-release.ts, then visit /canvas/phase8-release in the viewer to see animations play. (#37)

Backward compatibility

All Phase 8 additions are opt-in:

  • Existing canvases without fonts / animation / transition / backdropFilter / path nodes render identically.
  • The legacy backdropBlur: number field keeps working unchanged.
  • Auto position: relative only applies via external stylesheet rule, so inline position declarations always win.
  • The renderer escape fix is invisible to canvases that didn't trip the bug.

No migration needed.

What's next

Phase 9 — Workspace-level design systems. Promote per-canvas variables to workspace-inherited tokens with explicit per-canvas overrides. "Every Coide canvas should follow Coide's design system without redefining colors per canvas."