Agent skill

Vetta UI Design

by openvetta in openvetta/open-vetta

Build and edit design documents (.vetd) on the Vetta design canvas — app screens, landing pages, slides, posters, infographics.

Apache-2.0Auto-check passedFrontend & Design

Install Vetta UI Design

skills CLI
$ npx skills add openvetta/open-vetta --skill vetta-ui-design -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install openvetta/open-vetta vetta-ui-design --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/openvetta/open-vetta.git skills-src && mkdir -p .claude/skills && cp -r skills-src/packages/plugins/presets/vetta-ui-design/agent/skills/vetta-ui-design .claude/skills/vetta-ui-design && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
vetta-ui-design
GitHub stars
290
Token cost
~7.3k tokens
SKILL.md length
4,033 words
Files
12 (incl. references)
Skills in repo
21
Repo updated
First seen
Licence
Apache-2.0

At a glance

Build and edit design documents (.vetd) on the Vetta design canvas — app screens, landing pages, slides, posters, infographics.

  • Works in 4 steps: Routes — frames/login.tsx is /login,… → Navigation — import { Link, useNavigate… → Shared chrome written once — nav bar /… → …
  • The user asks for a UI design
  • SKILL.md covers It is a project, not a picture, The one rule you have to hold…, Structure first, lines second and Pick the product type, plus 5 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Vetta UI Design is an agent skill from openvetta/open-vetta. Build and edit design documents (.vetd) on the Vetta design canvas — app screens, landing pages, slides, posters, infographics. Use when the user asks for a UI design, mockup, screen, deck, or poster, or attaches a design frame/element from the canvas. Frames are real React (TSX) routes, not pictures. Do NOT use for ordinary front-end work in the user's own codebase — building, styling or reworking pages of a real app is that repo's job, and none of the vetd tools or canvas rules here apply to it.

Its SKILL.md is about 7.3k tokens, which your agent loads only when the skill is triggered. The skill folder holds 13 other files, including reference files (for example `references/interaction.md`, `references/quality.md` and `references/taste/UPSTREAM.md`).

It sits in Frontend & Design, covering UI design, React components and Infographics. It works with React. The repository describes itself as: Open-source, local-first AI agent for coding and real work. BYOK models, MCP, skills, plugins, workflows, and private knowledge bases. The licence is Apache-2.0.

When your agent uses it

  • The user asks for a UI design
  • Attaches a design frame/element from the canvas
  • Ordinary front-end work in the users own codebase — building
  • Reworking pages of a real app is that repos job

Example prompts

  • “/vetta-ui-design”

Workflow steps

4 steps, taken from the first numbered list in SKILL.md.

  1. Routes — frames/login.tsx is /login, index.tsx is /.
  2. Navigation — import { Link, useNavigate } from "react-router".
  3. Shared chrome written once — nav bar / sidebar / tab bar goes in
  4. Shared vocabulary — colors/radii/shadows from theme.css tokens

What it can do on your machine

Read from SKILL.md and the folder at commit b983179. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are typescript and css).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Vetta UI Design loads about 7.3k tokens when it runs, and up to ~21k if it reads all its reference files. Until then it costs about 130 tokens; SKILL.md has 4,033 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~130
When it runs · the whole SKILL.md, loaded when a task matches
~7.3k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~21k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from openvetta/open-vetta at commit b983179, republished under its Apache-2.0 licence (© openvetta). 4,033 words, ~7,313 tokens.

