SkillGild
Design

Vernier

Interactive isometric line illustrations that answer the pointer, touch, the keyboard and live data. Your agent designs the instrument; the engine handles input, themes and accessibility, and it ships as a React component, a web component and a preview page.

  • Included with SkillGild Pro
  • Runs in your agent, private tools on SkillGild
  • v1.0.0
  • SkillGild
skillgild install vernier
Works with
  • Claude Code
  • Codex
  • Cursor
  • Gemini CLI
and any MCP client

Created by SkillGild

What you get

  • An interactive isometric illustration of a real object that answers the pointer, touch, the keyboard and live data from your product
  • Three deliverables from one source: a React component, a framework-free web component and a preview page with gain, theme, signal and accent controls
  • Light and dark themes that follow the system, one optional brand accent, and ground and line tones you can match to your design system
  • Accessibility built in: keyboard stepping, a screen-reader status, a focus ring and reduced-motion support
  • Data mode: feed it a number from 0 to 1, such as usage against a limit, and it rests on that reading
  • Matched series of up to four instruments for one page, checked for a shared camera and visual weight
  • Every instrument measured in simulated time and checked by SkillGild's validator before handover

Is it a good fit?

Good for

  • Hero and feature-section illustrations for developer tools, infrastructure and SaaS products
  • Empty states, onboarding steps and dashboards that should feel alive without being busy
  • Teams that want motion that stays on brand, works on phones and passes an accessibility review

Not for

  • Photographic, painted or 3D-rendered illustration
  • Charts with axes, legends and many data points; Vernier shows one reading at a time
  • Logos, icons or anything that needs text inside the drawing

Requirements

  • A coding agent that can write files: Claude Code, Cursor, Codex and similar
  • Node.js for the build and QA tools (recommended; the skill also works without it, with a hand-assembled build)
  • A browser to look at the result (recommended)
  • React 18 or later for the React component; the web component needs no framework

Install the Vernier skill

Pick your agent. The wrapper only tells your agent how to start a session. The skill's instructions arrive with each session, after your access is checked.

  1. Sign in once from your terminal.

    Terminal
    skillgild login
  2. Install this skill for Claude Code.

    Terminal
    skillgild install vernier --agent claude-code
  3. Register the SkillGild MCP server with Claude Code.

    Terminal
    claude mcp add --scope user skillgild -- $(command -v skillgild) mcp

How it runs

  1. Your agent starts a session. SkillGild checks your access and allowance, counts one run, and sends the skill's instructions for this task.
  2. Your agent does the work with its own model and tools, in your project. SkillGild makes no AI model call.
  3. Private steps run on SkillGild. Your agent calls the server tools below and gets their results. The tool code never leaves SkillGild, and tool input is not stored.

Use it from code

Start a session, call its tools, then end it. Create an API key under Account and pass it as a bearer token.

