Find or resume component work
21st components lists every accessible personal or Team component and every
owned saved draft, draining all result pages by default. It closes with how
many new drafts you may still start this hour, so the limit is visible before a
publish runs into it. Drafts nobody returns to are reclaimed automatically
after a day of silence. Use
--status all|draft|published|private and
--scope all|personal|team:<uuid> to narrow the inventory. The returned
component:<id> and draft:<uuid> values are stable references.
21st open draft:<uuid> resumes an editable Studio draft.
21st open component:<id> creates or resumes a server-owned CLI Review
revision from the retained published component code and demos. The live
component stays unchanged until that revision is published. Each demo needs a
fresh cover; Studio prioritizes the required covers and attempts optional
videos best-effort in the background. --no-open creates or resumes the
workspace and prints its editor URL without launching a browser.
Use a local file when you already changed the source:
Look at a component without publishing it
21st render builds the component in a Studio workspace, photographs its demo,
writes default.png (and default.mp4 with --video) into --out, then
deletes the workspace — including on Ctrl-C. Nothing is published, nothing is
listed, and no draft is left behind for you to find later. Use it to check a
change before spending a publish on it.
It borrows one Studio workspace while it runs, so it counts against the same
draft limit as publishing; --keep leaves the workspace in place if you want
to open it in Studio afterwards.
Manage a library
21st library lists every library you can manage — your own and those of
teams where you are an owner or admin. update changes only what you pass:
--name, --description, --display-name, --logo <file> or
--logo-url <url>, --website, --github, --x, and --public /
--private for the library’s public page. A library whose access is private
has no public page, so --public is refused until the library itself is made
public in Studio. Logos accept PNG, JPEG, WebP or SVG up to 2 MiB. Add --json
to any of them for machine-readable output.
Publish a component
--preview satisfies that on its own — it becomes the demo’s cover and no
generated one is required.
CLI Review is an overview: the component, its demos and their media, and the
tags each state their status, with the matching form one click behind them.
Above the preview, a switcher flips between the live demo, the captured cover,
the video, and the component’s card as it appears in a listing. Access lives on
the same screen — Public or Private, plus whether to submit the component to
the catalog — so --visibility only sets the default. Publishing lands on the
published component.
Along with the Studio URL the CLI prints a review link. It opens the same
screen in a browser that is signed into nothing — an agent’s browser, a phone,
a colleague’s laptop — because it carries its own one-draft capability instead
of relying on a session. The link opens once, expires in 24 hours, and dies the
moment the draft is published or deleted; it can do nothing outside that draft.
Treat it like the draft itself: whoever holds it can finish this publish.
To update local source, pass its stable --component component:<id> ref; this
creates a pending revision and sends it through the same CLI Review instead of
updating the live component directly.
Agents and scripts can complete the same review without opening Studio:
--prepare never publishes. It waits for revision-bound automatic media and
optionally downloads it with --media-dir. --auto publishes only after every
required cover is ready; a cover attached with --preview counts as ready on
its own, so --auto --preview neither waits for nor fails on capture.
--wait-video additionally requires a successful video. Both modes are
CLI-only and never open a browser.
One draft, many edits
--draft sends the file you pass into that draft before anything else, so
fixing the component and running the command again keeps working in the same
draft instead of creating a sandbox per edit:
--demo to add demos, drop one from the command to remove it, and edited
--description, --name or --tags travel with the code. The slug and the
registry are fixed when the draft is created, since they decide what it
publishes as.
The component slug and the set of demos are fixed when the draft is created, so
a push changes code only; add --no-push to resume a draft without touching
its source, for example to finish a publish that was interrupted.
With --json, stdout carries exactly one JSON document (state, and on
success component_id, url, install_ref); all progress moves to stderr.
Exit codes are stable for scripting: 0 published, 1 generic failure,
2 draft handed off without publishing (CI), 3 auth, 4 rate limited,
5 build failed, 6 cover/media not ready, 7 conflict, 130 interrupted.
To read a draft the same way without publishing, 21st draft <draft:uuid>
prints its state, editor URL and per-demo media states; --watch streams
every transition until the draft publishes, fails or is deleted.
Common flags:
See Publishing → Quick Start for the full flow and requirements.
Controls come from the demo file
A demo that declares a module-levelconst settings = { … } and takes it as
props publishes with a live controls panel next to its preview, and visitors
copy code carrying the values they tuned. The CLI needs no flag for it: the
defaults are read from the source you publish. Labels and ranges are edited
afterwards from the component’s Edit dialog without a re-publish, but which
knobs exist and what they start at change only by publishing again. See
Demo Controls.
The current CLI Review command sends one self-contained component source file
and one demo. Additional local files,
21st.json, and registry dependencies
are not supported for either a new component or an owned revision yet.Review the CLI draft before publishing
The build check cannot detect every runtime, interaction, or theme problem. Before publishing, confirm that the build passed, every imported package is declared in the nearestpackage.json, and every demo works in the right-side
live preview. Test meaningful states in both light and dark themes, including
that the primary color resolves correctly.
Use semantic Tailwind utilities such as bg-primary and
text-primary-foreground. For custom CSS, use Tailwind v4 variables such as
var(--color-primary). Do not write oklch(var(--primary)) or
hsl(var(--primary)): projects can represent raw tokens differently, making
otherwise valid CSS render the wrong color in Studio. Use an opacity utility
such as bg-primary/20, or color-mix() with var(--color-primary).
The CLI rejects these known non-portable raw-token wrappers before it creates a
draft.
Studio starts media generation as soon as the draft is ready. It prioritizes the
required cover, which must be ready before publishing. The optional video is
best-effort in the background: publishing never waits for it and includes it
only if it is ready. An interaction video is accepted only when a click, press,
typing, keyboard, or scroll beat produces a visible result. Give interactive
controls stable semantic selectors such as an id, native role, or
data-slot; a missing selector or a visually unchanged interaction is retried
once and then fails closed instead of attaching a cursor-only clip. You can
replace either generated asset manually.
If the component is blank, throws, has unresolved dependencies, or renders the
wrong primary color, fix the source in CLI Review and save it. Studio signs the
new source revision, invalidates every cover and video from the old revision,
and queues fresh media with the required cover first. Publishing stays blocked
until that new cover is ready or you upload a replacement. An auto-generated
cover does not replace the visual and interaction review.
Private personal components are visible only to you. Publishing privately to a
Team library requires an active Team plan and owner or admin access.
When a publish fails
A failed publish prints what went wrong, which step it happened in, and the build output itself:
The JSON body of a failed
POST /api/v1/components/publish carries the same
information: error (the code above), message, retryable, request_id, and
details with stage, demo_slug or dependency, and output. Retry only
when retryable is true. The rest will fail the same way until the source
changes.
Publish a theme
:root and .dark blocks.
Publish a template
--price and a --buy-url checkout link. See Selling & promotion.
Edit your content
--type is component, theme, or template. Component metadata edit and
delete accept a saved 21st login session or API key. A Team manager can manage
a teammate’s component metadata, but only its original author can check out a
code revision. Theme/template management still requires an API key. Editable
fields differ per type (templates use numeric tag ids and have no visibility
field).
Unpublish or delete
--yes is required to confirm. For components and themes this unpublishes (sets visibility to private / clears the published date). For templates it is a permanent delete.
Deleting a draft permanently removes its unpublished sandbox and code.