Skip to content

Documentation

Getting started

From an empty folder to a composed SaaS: scaffold the product, keep the provider, switch theme, grow it with add-page, then pull updates without losing edits. Already have an app? init and add.

1. Scaffold a SaaS app

One command generates a Next.js app composed from validated blocks — auth, an app-shell dashboard, billing, settings — plus the theme runtime and AI Kit. Generated pages are block imports plus a main landmark that stacks them.

bash
npx create-cronus-app my-app --template saas

Prefer another package manager? Use pnpm dlx create-cronus-app@latest my-app --template saas, yarn dlx create-cronus-app@latest my-app --template saas, or bunx create-cronus-app@latest my-app --template saas. Templates store and landing compose the same way. See Installation for Create Studio and existing apps.

2. The provider is already in the scaffold

The generated app already imports the tokens stylesheet and wraps the tree in CronusUIProvider. You only add this yourself when wiring an existing app.

tsx
import { CronusThemeScript, CronusUIProvider } from "@cronus-ui/theme";
export default function RootLayout({ children }) {
return (
<html lang="en" suppressHydrationWarning>
<head>
<CronusThemeScript
storageKey="theme"
defaultThemeName="aurora"
defaultModeName="dark"
/>
</head>
<body>
<CronusUIProvider
asRoot
defaultThemeName="aurora"
defaultModeName="dark"
storageKey="theme"
>
{children}
</CronusUIProvider>
</body>
</html>
);
}

Tokens are imported in globals.css via @import "@cronus-ui/tokens/styles.css". CronusThemeScript in the document head applies the saved mode before paint. See Theming for the full no-FOUC setup.

3. Switch the theme

Aurora is the default on generated products. theme set rewrites the layout attributes and cronus-ui.json. Presets: aurora, neutral, midnight, sunset, emerald.

bash
npx cronus-ui theme set aurora
npx cronus-ui theme set midnight --mode light

Override individual tokens at runtime, or build a look visually in Create and apply it with npx cronus-ui theme add. See Theming and Styling for the full API.

4. Add a page

add-page grows an already-composed app by one route: installs new blocks, updates chrome nav, and records the page in cronus-ui.json.

bash
npx cronus-ui add-page --route /faq --blocks faq,cta --nav FAQ

--route and --blocks are required. Add --nav to list the page in the shell, --dry-run to preview. Full flags live on CLI.

5. Pull updates without losing edits

upgrade 3-way-merges installed source and generated pages/layouts against .cronus-ui/base. add-page routes are kept. Never use compose --overwrite to pull updates.

bash
npx cronus-ui upgrade --all --dry-run
npx cronus-ui upgrade --all

Dry-run first, then apply. If the app was composed from a custom manifest, pass --manifest. Do not run compose --overwrite to upgrade — that wipes page edits. Full flags live on CLI.

6. Already have an app?

Run init inside the project, wrap the root with the provider, then add a component or a block. The CLI is framework-agnostic and acts on the current directory.

bash
npx cronus-ui@latest init

init writes cronus-ui.json, installs base dependencies, and wires cn(). Import tokens and wrap the tree yourself:

tsx
import "@cronus-ui/tokens/styles.css";
import { CronusThemeScript, CronusUIProvider } from "@cronus-ui/theme";
export default function RootLayout({ children }) {
return (
<html lang="en" suppressHydrationWarning>
<head>
<CronusThemeScript
storageKey="theme"
defaultThemeName="aurora"
defaultModeName="dark"
/>
</head>
<body>
<CronusUIProvider
asRoot
defaultThemeName="aurora"
defaultModeName="dark"
storageKey="theme"
>
{children}
</CronusUIProvider>
</body>
</html>
);
}

Put it at the root

The provider belongs at the very top of your tree — the layout in Next.js, the root route in TanStack Start or React Router, or wherever your app mounts.

Then copy source with add:

bash
npx cronus-ui add button

This writes components/ui/button.tsx. Import it from your aliases — it is already styled by the tokens the provider supplies.

tsx
import { Button } from "@/components/ui/button";
export default function Page() {
return (
<main className="flex min-h-svh items-center justify-center bg-surface-base">
<Button>Get started</Button>
</main>
);
}

A block is a whole section composed from primitives. Same command, different folder:

bash
npx cronus-ui add login
tsx
import { LoginBlock } from "@/components/blocks/login";
export default function SignInPage() {
return (
<main className="flex min-h-svh items-center justify-center bg-surface-base p-6">
{/* Installed source — yours to edit, restyle, and wire up. */}
<LoginBlock />
</main>
);
}

Where to go next

You have a composed product, or a themed app with a component and a block. Deepen each part.