Command line
buttery's command line starts an app from a template, adds pages and components to it, checks its layout, and sets buttery up in an app you have.
@butteryui/cli is the buttery command. It starts an app from one of the four templates, adds a page from buttery's patterns or a component of the app's own, runs the layout checks on the running app, and sets buttery up in a React app that doesn't have it yet. When something can't be done, it says how to fix it, and --json gives a machine the same findings as a person.
Start an app
npx create-buttery my-shop --template dashboardcreate-buttery runs buttery create with the package manager that started it, so pnpm create buttery my-shop installs with pnpm. It copies the template into a folder named after the app, puts that name in the title, the sidebar and package.json, and installs it:
Made my-shop from the dashboard template.
cd my-shop
npm run dev
Then check its layout with npx buttery check, and add pages with npx buttery add page <kind>.| Template | What it starts |
|---|---|
blank | A Vite and React app wired up for buttery, with nothing on the screen yet |
dashboard | A back office: a sidebar of pages, an overview, a table of orders with a page for each, products, search, settings and a sign-in screen |
editor | An app for making one thing at a time: a header bar, a stage and an inspector |
marketing | A one-page site: a sticky bar, a hero, what a product does and costs, and a footer |
Every app comes with buttery's lint configs, Playwright with @butteryui/test and specs of its own, VS Code snippets (bt-page, bt-component, bt-stack and the rest), an AGENTS.md and CLAUDE.md, the make-it-buttery skill, and the MCP server in each common coding agent's config. --desktop adds the Tauri shell, so the app also opens as a desktop window, and --no-install leaves installing to you.
Add a page
npx buttery add page table --name CustomersAdded src/pages/CustomersPage.tsx: a list of records in a table, with its header and actions, from DataTable.
It's at /customers in src/App.tsx, with an item in the sidebar.
Check it with npx buttery check /customers.A page starts from the example of its pattern that is a whole page, set in the page grammar: an example that isn't a page yet goes inside an AppPage with a title, and a sign-up or onboarding screen in a section of its own. In an app made from the dashboard template, the page is also wired into src/App.tsx: imported, its path in routes, a case in the page switch and an item in the sidebar, or a screen of its own outside the shell. Anywhere else, it says where to render it. --name names the component, its file, its path and its label; without it, the page keeps its example's name. Each one passes buttery check as it comes.
| Kind | The page |
|---|---|
table | A list of records in a table, with its header and actions, from DataTable |
detail | One record: its facts, its actions and what's linked to it, from DetailPage |
overview | A dashboard's numbers for a period, from MetricCard |
settings | One group of settings, each in a row, from SettingsPage |
settings-index | Every group of settings, each opening its own page, from SettingsIndex |
catalog | Items to browse and pick from, by category, from CatalogPage |
plans | Plans side by side, one recommended, from PlanComparison |
search-results | Results of a search, paged, from SearchResults |
empty | A page with nothing in it yet and the way to start, from EmptyState |
feature-intro | A feature someone hasn't turned on, and why to, from FeatureIntro |
sign-in | Signing in or signing up with a code sent by email or text, no password, from AuthFlow |
sign-up | Creating an account, from SignUpForm |
onboarding | A first run that shows the way around, from Onboarding |
landing | A marketing page in bands, from Page |
article | A long read with an aside, from ArticleLayout |
faq | Questions and answers, from Faq |
buttery add settings, onboarding, marketing-page and article add the same pages by their patterns' names, and buttery add app-shell writes src/AppFrame.tsx, a sidebar and a top bar to render the app's pages in.
Make a component
npx buttery create component OrderCard --purpose "One order, as a card."Made OrderCard:
src/components/OrderCard/OrderCard.tsx
src/components/OrderCard/order-card.css
src/components/OrderCard/OrderCard.examples.tsx
src/components/OrderCard/preview.html
src/components/OrderCard/preview.tsx
e2e/order-card.spec.ts
See it at /src/components/OrderCard/preview.html on the dev server, check it with npx buttery check /src/components/OrderCard/preview.html,
and run its spec with npx playwright test e2e/order-card.spec.ts.The component is built on buttery's public parts, Slot and variants(), with a ref, its own class and a tone variant to start from, and the purpose as its JSDoc. Its CSS file is named after it in kebab case, so --bt-order-card-* variables at its top may hold raw values the lint config allows nowhere else. The dev server serves its preview page, so buttery check runs on it like any page, and its spec runs expectButtery there.
Check the layout
npx buttery check / /customersbuttery check opens each page in the app's own Playwright and runs the checks from @butteryui/test on it, the ones expectButtery runs: overlap, overflow, text that crowds or wraps, sizes off the scale, small targets, controls out of line, contrast and the rest. A page is a path on the dev server or a whole address. When a page is a path and the app isn't running, it starts the dev server, on the port in package.json's config.port or wherever the server says it's listening, and stops it afterwards. If another app is answering on that port, it stops and says so rather than check the wrong one.
Checked / and /customers at 390 and 1280, light and dark, comfortable, in chromium.
buttery found no layout problems.Each problem comes once, with its elements, its fix and every condition it showed in:
Checked /settings at 390 and 1280, light and dark, comfortable, in chromium.
โ /settings
overflow [data-bt="SettingsSection"]:nth-child(1) > [data-bt-part="section-head"]: content overflows its width by 1466px
Fix: Give it room, let it shrink (min-width: 0 comes with Stack, Inline and Grid), wrap the text, or truncate it with <Text truncate>.
In 390x844 light comfortable chromium, 390x844 dark comfortable chromium, 1280x800 light comfortable chromium and 1280x800 dark comfortable chromium.
overflow [data-bt="SettingRow"]: content overflows its width by 558px
Fix: Give it room, let it shrink (min-width: 0 comes with Stack, Inline and Grid), wrap the text, or truncate it with <Text truncate>.
In 390x844 light comfortable chromium, 390x844 dark comfortable chromium, 1280x800 light comfortable chromium and 1280x800 dark comfortable chromium.
buttery found 2 layout problems.--json prints a list with each problem once for every condition it showed in, in the format LayoutGuard logs. Its first entry here:
{
"rule": "overflow",
"a": "[data-bt=\"SettingsSection\"]:nth-child(1) > [data-bt-part=\"section-head\"]",
"px": 1466,
"message": "content overflows its width by 1466px",
"fix": "Give it room, let it shrink (min-width: 0 comes with Stack, Inline and Grid), wrap the text, or truncate it with <Text truncate>.",
"page": "/settings",
"viewport": "390x844",
"theme": "light",
"density": "comfortable",
"engine": "chromium"
}By default it checks at 390 and 1280 wide, light and dark, in comfortable density, in Chromium. --full checks every width from 390 to 1728 in both densities, in Chromium and WebKit, and --engine webkit picks the engine. It needs @playwright/test and @butteryui/test in the app, which the templates have, and Playwright's browsers, from npx playwright install.
Set up an app you have
npx buttery initinit installs buttery's packages with the app's package manager, imports the styles and wraps the app in ButteryProvider at its entry, writes buttery's ESLint and stylelint configs when the app has none, adds lint and check scripts and buttery's VS Code snippets, and gives coding agents what they read: a section in AGENTS.md between <!-- buttery:start --> and <!-- buttery:end -->, the @AGENTS.md import in CLAUDE.md, the skill, and the MCP server in each agent's config, added to any config the app already has. What it can't do for certain, such as adding buttery's rules to an ESLint config of the app's own, it lists with how. Run again, it changes nothing:
buttery is already set up here.buttery doctor checks the setup and says how to fix what isn't right:
โ React 19.3.1
โ @butteryui/core, @butteryui/react, @butteryui/test, @butteryui/lint, @butteryui/mcp, @butteryui/cli at 1.0.0
โ src/main.tsx imports buttery's styles, which bring the Inter font
โ ButteryProvider wraps the app
โ No fonts load from the network
โ eslint.config.js uses buttery's rules
โ stylelint.config.mjs uses buttery's rules
โ buttery check can run: @playwright/test and @butteryui/test are installed
โ AGENTS.md and the agents' MCP configs know buttery
buttery is set up here.It looks at the React version, whether buttery's packages are at one version, the styles at the entry and whether they're imported twice, the provider, fonts loaded from the network, the lint configs, a desktop app's smallest window, what buttery check needs, and the agents' files.
Migrate
buttery migrate runs the codemods a release asks for, from the version the app has installed to the command line's own, or to --to. No release has needed one yet.
Exit codes
A command exits 0 when it did what was asked, 1 when check or doctor found problems, and 2 when it couldn't run, with the reason and its fix on stderr.
Related
- Installation
Starting a new app with create-buttery, adding buttery to an app you have with buttery init, working in buttery's repository, and what an app on buttery is made of.
- Testing
expectButtery, the Playwright check that fails a page that overlaps, overflows or shifts, at every size you ask for.
- MCP server
@butteryui/mcp lets a coding agent look buttery up instead of guessing: components and token values for the version in use, page starters, and checks that say how to fix what they find.
- Dashboard
A web app with a sidebar, an overview of the week's numbers, a table of orders with a page for each, products, search, settings with a plan page, and a sign-in screen, made from the App kit.