PlantUML Salt UI wireframes: from ASCII to UI mockups
When you need to document “what the UI looks like” inside a Markdown-friendly diff-able file, PlantUML Salt turns ASCII boxes into readable wireframes. No drawing tool, no Figma — just text.
What is Salt Salt is PlantUML’s wireframe language. It draws UI windows in pure ASCII; the renderer turns them into readable UI mockups.
1 2 3 4 5 6 7 8 9 10 11 12 @startsalt {+ -------------------- | Order detail -------------------- Order id: | "ORD-2026-001" Customer: | "Alice" Total: | "299.00" . [Cancel] | [Pay] } @endsalt
What you get:
|...| text input field
[ ] checkbox / [X] checked
{ } window container
.{...} dotted separator
+ nested
. vertical space
Element cheat sheet
Element
Syntax
Render
Text input
placeholder
Editable field
Filled input
{"value"}
Filled field
Button
[label]
Button
Radio
( ) / (X)
Empty / selected
Checkbox
[ ] / [X]
Unchecked / checked
Dropdown
^single ^multi
Dropdown
Table
{#col1, col2, ..., rows}
Table
Real examples 1 2 3 4 5 6 7 8 9 10 11 @startsalt {+ Login ---- Email: | "Your email" Password: | "Your password" .. [^Remember me] [Login] | [Cancel] } @endsalt
Settings page 1 2 3 4 5 6 7 8 9 10 11 12 13 @startsalt {+ UserSettings { (Basic Username: | {"alice"} Email: | {"alice@example.com"} } { (Roles Role: | ( ) Member | ( ) Editor | (X) Admin } .. [Save] | [Cancel] } @endsalt
{} inside the root window groups sections.
Table view 1 2 3 4 5 6 7 8 9 10 11 12 13 @startsalt {+ Orders {#col1, col2, col3 A | B | C -- | - | - cell | cell | cell cell | cell | cell cell | cell | cell } .. [New] | [Export] | [Delete] } @endsalt
Tabs 1 2 3 4 5 6 7 8 @startsalt {+ {/ <b>Overview</b> | Settings | Permissions | History } { Tab content goes here } .. [Save] | [Cancel] } @endsalt
Markdown-embedded content 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @startsalt {+ Editor == README.md This project is a **rich text** editor... See [PlantUML](https://plantuml.com) -- separator -- - item 1 - item 2 ```plantuml @startuml class Demo @enduml
== } @endsalt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 `==...==` block renders Markdown / fenced code. ## Form (lighter variant) `@startform` / `@endform` is the same engine with a different name; pick whichever you prefer: ```plantuml @startform {+ Submit feedback Name: | "Your name" Email: | "Your email" Type | ( ) Bug | ( ) Feature | (X) Suggestion Detail | "..." .. [Submit] | [Cancel] } @endform
Pairing with JSON for API docs UI elements and data fields pair clearly:
1 2 3 4 5 6 7 8 9 10 11 @startsalt {+ User profile {/ Profile | Orders | Favorites } { Avatar: | <img> Name: | "Alice" Signed up: | "2026-07-15" Bio: | "..." } } @endsalt
Companion JSON:
1 2 3 4 5 6 7 8 9 @startjson { "user_id": 1024, "avatar_url": "https://cdn.example.com/avatars/1024.png", "name": "Alice", "created_at": "2026-07-15T14:00:00Z", "bio": "..." } @endjson
Real: full login API doc set 1 2 3 4 5 6 docs/login/ login-ui.puml # @startsalt login-request.puml # @startjson POST /login body login-response.puml # @startjson POST /login success login-errors.puml # @startjson error responses login-sequence.puml # @startuml sequence
5 separate .puml files cover the full Login API + UI + errors surface.
Error-response UI Validation errors:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @startsalt {+ Login - validation Email: | "alice|" Password: | "" . {# Error | Field --------------------------- | ----- Must be a valid email | Email At least 8 characters | Password } .. [Retry] } @endsalt
Complex dashboard 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @startsalt {+ Admin - data dashboard {/ <b>Live</b> | 7 days | 30 days | Custom } { { Metric cards (7 days) { PV: 12,345 | UV: 4,567 | Conv: 3.2% | Bounce: 21% . [+ Add] | [Export] } } { {# Hot pages, Page | PV | Share -------- | -- | ----- Home | 8000 | 35% Product | 5000 | 22% Detail | 3000 | 13% } } } @endsalt
Need
Use
Wireframe / UI mockup
@startsalt
Form fields
@startform
API response / config
@startjson
Config files
@startyaml
Sequence / class / component
standard @startuml
Anti-patterns 1. Salt with embedded CSS 1 2 3 4 5 @startsalt {+ login email: | <input type="email" class="..."> } @endsalt
Salt doesn’t support rich styles. For real layouts, switch to Figma / Storybook.
2. JSON not fenced with @startjson 1 2 3 4 5 6 @startuml { "code": 0, "data": [] } @enduml
Plain @startuml doesn’t auto-expand JSON. Always use @startjson.
3. UI nested too deep 1 2 3 @startsalt {+ root { { { { {... deep nested ... } } } } } @endsalt
Past 3 levels of {}, break into separate .puml files (or move to Figma).
Review checklist Salt
JSON
TL;DR Salt lifts wireframes back to text — diffable alongside the actual code in the same review. UI docs don’t need a separate drawing tool any more; they ride in the same git history as the schema they describe.