BeatUI is an admin template built on shadcn/ui + Vite, following the shadcn philosophy end to end: the code is yours. Clone it, delete what you don't need, and edit anything — there is no package to install, no version to upgrade, no configuration API to learn. Editing the source is the configuration.
Based on satnaing/shadcn-admin (MIT), restructured into a layered template.
| Concept | Where | What it is |
|---|---|---|
| Base components | src/components/ui/ |
shadcn primitives + our shadcn-style additions. Stateless/controlled; never touch context or routing. Managed by the shadcn CLI. |
| Framework components | src/components/features/ |
Admin scenario components composed from base ones: data-table suite, layout shell, auth pages, settings, errors, command menu… May use framework providers and routing, but contain zero project-specific business — usable by any project as-is. |
| Demo | src/demo/ |
Reference pages built by filling framework components with fake business data. Not a component tier. Delete the whole directory and nothing breaks. |
| Starter | generated | This repo minus the demo. What you actually clone to start a project. |
The one red line: anything carrying project-specific business attributes (fields, enums, copy) never enters the component tiers. Scenario semantics (login, table, settings) are not business attributes — the test is: could another company use this component unchanged?
One-way dependency rule (enforced by ESLint):
components/ui ← components/features ← demo ← routes (assembly)
src/config/ holds app fill-in config (sidebar-data.ts). Framework components never import it — routes inject it via props.
- Does it have project business attributes? →
src/demo/(in your project: your feature folder) - Does it touch context or routing? →
src/components/features/ - Otherwise →
src/components/ui/
Start a project — generate the starter (layout shell + sidebar/top nav + routing + theme switching + auth pages + settings + error pages + empty home):
node scripts/create-starter.mjs ../my-admin
cd ../my-admin && git init && pnpm install && pnpm devExplore the full demo — run this repo directly:
pnpm install && pnpm devsrc/demo/users/ is the canonical CRUD pattern: table + URL-synced state + faceted filters + bulk actions + row actions + add/edit/invite/import/delete dialogs. To create your own page:
- Copy
src/demo/users/to your feature folder and rename. - Add a route under
src/routes/_authenticated/<your-page>/(copyusers/index.tsx, adjust the search schema). - Add a nav entry in
src/config/sidebar-data.ts.
What you then edit is exactly the fill-in surface: column defs, filter options, form fields + zod schema, action menus, copy. Everything else comes from @/components/features/data-table.
Styles are split by ownership in src/styles/:
| File | Owner | Content |
|---|---|---|
shadcn.css |
shadcn CLI | The standard token contract (:root/.dark + @theme inline). components.json points here, so CLI updates land here and nowhere else. |
framework.css |
this template | Base styles, utilities, animations, font variables. |
themes/ |
you | One theme = one CSS file — only token value overrides, imported last. |
To reskin: design at tweakcn.com, export, save the :root/.dark blocks as src/styles/themes/<name>.css, and import it at the end of index.css.
- shadcn components:
npx shadcn@latest add <component>keeps working —components.jsonships with the template. Note: some ui components are customized (scroll-area, sonner, separator and RTL tweaks inherited from upstream); diff before overwriting. - This template: it's a git fork — add this repo as
upstreamandgit merge/ cherry-pick. Conflicts mark exactly the places you customized; that's the model working as intended.
Vite · React 19 · TypeScript · Tailwind CSS v4 · TanStack Router/Query/Table · react-hook-form + Zod · Zustand · Vitest (browser mode)
ui/sonner.tsximports the theme context (shadcn's own implementation requires it) — the only sanctioned upward dependency from the ui tier.- The auth pages ship with a fake submit (
sleep+ toast). Wire your real auth incomponents/features/auth/*-form.tsxandsrc/stores/auth-store.ts— both are yours to edit.
