spacering-net/codeg/ui-render
- community
Checking that the SKILL.md file is still in the repository.
Show results as interactive UI inside Codeg's chat (cards, tables, charts, tabs, accordions, badges, progress bars, simple forms) by writing a json-render spec code block in your reply. Use when the user invokes this skill or asks to see something as a card, table, chart, dashboard or other visual layout in Codeg.
Install
npx vskill@latest install spacering-net/codeg/ui-renderSKILL.md
Codeg renders a ```spec code block in your reply as interactive UI inside the chat. Write the block directly in your reply message, never into a file. Use it when a visual layout genuinely helps (comparisons, trends, status or progress summaries, structured results, checklists); answer in plain Markdown otherwise. The format reference follows.
OUTPUT FORMAT (text + JSONL, RFC 6902 JSON Patch): You respond conversationally. When generating UI, first write a brief explanation (1-3 sentences), then output JSONL patch lines wrapped in a ``spec code fence. The JSONL lines use RFC 6902 JSON Patch operations to build a UI tree. Always wrap them in a `spec fence block: `spec {"op":"add","path":"/root","value":"main"} {"op":"add","path":"/elements/main","value":{"type":"Card","props":{"title":"Hello"},"children":[]}} `` If the user's message does not require a UI (e.g. a greeting or clarifying question), respond with text only — no JSONL. Each line is a JSON patch operation (add, remove, replace). Start with /root, then stream /elements and /state patches interleaved so the UI fills in progressively as it streams.
Example output (each line is a separate JSON object):
{"op":"add","path":"/root","value":"main"} {"op":"add","path":"/elements/main","value":{"type":"Card","props":{"title":"Overview","description":"Your account summary"},"children":["child-1","list"]}} {"op":"add","path":"/elements/child-1","value":{"type":"Stack","props":{"direction":"vertical","gap":"md"},"children":[]}} {"op":"add","path":"/elements/list","value":{"type":"Card","props":{"title":"Overview","description":"Your account summary"},"repeat":{"statePath":"/items","key":"id"},"children":["item"]}} {"op":"add","path":"/elements/item","value":{"type":"Stack","props":{"direction":"vertical","gap":"md"},"children":[]}} {"op":"add","path":"/state/items","value":[]} {"op":"add","path":"/state/items/0","value":{"id":"1","title":"First Item"}} {"op":"add","path":"/state/items/1","value":{"id":"2","title":"Second Item"}}
Note: state patches appear right after the elements that use them, so the UI fills in as it streams. ONLY use component types from the AVAILABLE COMPONENTS list below.
INITIAL STATE: Specs include a /state field to seed the state model. Components with { $bindState } or { $bindItem } read from and write to this state, and $state expressions read from it. CRITICAL: You MUST include state patches whenever your UI displays data via $state, $bindState, $bindItem, $item, or $index expressions, or uses repeat to iterate over arrays. Without state, these references resolve to nothing and repeat lists render zero items. Output state patches right after the elements that reference them, so the UI fills in progressively as it streams. Stream state progressively - output one patch per array item instead of one giant blob: For arrays: {"op":"add","path":"/state/posts/0","value":{"id":"1","title":"First Post",...}} then /state/posts/1, /state/posts/2, etc. For scalars: {"op":"add","path":"/state/newTodoText","value":""} Initialize the array first if needed: {"op":"add","path":"/state/posts","value":[]} When content comes from the state model, use { "$state": "/some/path" } dynamic props to display it instead of hardcoding the same value in both state and props. The state model is the single source of truth. Include realistic sample data in state. For blogs: 3-4 posts with titles, excerpts, authors, dates. For product lists: 3-5 items with names, prices, descriptions. Never leave arrays empty.
DYNAMIC LISTS (repeat field): Any element can have a top-level "repeat" field to render its children once per item in a state array: { "repeat": { "statePath": "/arrayPath", "key": "id" } }. The element itself renders once (as the container), and its children are expanded once per array item. "statePath" is the state array path. "key" is an optional field name on each item for stable React keys. For nested lists, an inner repeat can read an array from the enclosing item with { "statePath": { "$item": "field" } }. This form is valid only inside another repeat. Use an empty field to repeat over the enclosing item itself. Example: {"type":"Card","props":{"title":"Overview","description":"Your account summary"},"repeat":{"statePath":"/todos","key":"id"},"children":["todo-item"]} Inside children of a repeated element, use { "$item": "field" } to read a field from the current item, and { "$index": true } to get the current array index. For two-way binding to an item field use { "$bindItem": "completed" } on the appropriate prop. ALWAYS use the repeat field for lists backed by state arrays. NEVER hardcode individual elements for each array item. IMPORTANT: "repeat" is a top-level field on the element (sibling of type/props/children), NOT inside props.
ARRAY STATE ACTIONS: Use action "pushState" to append items to arrays. Params: { statePath: "/arrayPath", value: { ...item }, clearStatePath: "/inputPath" }. Values inside pushState can contain { "$state": "/statePath" } references to read current state (e.g. the text from an input field). Use "$id" inside a pushState value to auto-generate a unique ID. Example: on: { "press": { "action": "pushState", "params": { "statePath": "/todos", "value": { "id": "$id", "title": { "$state": "/newTodoText" }, "completed": false }, "clearStatePath": "/newTodoText" } } } Use action "removeState" to remove items from arrays by index. Params: { statePath: "/arrayPath", index: N }. Inside a repeated element's children, use { "$index": true } for the current item index. Action params support the same expressions as props: { "$item": "field" } resolves to the absolute state path, { "$index": true } resolves to the index number, and { "$state": "/path" } reads a value from state. For lists where users can add/remove items (todos, carts, etc.), use pushState and removeState instead of hardcoding with setState.
IMPORTANT: State paths use RFC 6901 JSON Pointer syntax (e.g. "/todos/0/title"). Do NOT use JavaScript-style dot notation (e.g. "/todos.length" is WRONG). To generate unique IDs for new items, use "$id" instead of trying to read array length.
AVAILABLE COMPONENTS (43):
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 90 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingsrc-tauri/genui/ui-render/SKILL.md
Popularity
- 7-day trend score
- 0
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/spacering-net/codeg/ui-render)