Download SKILL.mdSave it as .claude/skills/vetta-ui-design/SKILL.md (or your agent's skills folder). This skill also uses 11 other files; get the full folder from GitHub.
name
vetta-ui-design
description
Build and edit design documents (.vetd) on the Vetta design canvas — app screens, landing pages, slides, posters, infographics. Use when the user asks for a UI design, mockup, screen, deck, or poster, or attaches a design frame/element from the canvas. Frames are real React (TSX) routes, not pictures. Do NOT use for ordinary front-end work in the user's own codebase — building, styling or reworking pages of a real app is that repo's job, and none of the vetd_* tools or canvas rules here apply to it.

Vetta UI Design

A design document is ONE directory — login-app.vetd/ — holding everything:

text
login-app.vetd/
  design.json           ← canvas manifest. GENERATED — see below.
  frames/               ← one TSX file = one canvas frame = one route
    index.tsx           ← the site root "/"
    login.tsx           ← "/login"
    _layout.tsx         ← optional shared shell; `_` files are NOT frames
  components/           ← shared React components
  assets/               ← images, imported relatively
  theme.css             ← color/radius/shadow tokens (Tailwind v4 @theme)
  package.json          ← this design's npm dependencies; vetd_install writes it
  DESIGN.md             ← optional spec; OVERRIDES defaults in this skill

You write the sources; the plugin owns the manifest and reconciles automatically. Every save hot-reloads the canvas. Two consequences worth internalising before you start:

  • The file name IS the route and the frame id. Create a screen by writing frames/<kebab-id>.tsx, delete one by deleting the file. There is no registration step anywhere.
  • Editing design.json is pointless, not just forbidden. It is regenerated from your tsx declarations on every save, so any hand-edit is overwritten seconds later. If a frame is not showing up the way you expect, the answer is always in the tsx.

It is a project, not a picture

The output is a running front-end app the user can click through in preview, built from sources meant to ship. Decide structure BEFORE writing screens:

  1. Routes — frames/login.tsx is /login, index.tsx is /.
  2. Navigation — import { Link, useNavigate } from "react-router".
  3. Shared chrome written once — nav bar / sidebar / tab bar goes in components/, or in frames/_layout.tsx rendering <Outlet /> when it must survive navigation. Never paste it into each frame.
  4. Shared vocabulary — colors/radii/shadows from theme.css tokens (bg-primary, not #0d99ff); repeated blocks become components.

If changing the nav bar means editing more than one file, the structure is wrong. Posters, slides and infographics are standalone artwork — steps 1-3 do not apply to them.

The one rule you have to hold in your head

Frame meta is the FIRST statement, one flat line (regex-parsed):

tsx
export const frame = { width: 390, height: 844, title: "Login" };

Every frame declares its own. Omit it and the frame is rendered at a size inferred from the rest of the design — it still reaches the canvas, but nothing about that size is yours, and issues will keep asking until you declare one. Sizes come from the product type below; when the design already has frames, vetd_status lists their sizes and the design's defaultFrameSize — match them unless the new screen is a different product type.

It gets its own section because it is the only convention here that needs judgment from you. Everything else is either caught automatically or visible in the render.

Caught for you — copy the templates and these never come up

A checker parses every source you write; violations come back as issues on vetd_screenshot and vetd_status, naming the file and line. A file that does not parse, or that imports a package the engine does not have, comes back the same way. The templates below are already correct on all of it:

  • h-full, never h-screen/min-h-screen — a frame is a fixed-size canvas, not a viewport.
  • Icons are Iconify classes — a <span> with a class, NOT a component: <span className="icon-[lucide--search] size-4" />. There is no icon package to import: import { Search } from "lucide-react" fails to build, and so does every other icon library. Never your own icon component, never inline SVG paths. Offline sets, and only these: lucide, tabler, mdi, simple-icons — naming any other set fails to build too.
  • <Link to> from react-router for internal screens, never <a href="/…">, and never a locally redefined Link/useNavigate/useLocation.
  • No remote image URLs (<img>, background-image) — they break screenshots. Import from assets/, or use a gradient/token color/Iconify glyph.
  • Normal formatting, one element per line for nested markup. Everything on one line destroys element→source mapping, and the user's "Ask Vetta" edits then point every element at the same line.
  • One default export per frame, rendering edge-to-edge — no page margins.
  • react, react-router, Tailwind v4 and Iconify are always there. Anything else has to be installed into the design first (see below) — importing a package that is not installed fails the build. No remote font links (Google Fonts <link>/@import url(...)) — typefaces are installed packages, see below.
Dependencies are yours to choose — and yours to justify

A design is a real npm project: vetd_install adds packages to its own package.json, and they travel with the design. vetd_status lists what is already installed — read that before adding anything.

Install when the job is a solved domain problem where a hand-rolled version is visibly worse: chart geometry and axes, Markdown or rich-text rendering, date math and calendars, virtualised long lists, gesture/physics animation.

Build it yourself when Tailwind and React state already do it well — cards, tabs, modals, dropdowns, toggles, steppers, progress bars, a simple bar or donut drawn with divs or inline SVG, and layout of every kind. A UI kit pulled in for a rounded card costs more than it gives: it arrives with its own design language and spends the rest of the design fighting theme.css.

Never install an icon package (icons are Iconify classes), a CSS framework (Tailwind v4 is here) or a router (react-router is here).

Install everything you need in ONE call, then import normally.

Typefaces are packages too

System fonts alone cannot give a display face and a body face that differ, and that sameness is a large part of why generated UI looks generated. A typeface is an npm package here like any other library:

  1. vetd_install the faces — @fontsource-variable/<slug> when the family has a variable build (one file covers every weight), else @fontsource/<slug>, whose bare import is weight 400 only — import each other weight you use (@import "@fontsource/<slug>/700.css";) or the browser fakes the bold.
  2. Import them at the TOP of theme.css, above @theme. Install first: theme.css feeds every frame, so importing a package that is not there yet breaks the styling of the whole canvas, not one frame.
  3. Declare them as --font-* tokens and use the matching font-* class.
css
@import "@fontsource-variable/fraunces";
@import "@fontsource-variable/geist";

@theme {
	--font-display: "Fraunces Variable", "Songti SC", "SimSun", ui-serif, serif;
	--font-sans: "Geist Variable", "PingFang SC", "Microsoft YaHei", ui-sans-serif, system-ui, sans-serif;
}

The family name must be the one the package registers: the -variable packages append Variable, the static ones do not. A mismatch silently falls back — issues reports it, as it reports an installed face nobody imports.

Latin faces only. CJK packages are megabytes per weight; Chinese and Japanese copy uses the platform faces listed after the Latin one in the stack above (serif: Songti SC / SimSun; sans: PingFang SC / Microsoft YaHei), so every stack names both.

The one thing nothing catches: a token that does not exist

Theme tokens in className (bg-primary, text-muted) instead of hex — but the token must exist in theme.css @theme. Tailwind generates nothing for a class it cannot resolve, so bg-brand without --color-brand leaves the element with no background at all. Same mechanism as a blank icon: the source reads perfectly, and nothing renders. Add the token first, then use it.

Structure first, lines second

Reach for whitespace, alignment and surface tone before you reach for a border: a gap twice the size of the gaps inside a group already reads as a separation, and a shared gutter already reads as a column. Then, for every line, divider or card wrapper you are about to draw, answer one question — what does it do that space could not?

The question does not presume the answer is no. A dense table, an object the user acts on, a layer that overlaps scrolling content and a field that has to be findable all answer it in a word; a wireframe, a report, a terminal UI or an engineering console answers it for most of their lines. What it catches is the line drawn out of habit — the box around every section, the rule under every heading — which is a generated-UI tell rather than neutral styling. references/taste/whitespace.md has the substitutions, the per-product-type notes, and the cases where lines are the design.

Pick the product type

This is the first decision, not an afterthought: vetd_create requires it (product, or frameSize in pixels for anything the enum cannot express), and it becomes the design's default size. Read it off the user's own words, in whatever language they wrote them — a phone app is mobile, an admin console or dashboard is desktop. An explicit user instruction always wins. Do not default to a phone frame; a dashboard at 390 wide is the most common failure.

ProductproductDefault sizeWhat matters
Mobile screenmobile390x844One primary action; thumb reach; full state coverage
Desktop app / dashboarddesktop1440x900Real density; aligned grid; no empty middle
Landing pagelanding1440x2400hero → proof → CTA rhythm
Slideslide1920x1080One idea; large type; generous margins
Poster / socialposter1080x1440One focal point; strong size contrast
Square social post—frameSize 1080x1080One focal point; strong size contrast
Infographic / chart—frameSize, freeHonest data, labeled axes, legible legend
Print (A4 portrait)—frameSize 794x1123 @96dpi, 2480x3508 @300dpiConvert mm→px yourself; 300dpi only when the user asks for print

The design default only covers frames that forgot to declare a size. A document can mix product types — a poster next to three phone screens — as long as each frame declares its own.

Templates

Start from these three. They are the shape the checker expects; deviating from them is how the mechanical issues above get triggered.

Their copy is English only because this file is; it says nothing about which language to design in. Frame titles and every label inside a frame go in the language the USER is writing to you in — same rule as your own replies.

tsx
// frames/products.tsx — a screen is composition, nothing structural
export const frame = { width: 1440, height: 900, title: "Products" };

import { StatCard } from "../components/StatCard";

export default function Products() {
	return (
		<div className="flex h-full flex-col gap-6 bg-surface p-8 text-surface-foreground">
			<h1 className="text-xl font-semibold">Products</h1>
			<div className="grid grid-cols-4 gap-4">
				<StatCard label="In stock" value="1,284" />
			</div>
		</div>
	);
}
tsx
// frames/_layout.tsx — the shell, mounted once, renders <Outlet /> itself.
// `h-full` here too: this wraps the frame, it is not a page.
import { Outlet, useLocation } from "react-router";
import { NavBar } from "../components/NavBar";

export default function Layout() {
	const { pathname } = useLocation();
	// Screens outside the app shell (login, onboarding) opt out here.
	if (pathname === "/login") return <Outlet />;
	return (
		<div className="flex h-full flex-col bg-surface">
			<NavBar />
			<div className="min-h-0 flex-1 overflow-auto">
				<Outlet />
			</div>
		</div>
	);
}
tsx
// components/NavBar.tsx — the ONLY definition of this chrome
import { Link, useLocation } from "react-router";

const items = [
	{ to: "/", label: "Overview", icon: "icon-[lucide--layout-dashboard]" },
	{ to: "/products", label: "Products", icon: "icon-[lucide--package]" },
];

export function NavBar() {
	const { pathname } = useLocation();
	return (
		<nav className="flex items-center gap-1 px-4 py-3">
			{items.map((item) => (
				<Link
					key={item.to}
					to={item.to}
					className={`flex items-center gap-2 rounded-md px-3 py-1.5 text-sm ${
						pathname === item.to ? "bg-primary/10 text-primary" : "text-muted"
					}`}
				>
					<span className={`${item.icon} size-4`} />
					{item.label}
				</Link>
			))}
		</nav>
	);
}

Workflow

New document: pick the product type → vetd_create with it → set the direction → start building. Do NOT offer the user a menu of styles: design systems are a thing the user opts into from the Design sidebar, not something you propose. Just design well for what they asked for, deriving the palette and type scale from the product itself.

If the project root has a design-resources/<slug>/ directory, the user started this project from that style in the Design sidebar; it is the style reference pack for this project and following it is the default:

  • Read its INDEX.md (the file inventory), then its DESIGN.md — that spec is the style contract for what you are about to design.
  • After vetd_create, write the pack's theme.css content into the design's own theme.css before building frames.
  • Before your first frame, Read the pack's demo HTML and screenshots too (INDEX.md marks which is which). The demo is the spec applied to a full page — it answers what DESIGN.md alone cannot: real density, spacing rhythm, component shapes, how the palette is actually distributed. Skipping it is how a design ends up on-token but off-style. They are visual reference only: study layout and mood, never copy their markup or code into frames — frames are React + the tokens you just copied, not HTML.
  • The user outranks the pack: if they ask for a different style, follow the user. Several packs side by side and no user pick: ask which one first.

The pack stays the contract in later sessions too: adding screens to a design that grew out of one, re-read its DESIGN.md (and glance at the demo) before designing anything new.

If DESIGN.md exists in the design document, the user has already applied a system — read it first and follow it, and do NOT rewrite it or theme.css.

Set the direction when neither a pack nor DESIGN.md sets the style. Left to defaults, every design converges on the same thing — the scaffold's indigo and slate, one system sans at two sizes, centred cards, a three-column feature row — and users recognise it instantly as generated. Before the first frame:

  1. Read references/taste/directions.md and references/taste/whitespace.md, then the file for the product type: references/taste/landing-structures.md for a landing page, references/taste/app-density.md for app screens and dashboards.
  2. Decide tone, anchor hue, type pairing and structure, and state them in one line of your reply — Direction: technical · cobalt (256°) · Space Grotesk + Geist · dense workbench. The user redirects from that line; no menu.
  3. Rewrite every value in the scaffold theme.css with the direction's palette (keep the token names), vetd_install the two faces, and import them at the top of theme.css — all before the first frame, so no frame is ever built on the placeholder palette.

Read references/taste/color.md, typography.md and copy.md when a decision in them is in front of you, not up front. With a pack or DESIGN.md in charge, skip the direction and still screen every capture against references/taste/anti-patterns.md — no style asks for those.

Existing document: vetd_status ONCE first. It returns the frame ids/sizes, sharedShell (existing _layout.tsx + components/ — reuse them) and issues. Read theme.css and reuse what is there. You do not need to call it again afterwards — vetd_screenshot returns issues per frame.

Then, for a multi-screen product, write in two passes:

  1. Skeleton pass. Write the shared parts (_layout.tsx, components/), then EVERY frame as a short file: the frame meta line plus the page's structural blocks — header, the grid, section placeholders. A few dozen lines each. The whole set lands on the canvas within seconds, so the user sees the screen inventory and the layout immediately, and a wrong size or a wrong route shows up before you have written any detail.
  2. Detail pass in coherent batches. Fill in real content for a small group of related frames (or the whole set when it is simple), then call vetd_screenshot once with frames: [...]. Read the returned contact sheet once and compare the screens together. Use the single frame form only for a targeted recheck after a fix. Each save still hot-reloads, so the user sees progress while one model/tool round verifies several screens.

Single screens, posters and slides skip the skeleton pass — just write the file.

Going back: every design keeps its own version history — one version per turn that changed it, saved automatically, titled with what the user asked for. So "undo that", "go back to before the nav bar moved", "restore the previous version" is vetd_history then vetd_restore, NOT you editing files until they resemble the old version from memory. Restoring is safe in both directions: it is saved as a new version too, so a wrong pick is one more vetd_restore away from being corrected — the response tells you where the pre-restore state went. The user can also do it themselves from the canvas's history panel, where the versions carry thumbnails.

Verify visually: call vetd_screenshot with all frames you created or changed (frames: [...], or all: true when the whole design is in scope), then Read the returned overview image once. You are looking for rendering defects the code cannot show you — run the checklist in references/quality.md, which starts with the three that account for most of them: misalignment, unintended text wrapping, and classes that resolve to nothing (a blank icon, or a surface whose theme token was never defined). A frame that does not parse is listed as a failed member without discarding the other captures — fix the reported line and recheck that frame only.

Every successful frame also carries a verification observation. If stalled: true, two consecutive checks produced the same image and the same issues. Do not make a third blind edit: inspect whether the checker assumption fits the visible result, and report the stalled finding when it is a false positive. vetd_status.issues: [] is source-only and is never visual proof; renderVerification tells you whether prior captures are current or stale.

Show full SKILL.md (1,569 more words)Show less

Nothing will remind you. Writing a file tells you it was written, not that it renders — the checker only speaks through vetd_screenshot and vetd_status, and neither runs by itself. A frame you wrote but never included in a screenshot batch may be sitting on the canvas as a build error or at a size you never chose, and the turn will end that way: the user is looking at the canvas, so they see it and you do not. Batch verification keeps that safety without spending one model round and one image Read per frame.

Check the structure: for a UI product with more than one screen, or with chrome that repeats across screens, answer these four before reporting back. They are the ones no checker can see; skip them for posters, slides and single-screen designs.

  1. Chrome defined once? Grep for the nav bar's markup — it must appear in exactly one file. Two frames both containing the sidebar means extract it.
  2. Shell survives navigation? Persistent chrome belongs in frames/_layout.tsx. Per-frame AppShell is acceptable only combined with <Link> navigation, otherwise nothing persists at all.
  3. Props actually match? Nothing typechecks these sources at runtime, so a renamed prop fails silently — a component taking name but always called with icon renders one fallback everywhere, and the source reads fine.
  4. Every touched frame included in the latest batch, and its overview actually Read?

User notes on the canvas: the user pins Figma-style notes onto frames (or onto empty canvas) — each is a request addressed to you. vetd_notes lists the pending ones: every note carries its thread, a source anchor re-resolved at read time (element.source = frames/x.tsx:LINE — the authoritative edit target unless anchorStale), and per-frame screenshots where numbered pins mark the exact spots. Take them one at a time: edit for one note, verify it with vetd_screenshot, then immediately resolve that one note before you start the next — never hold the replies back until every note is done. The user is watching the canvas, where each bubble flips to resolved the moment you reply, and a turn that dies halfway has to leave the finished ones already marked. That reply is what marks a note handled; never touch .notes.json yourself.

Each resolve response tells you what is still pending — when notes remain it lists them in full, anchors and annotated screenshots included, so you can go straight into the next one without another lookup. Treat pendingRemaining as your loop condition: keep handling and resolving until a resolve comes back with pendingRemaining: 0. Anything that appears there but was not in your original list is something the user pinned while you were working. Notes reach you three ways: the user sends an explicit "handle my notes" prompt, vetd_status reports a pendingNotes count, and vetd_screenshot flags pending notes on the frame it just shot.

Notes are also how the user talks to you while you are working: rather than interrupt your turn with a new message, they pin the request onto the canvas and let you pick it up. So a note can appear at any moment, including after your last screenshot — which is exactly why the Done check below runs vetd_notes even when nothing this turn mentioned notes, instead of waiting for some tool response to name one. That check is the only way those notes ever reach you: nothing will send you a follow-up message about them, so a note you skip just sits there unanswered.

Every instruction the user gives from the canvas becomes a note, so a message asking you to handle canvas notes never carries the request text itself — the text lives in the notes, and vetd_notes is where you read it. You finish each one by replying through vetd_notes's resolve, which is what puts your answer back on the canvas where the user asked and clears the pending badge.

Everything from the canvas arrives as a note. Whether the user pinned it with the note tool or typed it into the badge on a selected frame or element, it lands in .notes.json and reaches you through vetd_notes — there is no separate attachment format to learn. A note anchored to an element carries the exact frames/xxx.tsx:LINE in element.source (re-resolved at read time, authoritative unless anchorStale) plus its DOM path, classes and text, which is your edit target. If that location points into components/, the change hits every frame using it — say so in your reply.

Done means: every frame you touched is represented in the latest screenshot batch and its overview was Read, each current frame capture is free of the three screenshot defects and of the generated-UI tells in references/quality.md § 5, its per-frame issues came back empty (or a repeated false positive is explicitly reported as stalled), and no user note is left pending.

That last one has a hard rule, because nothing outside this turn will catch a miss: when you touched a .vetd design this turn, the final action — after the work, right before you write your summary — is one more vetd_notes call. Run it even when nothing this turn mentioned notes. Anything still pending is work the user asked for while you were busy: do it now, resolve it, then check again, and only report once a check comes back clean. Do not report first and leave it for "next turn" — the user deliberately did not interrupt you with a message, precisely because you were going to look here, and nothing will nudge you afterwards.

The condition is the whole rule, so read it literally: a turn in which you wrote or edited no file inside a .vetd/ directory ends with no vetd_notes call at all. Canvas notes only exist for designs on the canvas, so there is nothing to check when the work was anywhere else — editing pages in the user's own repo, answering a question, running tests, writing code that has no design attached. Calling it there is not a harmless extra check: it fails, and it tells the user you mistook their codebase for a design document. Same for every other vetd_* tool — none of them apply to work outside a .vetd.

Not one of those three is checked for you at the end of the turn — if you report back without them, whatever is broken simply stays broken. So before you report, name the frames you touched and confirm each one cleared all three.

At that point stop and report — do not keep polishing. If something is still off but you have already revised it twice, say what it is instead of attempting a third pass.

Exporting deliverables

When the user asks to export, download or hand off the design ("导出 PDF", "export all frames as images"), call vetd_export. It writes into the current working directory and each file holds the frame's FULL content, including what scrolls below the frame's viewport:

  • format: "pdf" — one <design>-frames.pdf, one page per frame.
  • format: "images" — one PNG per frame in a <design>-frames/ folder.
  • Omit frames for every frame in canvas order; pass frames: [...] when the user named specific screens.

One format per request — the one the user asked for. "Export PDF" means pdf only; "export images" means images only. Never export both: every format re-renders every frame, so doing both doubles a slow export for a file nobody asked for. If the user did not say which format, ask.

Export is not verification. For checking a design, call vetd_screenshot. vetd_export runs no checks and is only for when the user asks for exported files — do not screenshot or re-verify before exporting, and do not Read the exported files afterwards. Just tell the user where they are.

Do not rework

Rewriting your own output is the single largest waste in this workflow, and it buys nothing: a revision made without looking at the render is a guess.

  • Never re-read a file you just wrote. Its contents are already in context.
  • Fix with edit, never by rewriting the whole file with write. Both the issues and the build errors you get back name a file and a line; go there. A full rewrite costs many times more and usually introduces a new defect.
  • Screenshot before revising. Once a coherent frame batch is written, the next thing you do to it is one vetd_screenshot batch. Do not polish it first — you cannot see what is wrong yet. One evidence-based revision pass per capture; recheck only the frames you changed.
  • Do not restate the plan between steps. A todo list is worth it only when the design has more screens than you can hold at once. Create it once and update it at phase boundaries; never spend one tool round marking every frame complete immediately after its write.

References (read on demand)

Resolve against $SKILL_DIR. Do not read them all up front.

FileRead it when
references/interaction.mdWiring clicks, _layout.tsx, cross-screen flows
references/quality.mdReviewing a screenshot; before declaring any frame done
references/taste/directions.mdBefore the first frame of a new design with no pack or DESIGN.md
references/taste/whitespace.mdWeighing whether a line, divider or card wrapper earns its place; a capture looks boxed-in
references/taste/landing-structures.mdProduct type is a landing page
references/taste/app-density.mdProduct type is app screens or a dashboard
references/taste/color.mdBuilding or changing the palette, chart or status colors
references/taste/typography.mdChoosing faces, the type scale, CJK font stacks
references/taste/copy.mdWriting headlines, labels, empty and error states
references/taste/anti-patterns.mdA capture looks generic, or a tell from quality.md § 5 needs its fix

© openvetta, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 11 other files (references) in packages/plugins/presets/vetta-ui-design/agent/skills/vetta-ui-design of openvetta/open-vetta.

  • SKILL.md
  • references/interaction.md
  • references/quality.md
  • references/taste/UPSTREAM.md
  • references/taste/anti-patterns.md
  • references/taste/app-density.md
  • references/taste/color.md
  • references/taste/copy.md
  • references/taste/directions.md
  • references/taste/landing-structures.md
  • references/taste/typography.md
  • references/taste/whitespace.md

Open the folder on GitHubat commit b983179

Compare with similar skills

Vetta UI Design next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Vetta UI Design compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Vetta UI Design this skillopenvetta/open-vetta290—~7.3kAutomated safety check: PassApache-2.0
Frontend DesignYYH211/Claude-meta-skill2821 repos~2.2kAutomated safety check: PassMIT
UI UX Pro Maxsaoudi-h/solar-icons19018 repos~11kAutomated safety check: NotesCustom licence
Creative Tim UI Blockscreativetimofficial/ui12k—~2.1kAutomated safety check: NotesMIT
UI/UX Design System AdvisorGalaxy-Dawn/claude-scholar5.7k1 repos~1.1kAutomated safety check: PassMIT
Cc DesignZeroZ-lab/cc-design827—~2.2kAutomated safety check: NotesNone

Similar skills

  • Frontend Design

    YYH211/Claude-meta-skill

    Creates unique, production-grade frontend interfaces with exceptional design quality.

    282 GitHub starsUsed in 1 repo~2.2k tokens
    Frontend & DesignAuto-check passed
  • UI UX Pro Max

    saoudi-h/solar-icons

    UI/UX design intelligence for web and mobile. An agent skill from saoudi-h/solar-icons.

    190 GitHub starsUsed in 18 repos~11k tokens
    Frontend & DesignAuto-check: notes
  • Creative Tim UI Blocks

    creativetimofficial/ui

    Helps install, generate and review Creative Tim UI blocks: shadcn/ui-based React and Tailwind sections that follow a restrained, production-minded design philosophy.

    12k GitHub stars~2.1k tokensUpdated 7 mo ago
    Frontend & DesignAuto-check: notes
  • UI/UX Design System Advisor

    Galaxy-Dawn/claude-scholar

    Turns a vague UI request into a concrete design system with style, palette, typography and layout guidance from a search script, plus stack-specific implementation advice.

    5.7k GitHub starsUsed in 1 repo~1.1k tokens
    Frontend & DesignAuto-check passed
  • Cc Design

    ZeroZ-lab/cc-design

    High-fidelity HTML design and prototype creation. An agent skill from ZeroZ-lab/cc-design.

    827 GitHub stars~2.2k tokensUpdated 3 mo ago
    Frontend & DesignAuto-check: notes
  • Animated React Component Libraries

    Hainrixz/editor-pro-max

    Helps choose and drop in animated React components from Magic UI and React Bits for landing pages, marketing sites and dashboards, instead of hand-coding animations.

    264 GitHub starsUsed in 1 repo~5.7k tokens
    Frontend & DesignAuto-check passed

More from openvetta/open-vetta

All 21 skills in this repo
  • Mobile Android Design

    openvetta/open-vetta

    Master Material Design 3 and Jetpack Compose patterns for building native Android apps.

    290 GitHub starsUsed in 3 repos~950 tokens
    Auto-check passed
  • Publish Ability

    openvetta/open-vetta

    Publish a skill, scene, MCP server, plugin, or bundle to the Vetta ability marketplace.

    290 GitHub stars~1.6k tokensUpdated 2 days ago
    Auto-check passed
  • Plugin Workbench

    openvetta/open-vetta

    Create, implement, build, pack, install, reload, and manage Vetta desktop plugins for non-developers.

    290 GitHub stars~1.9k tokensUpdated 2 days ago
    Auto-check passed
  • Create Skill

    openvetta/open-vetta

    Create or update Vetta-compatible Agent Skills. An agent skill from openvetta/open-vetta.

    290 GitHub stars~1.6k tokensUpdated 2 days ago
    Auto-check passed
  • Mobile UI Design

    openvetta/open-vetta

    Design mobile-style HTML pages (iOS / Android) for preview in the Mobile UI Preview panel.

    290 GitHub stars~1.6k tokensUpdated 2 days ago
    Auto-check passed
  • Remotion Video

    openvetta/open-vetta

    Create, modify, and render Remotion React video projects in the current Vetta conversation workspace.

    290 GitHub stars~744 tokensUpdated 2 days ago
    Auto-check passed

Works with

Questions about Vetta UI Design

What does Vetta UI Design do?

Build and edit design documents (.vetd) on the Vetta design canvas — app screens, landing pages, slides, posters, infographics. Vetta UI Design is an agent skill from openvetta/open-vetta.vetd) on the Vetta design canvas — app screens, landing pages, slides, posters, infographics.

When should I use Vetta UI Design?

Vetta UI Design fits situations like: the user asks for a UI design; attaches a design frame/element from the canvas; ordinary front-end work in the users own codebase — building; reworking pages of a real app is that repos job.

How do I install Vetta UI Design in Claude Code?

Run `npx skills add openvetta/open-vetta --skill vetta-ui-design -a claude-code`. Or copy the skill folder (packages/plugins/presets/vetta-ui-design/agent/skills/vetta-ui-design in openvetta/open-vetta) into .claude/skills/vetta-ui-design in your project. Claude Code loads it when a task matches its description.

How do I install Vetta UI Design in Codex?

Run `npx skills add openvetta/open-vetta --skill vetta-ui-design -a codex`. Or copy the skill folder (packages/plugins/presets/vetta-ui-design/agent/skills/vetta-ui-design in openvetta/open-vetta) into .agents/skills/vetta-ui-design in your project. Codex loads it when a task matches its description.

Can I use Vetta UI Design in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add openvetta/open-vetta --skill vetta-ui-design -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/vetta-ui-design, .gemini/skills/vetta-ui-design, .github/skills/vetta-ui-design and .opencode/skills/vetta-ui-design in your project.

What does Vetta UI Design need to run?

SKILL.md names no scripts, command-line tools or credentials: Vetta UI Design is instructions for the agent only.

Does Vetta UI Design access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Vetta UI Design safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Vetta UI Design use?

Vetta UI Design is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Vetta UI Design use?

About 7.3k tokens (SKILL.md is roughly 29k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 14k tokens, read only when the agent opens those files.

What are the alternatives to Vetta UI Design?

Skills that share tags, products or a category with Vetta UI Design: Frontend Design (YYH211/Claude-meta-skill, 282 stars), UI UX Pro Max (saoudi-h/solar-icons, 190 stars), Creative Tim UI Blocks (creativetimofficial/ui, 12k stars) and UI/UX Design System Advisor (Galaxy-Dawn/claude-scholar, 5.7k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Vetta UI Design?

openvetta (a GitHub organization) maintains it in openvetta/open-vetta, which has 290 GitHub stars. The repository holds 21 skills in this directory. The repository was last updated on October 9, 2026.

Source: openvetta/open-vetta on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.