Terminal
# Prints the session ID, its tools and the instructions for your agent
skillgild session vernier
skillgild call <session-id> validate_instrument --input '{"instruments":[{"source":"// A rack of sample vials. Pointing at one lifts it clear of the rack; its\n// neighbours rise after it, less the farther they stand. Pick mode, signal \"pick\".\nVernier.define({\n  name: \"vials\",\n  purpose: \"A rack of sample vials: the one you point at lifts clear, and its neighbours rise after it.\",\n  principles: [1, 2, 5, 9],\n  gain: [12, 22, 34], // how far the chosen vial lifts, in world units\n  extent: [[-102, -24, 0], [102, 24, 88]],\n  signal: \"pick\",\n  tune: { stagger: [15, 40, 90], reach: [1.5, 3.2, 6] },\n\n  build(v) {\n    const n = 7, gap = 27, R = 7, BASE = 5, BODY = 40, y = 2;\n    const levels = [0.62, 0.34, 0.8, 0.5, 0.24, 0.7, 0.44];\n    const front = Math.atan2(v.view[1], v.view[0]);\n    v.solid({ x: 0, y: 0, w: 204, d: 44, h: BASE, r: 9 }, { layer: \"back\" });\n    v.solid({ x: 0, y: -17, z: BASE, w: 194, d: 4, h: 26, r: 2 }, { layer: \"back\" });\n    const vials = [];\n    for (let i = 0; i < n; i++) {\n      const x = (i - (n - 1) / 2) * gap, part = \"vial-\" + i;\n      const body = v.solid({ x, y, z: BASE, w: R * 2, round: true, h: BODY }, { part });\n      const cap = v.solid({ x, y, z: BASE + BODY, w: R * 2 + 2, round: true, h: 6 }, { part });\n      const level = v.line([], { tier: \"seam\", under: cap });\n      const ring = (z) => Array.from({ length: 13 }, (_, k) => {\n        const a = front - Math.PI / 2 + (k / 12) * Math.PI;\n        return [x + Math.cos(a) * R, y + Math.sin(a) * R, z];\n      });\n      v.target(\"vial-\" + (i + 1), { shape: body });\n      vials.push({ body, cap, level, ring, fill: levels[i] * (BODY - 6), lift: v.ease(0) });\n    }\n    return { vials, rest: 2, BASE, BODY };\n  },\n\n  respond(v, s) {\n    const id = v.input.target;\n    const a = id ? Number(id.slice(5)) - 1 : null;\n    s.vials.forEach((vial, i) => {\n      const goal = a == null ? (i === s.rest ? 0.55 : 0) : v.falloff(i - a, v.tune.reach, 0);\n      vial.lift.set(goal * v.gain, a == null ? 0 : v.delay(i, a, v.tune.stagger));\n      const lit = a == null ? i === s.rest : i === a;\n      vial.body.lit(lit);\n      vial.cap.lit(lit);\n    });\n    v.status(a == null ? \"idle\" : \"vial \" + (a + 1));\n  },\n\n  draw(v, s) {\n    for (const vial of s.vials) {\n      const z = s.BASE + vial.lift.value;\n      vial.body.set({ z });\n      vial.cap.set({ z: z + s.BODY });\n      vial.level.set(vial.ring(z + 3 + vial.fill));\n    }\n  },\n});\n","qa":{"engine":"vernier/1.0.0","name":"vials","frame":[480,360],"mode":"pick","ambient":false,"view":{"yaw":45,"tilt":30},"shapes":23,"targets":7,"idle_label":"idle","poses":{"idle":{"bbox":[86.9,110.4,393.1,326.1],"coverage":0.382,"settled":true,"settle_ms":567,"lit_parts":1,"status":"idle","smallest":85.7},"respond":{"bbox":[86.9,110,393.1,326.1],"coverage":0.383,"settled":true,"settle_ms":683,"lit_parts":1,"status":"vial 4","smallest":85.7,"changed":0.556},"low":{"bbox":[86.9,91.5,393.1,326.1],"coverage":0.416,"settled":true,"settle_ms":733,"lit_parts":1,"smallest":85.7},"high":{"bbox":[86.9,57,393.1,326.1],"coverage":0.477,"settled":true,"settle_ms":733,"lit_parts":1,"smallest":85.7},"signal":{"bbox":[86.9,75.8,393.1,326.1],"coverage":0.444,"settled":true,"settle_ms":733,"lit_parts":1,"smallest":85.7}},"sweep":{"targets":7,"settled":7,"single_lit":7,"named":7,"checked":7},"falloff":null,"errors":[]}}]}'
skillgild end <session-id>

Server tools

Each call uses one of the session's tool calls.

validate_instrumentValidate Vernier instruments

Checks one to four Vernier instrument sources against the skill's rules: the Vernier.define declaration, no DOM, timers, network, colours or markup of their own, and the length limit. With each instrument's QA report (from the preview page's ?qa or tools/qa.mjs) it also checks the frame, settling, the single highlight, the status, the response and its falloff, and a series' consistency. It reads the source as text and never runs it; it does not judge how the drawing looks.

FieldTypeNotes
instrumentsRequiredarrayNo extra rules.

validate_paletteValidate palette and contrast

Checks named six-digit hex colors and specified foreground/background pairs against your target contrast ratio. This is a calculation, not an aesthetic review or a complete accessibility audit.

FieldTypeNotes
colorsRequiredobjectNo extra rules.
pairsRequiredarrayNo extra rules.

Questions

Does the instrument depend on an npm package?

No. Each deliverable carries its own copy of the small engine (about 15 KB gzipped), so you add one file to your project and nothing to package.json. Two instruments on one page do not interfere.

Does it work on phones?

Yes. A tap or a horizontal drag chooses and the choice holds briefly after you lift your finger. On touch-only devices the instrument can also demonstrate itself slowly after a few seconds without input; switch that off with attract="off".

Can my product's data drive it?

Yes. Give it a signal between 0 and 1 and it rests on that reading, while pointer, touch and keyboard still work. Your agent sets out what 0 and 1 mean for the instrument it builds.

What does SkillGild run, and what does my agent run?

Your agent designs and writes the instrument with your own model. SkillGild runs the validator, deterministic Go code with no AI model behind it, which reads the source and the QA measurements and returns errors and warnings. No AI tokens are spent on SkillGild's side.

Can I match it to my brand?

Set one accent colour for the highlight, and override the ground and line tones with CSS variables such as --vernier-ground. The validator keeps each instrument to a single highlight so the accent always means something.

Related guides

Setup steps and worked examples for this kind of skill.