@sketchmark/core
v0.1.4
Published
Agent-first visual document language core.
Maintainers
Readme
Sketchmark Core
Implementation of the new agent-first Sketchmark language through the practical core phases, including deck playback, visual fidelity, Three/WebGL rendering, and PPTX-native export.
This package currently supports:
- compact
.sketchparsing .sketch.jsoncloading- normalization into a stable document model
- structured validation errors
- JSON-style patch application
- symbol index generation for single files and project folders
- folder-based project loading from
manifest.sketch - component
use ... as ...expansion - deterministic
stack,grid,align, anddistributelayout helpers - mark-level placement helpers like
place,below, andrightOf - link waypoints for explicit polyline routes
sceneswith scene-level marks, links, layout, andspeakerNotessequencesfor long MP4 exports that concatenate scene clips over time- PowerPoint-style
mode: deckplayback with explicit scene-localstepbuilds - static SVG rendering
- browser preview server with live
.sketch/.sketch.jsoncediting - preview-server export button for
svg,png,jpg,html,mp4, andpptx - simple SVG transforms for
rotate,rotateZ,scale,scaleX, andscaleY - linear/radial gradient paints for
fillandstroke, including animated matching gradient stops - rich SVG text:
font,weight,letterSpacing,lineHeight,align, and multiline\n - project font-face declarations with
font id: - stroke controls:
strokeCap,strokeJoin,dashArray,dashOffset,drawStart, anddrawEnd - procedural paths from
fx,xt/yt, stringpoints, andclosed - SVG effects:
blur,brightness,contrast,saturate,hueRotate,shadow, andblend - SVG masks by referencing a normal mark with
mask: mask_id - inline typed tweens for numbers, vectors, colors, angles, opacity, scale, and camera pan/zoom
- keyframe syntax for numeric and color properties, such as
opacity: 0 at 0s, 1 at 1s ease-out - advanced motion helpers:
spring(...), deterministicwiggle(...), and explicitref("id", "prop") show: 2s..endvisibility ranges using the document/export duration- generated canonical timeline tracks for inline motion
f(time) = ...expressions for animated numeric properties- timed narration cues with
narrate at 1s "...", rendered as frame captions and HTML transcript metadata - document audio tracks with
audio id:blocks for HTML playback and MP4 audio muxing - validation that rejects ambiguous
tin time expressions; usetime - frame resolution with
resolveFrame(document, "1.5s") - nested theme references such as
{theme.colors.text} - JSONC
repeatmarks with seeded$random,$choose, and$randomVechelpers - SVG frame previews at a chosen time
calloutmarks for product-demo annotations- orthographic camera pan/zoom for SVG previews
- interactive HTML playback generated from resolved SVG frames
- strict 3D mode:
space: 3dmust userenderer: three; SVG/canvas fallback 3D is intentionally disabled - exporter capability declarations and repairable capability errors
- file exports for
png,jpg, andmp4 renderer: threeWebGL HTML previews plus browser-captured PNG/JPG/MP4 exports- PPTX deck export through
@bapunhansdah/pptxgenjs - PPTX-specific export modes:
snapshot,native, andnativeWithFallback - editable native PPTX output for supported text, shapes, images, lines, arrows, labels, notes, and step-level PowerPoint effects
PDF, particles, and charts need dedicated adapters later. PNG/JPG use Sharp for 2D exports; renderer: three uses a Chromium/WebGL capture path; MP4 encodes captured PNG frames with ffmpeg.
Example
canvas:
size: 1200 720
bg: #ffffff
export: svg
mark client rect:
at: 260 320
size: 160 64
text: "Client"
fill: #eef2ff
stroke: #4f46e5
mark api rect:
at: 560 320
size: 160 64
text: "API"
fill: #f0fdf4
stroke: #16a34a
link client_to_api arrow:
from: client
to: api
label: "HTTPS"
route: orthogonal
anchors: right leftMotion Example
canvas:
size: 960 540
bg: #ffffff
export: svg
duration: 3s
mark ball circle:
r: 18
fill: #ef4444 -> #2563eb over 3s
show: 0s..3s
x: 120 -> 760 over 3s ease-out
y: f(time) = 382 - (170 * time - 38 * time^2)
opacity: 0 at 0s, 1 at 1s ease-out
mark card rect:
at: [180, 280, 0] -> [700, 280, 0] over 3s ease-in-out
size: [140, 72] -> [240, 104] over 3s
fill: #eef2ff -> #dcfce7 over 3s
rotateZ: -8deg -> 8deg over 3sThe parser keeps the syntax compact. The normalizer turns animated fields into a stable motion map and generates patchable timeline tracks. The frame resolver evaluates them into ordinary static mark properties for rendering.
Project Example
product-demo.sketch/
manifest.sketch
theme.sketch
components/
rocket.sketch
scenes/
launch.sketch
sequences/
main-video.sketch
index.sketch.jsonmanifest.sketch owns the canvas, exports, and imports. The project loader merges imported modules into one normalized document and the indexer writes stable symbol paths for agents.
Layout Example
layout main_flow stack:
direction: x
items: client api db
gap: 120
box: 100 190 760 180Manual at: coordinates still win. Layout only fills in positions for marks that do not already have one.
Repeat Example
{
"marks": {
"stars": {
"type": "repeat",
"count": 12,
"seed": 42,
"template": {
"type": "circle",
"radius": { "$random": [3, 8] },
"at": ["120 + i * 42", "170 + 34 * sin(i)", 0],
"fill": { "$choose": ["#facc15", "#fde68a", "#ffffff"] }
}
}
}
}Repeat expands during normalization into stable IDs like stars_0, stars_1, and stars_2, so agents can patch generated instances later.
scenes Example
scene intro:
speakerNotes: "Introduce the deck."
mark intro_title text:
role: title
text: "Sketchmark Deck"
place: top-left
margin: 96 96scenes can render as static SVG previews or as deck slides when canvas mode: deck is set.
Sequence Example
sequence main_video:
export: mp4
clip intro:
scene: intro
duration: 4s
transition fade:
duration: 0.5s
clip launch:
scene: launch
duration: 8sA sequence joins scenes over time for longer videos. scenes stay isolated; shared visuals belong in components, assets, theme, or vars.
Deck Example
canvas:
size: 1280 720
export: html
mode: deck
pptx:
mode: nativeWithFallback
animations: native
scene intro:
speakerNotes: "Open with the deck playback model."
mark title text:
text: "Deck mode"
at: 120 170
anchor: left
size: 64
opacity: 0
step title_in:
duration: 0.6s
narrate: "The title appears on the first click."
pptx: flyin
direction: left
animate title:
opacity: 0 -> 1 over 0.6s ease-out
y: 210 -> 170 over 0.6s ease-outDeck preview Next/Prev advances through scene steps before changing slides.
For PPTX export, pptx.mode controls how PowerPoint-specific the export should be:
nativeWithFallback: supported 2D scenes become editable PowerPoint objects; unsupported scenes fall back to full-slide snapshots. Three/WebGL scenes are captured as image snapshot slides.native: require native editable PowerPoint output and fail with a clear error if a slide uses unsupported features.snapshot: preserve visual fidelity by exporting each build state as a full-slide SVG image layer.
Each step can choose a small deck-safe PowerPoint build effect with pptx:, plus direction, trigger, and delay. Supported effects are intentionally limited to appear, fadein, flyin, wipe, zoom, fadeout, and disappear. This keeps Sketchmark aligned with the animation ideas the DSL can express directly: show, fade, move in, reveal, zoom in, and hide. flyin and wipe accept top, bottom, left, or right; zoom accepts slideCenter or objectCenter.
Product Demo Example
camera:
type: orthographic
zoom: 1.08
at: 40 -18 900
mark chart_callout callout:
target: chart
title: "Live analytics"
body: "Track changes as they happen."Product demos can render to interactive HTML playback today.
3D Example
canvas:
size: 1280 720
bg: #020617
space: 3d
renderer: three
export: html
mark cube cuboid:
at: 0 0 0
size: 180 180 180
fill: #38bdf83D documents render through Three/WebGL. For SVG output, remove space: 3d and use normal 2D marks instead.
In mixed decks, keep the deck canvas 2D and set renderer: three only inside the scene that needs 3D:
scene model_3d:
canvas:
space: 3d
renderer: three
mark core sphere:
r: 0.7
fill: #38bdf8For PPTX, neighboring 2D scenes can remain native editable slides while the 3D scene becomes a full-slide image snapshot.
API
import {
parseSketch,
normalizeDocument,
validateDocument,
exportSketchToFile,
loadSketchProject,
resolveFrame,
renderToHtml,
renderDeckToHtml,
renderPageToSvg,
renderToSvg
} from "@sketchmark/core";
const parsed = parseSketch(source);
const document = normalizeDocument(parsed);
const result = validateDocument(document);
if (!result.ok) {
console.log(result.issues);
} else {
const frame = resolveFrame(document, "1.5s");
const svg = renderToSvg(frame);
}
const project = loadSketchProject("examples/split-project");
const pageSvg = renderPageToSvg(document, "intro");
await exportSketchToFile(document, "out.png", { time: "2s" });
await exportSketchToFile(document, "out.mp4", { duration: "4s", fps: 24 });
await exportSketchToFile(document, "deck.pptx");Installation
npm install @sketchmark/coreBuild And Test
npm install
npm test