wireframe_guide
tsquare language guide
How to write a tsquare wireframe: the text format, the rules, a worked example and every component with its props. Call it once before writing your first wireframe.
Takes no parameters.

dev.tsquarePublished by tsquare.devOfficial publisherv0.14.2Updated Nov 4, 2026
Draws UI wireframes from a small text language: multi-screen boards with notes and flow arrows.
Remote MCP server that lets an assistant write tsquare text wireframes, render them to PNG for checking, and produce share or image links.
Web executable via Streamable HTTP. Remote servers run from the web runtime once configured in a workspace.
Paste this prompt into Claude Code, Codex, Cursor or another agent — or into SourceWeft chat. The agent reads this server's install guide, shows you its publisher, endpoint and sign-in, and adds it to your client once you agree. Keys never go into a command.
Read https://sourceweft.com/mcp/dev.tsquare%2Ftsquare/install.md and connect the MCP server it describes to my client. Before changing any config, show me its publisher, endpoint and sign-in method and wait for my OK. Never put an API key in a command or in a file I would commit; ask me where it should come from.Add this to your client's mcpServers config.
{
"mcpServers": {
"tsquare-wireframes": {
"type": "http",
"url": "https://tsquare.dev/mcp"
}
}
}Wireframes in plain text: easy for LLMs to write, fast to render as SVG or PNG. A small text language for low-fidelity screens, with several devices side by side and notes beside them. Built for LLMs to write: the prompt comes from the component catalog, and errors come back with line numbers so a model can fix its own output.
Save that as login.tsq, then:
Requires Node 20 or newer. To work on tsquare itself, clone the repo, run npm install, and use npm run render -- examples/notes-mobile.tsq -o notes.png --scale 2.
Getting started · The language · Components · Icons · Colors · Using it with AI
Online at tsquare.dev/playground, or locally:
The local playground uses the same renderer as the CLI; its links point to tsquare.dev. In this repo, npm run playground runs it from source.
A wireframe can be embedded anywhere an image works (Notion, GitHub, docs sites) with a link that contains the wireframe itself:
The playground's Copy link menu makes these; Embedding has the steps for Notion, GitHub and your own site. The text is compressed into the URL, not encrypted, so anyone with the link can read it; see privacy. encodeWireframe and decodeWireframe in the library produce and read the same links.
With AI
In your docs
remark-tsquare draws ```tsquare code blocks when the site is built.markdown-it-tsquare, the same for sites built on markdown-it.In your app
@tsquare-js/react shows boards, a zoomable viewer, an editor and a playground, including boards in a model's reply while it's still streaming in.In your editor and notes
.tsq files a live preview, problems as you type, highlighting and autocomplete. Also on Open VSX.```tsquare code blocks in your notes, on desktop and mobile. See the Obsidian page.One element per line; children are indented two spaces under their parent. The first line is the board.
If a bare word could mean two props (for example start, which is both an align and a justify value), write it as key=value. Code fences (```) are ignored, so a model's reply can be rendered as-is.
Structure
Wireframes are grayscale. There are three deliberate exceptions in the UI itself:
accent takes blue, indigo, violet, pink, red, orange, green or teal, or a hex color like #1a73e8. With a light hex color, text on it switches to dark and accent-colored text is darkened so it stays readable. There are no other UI color props, on purpose.
Sticky notes beside the wireframe have their own colors, since they're annotations rather than part of the UI: note "TBD" color=pink (yellow is the default, plus blue, pink and green). See Colors for more.
Each component has its own page with a rendered example and its props: see Components.
Run them with npx tsquare … (nothing to install), or install the tsquare command with npm install -g tsquare. Use - to read from stdin. In this repo, run them through npm: npm run check -- file.tsq. Files use the .tsq extension; the CLI reads any text file.
tsquare/playground exports the playground's request handler, for hosting it inside your own Node server. tsquare/viewer is the playground's zoomable board (zoom, pan, pinch, a chip per screen) for your own page: pass it the elements, then show() the SVG from renderWireframeSvg with the size and screens from measureBoardLayout (exact; boardLayout is a synchronous estimate that can be off by a line or more on boards with notes). It sets the styles its zoom math needs itself; give the stage a size, and optionally style the classes it toggles on the stage: panning (while dragging), animate (while fitting or zooming to a screen, e.g. .animate > * { transition: transform .25s }) and stale (from setStale, e.g. .stale img { opacity: .35 }). Call destroy() when you remove it. Give it the board's measureElements entries (setElements) and it reports clicks and hovers on elements, outlines them (highlight) and zooms to them (zoomTo): see Element positions. languageData() lists every component, prop, option word, icon and accent, for editor highlighting and autocomplete. In a browser bundle (esbuild, Vite, webpack) the same imports render SVG with no setup; PNG and share links need Node. On a page without a build step, <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/tsquare.min.js"></script> draws every ```tsquare code block on the page (see Embedding). See Using it with AI for the prompt and the repair loop. measureElements gives each element's box on the board and its line in the text, and elementsAt what's under a click, for making a board clickable (see Element positions).
tsquare/editorThe playground's code editor for your own page: highlighting, autocomplete for components, props, option words, icons and accents, problems underlined on their lines, Enter keeping the indentation, and pasting a whole model reply keeps just its code block. CodeMirror is bundled inside (about 125 KB compressed once your bundler minifies it), so it imports nothing and can't clash with a CodeMirror your page already has.
Give the element a height; the editor fills it. Options: doc, data, onChange, onCursorLine (the caret's line, when it moves to another), lineNumbers (default true), lineWrapping (default false: wrap long lines instead of scrolling sideways, continuation rows indented 4 spaces past their line's indentation, so they don't look like a child element) and ariaLabel (default "Wireframe text"). The editor has getText(), setText(text) (one undoable step), setIssues(issues), goToLine(n), focus(), dom and destroy().
Its colors are CSS variables, light or dark by the page's color-scheme, defaulting to the playground's:
skill/tsquare/ is a Claude skill: the syntax, the component reference, and a workflow of write → tsquare check → tsquare render → look at the PNG and fix. Copy it to ~/.claude/skills/tsquare (all projects) or <project>/.claude/skills/tsquare, and make sure npx tsquare runs where Claude works. Rebuild it after catalog changes with npm run skill.
Text is parsed into a json-render spec and validated against Zod schemas. It's then laid out and drawn by Satori into SVG; PNG output goes through resvg.
How often models write valid tsquare on the first try, with no repair round:
How it was measured, the tasks, every model output, and the scripts: eval/.
MIT. The Inter font comes from the @fontsource/inter dependency, under the SIL Open Font License 1.1. Icons are from Lucide, under the ISC license. Brand logos are from Simple Icons (CC0); the logos themselves are trademarks of their owners. The browser build (dist/browser/) bundles some dependencies, Inter and satori (MPL-2.0) among them; their notices are in dist/browser/THIRD_PARTY_LICENSES.txt.
Source: README.md at commit 3aa55c7
tsquare language guide
How to write a tsquare wireframe: the text format, the rules, a worked example and every component with its props. Call it once before writing your first wireframe.
Takes no parameters.
Render a wireframe
Check tsquare wireframe text and render it. Returns a PNG of the board so you can see it, or the problems by line number (with the valid options) if the text isn't valid. Fix every problem and call it again.
textrequiredflowsShare a wireframe
Links for valid tsquare wireframe text, the same kinds as the playground's Copy link menu: a share link to edit it in the playground, image links (SVG, PNG), Markdown and HTML. Ask only for the links the user needs (default: an SVG image link and the share link). Each link contains the whole wireframe text (compressed), so anyone with a link can read it.
textrequiredflowslinks100% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
board "Login" screen phone "Sign in" heading "Welcome back" input "Email" placeholder="[email protected]" input password "Password" checkbox "Remember me" checked button primary "Sign in" fullWidthnpx tsquare render login.tsq -o login.png --scale 2npx tsquare playground # http://localhost:4321tsquare render <file.tsq|-> [-o out.svg|out.png] [--scale 2]tsquare check <file.tsq|-> # problems by line numbertsquare fmt <file.tsq|-> [-w] # canonical formatting (drops comments)tsquare prompt # system prompt for modelstsquare playground [--port 4321] # live editor, component reference, promptnpm install tsquareimport { renderWireframe, compileWireframe, formatIssues } from "tsquare";
const { issues } = compileWireframe(source); // problems by line, empty when validconst png = await renderWireframe(source, { format: "png", scale: 2 });import { createEditor } from "tsquare/editor";import { compileWireframe, languageData } from "tsquare";
const editor = createEditor(document.getElementById("code")!, { doc: "board\n screen phone", data: languageData(), // autocomplete; leave it out for none onChange: (text) => editor.setIssues(compileWireframe(text).issues),});