Hybrid traditional + AI-first webapp scaffold. Sibling to crema-app-template, adds the AI assistant surface, command bus, scripts dialog, and virtual cursor. What's pre-wired: - 6 routes: Overview, Resources, Activity, Assistant, Library, Settings - Collapsible rail + appbar + avatar dropdown shell (template code, not a lib) - Mobile sheet at <md - /assistant: streaming chat via @crema/llm-ui, mock fallback, model selector, token meter, retry probe, stop-while-streaming, persistent UI Control toggle - /settings: editable LM Studio endpoint + context window + response cap, with test-connection button - Markdown rendering for assistant replies; ```action``` blocks rendered as a small "Ran N actions" pill - ⌘⇧P script runner dialog + Play icon in the appbar - Two demo scripts in public/scripts/ - mightypix theme as default, scoped via <AppShell theme="mightypix"> Libs wired in tsconfig + app.css: - @crema/action-bus (the bus, parser, runner, cursor, provider, ws, llm-bridge) - @crema/llm-ui, @crema/chat-ui, @crema/aifirst-ui, @crema/notification-ui - lib-theme-mightypix Docs: - README.md — pitch + quick start + structure - docs/AI_FIRST.md — full system tour (data-action contract, bus, DSL, scripts, cursor, LLM integration) - app/components/layout/THEME_CONTRACT.md — every CSS variable a theme must declare - CLAUDE.md — orientation for an LLM working in the repo Genericized from comfy-cloud (the original prototype): - Brand defaults to "App" / Sparkles icon (override via app/lib/identity.ts) - User defaults to a stub (swap useUser() for real auth) - localStorage namespace is "crema.*" (was "comfy.*") Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
crema-app-aifirst-template
Minimal hybrid traditional + AI-first webapp scaffold built on the
Crema design system. Sibling to
crema-app-template
(the bare scaffold) — this template adds the AI assistant surface, the
command bus, scripts, and a virtual cursor.
The pitch: most surfaces are normal (sidenav, tables, forms) and an Assistant surface where the LLM can actually drive the UI on the user's behalf — click, navigate, fill, submit — through a documented command bus that scripts and remote control share.
Quick start
npm install
npm run dev
Open http://localhost:5173. The app probes a local
LM Studio at http://localhost:1234/v1 and falls back to a MockLLM if it
can't reach one — the UI is always usable.
To use the Assistant with a real model:
- Run LM Studio (or any OpenAI-compatible local server — Ollama, vLLM, etc.). Enable CORS in its server settings.
- Visit
/settingsand confirm the base URL. - Visit
/assistantand click Enable UI Control. - Type "take me to settings" — watch the cursor.
What this template gives you
App shell
app/components/layout/app-shell.tsx. Collapsible left rail (icon-only ↔
expanded with labels, persisted), top appbar (search · scripts · theme · bell
· avatar dropdown), mobile sheet at <md. Brand and user identity come from
app/lib/identity.ts — swap useBrand() / useUser() for a real session
later. Skip-to-main-content link, focus rings, [data-action] slots
throughout. The shell is template code, not a lib — fork it, customize
it, no need to upgrade an upstream.
AI assistant with UI control
/assistant route. Streams from any OpenAI-compatible LLM via
@crema/llm-ui, with mock
fallback. Message bubbles render markdown, fenced ```action blocks in the
model's reply are extracted and run through the command bus. Status bar,
model selector, token meter, retry probe, stop-while-streaming, persistent
UI Control toggle.
Command bus + DSL + virtual cursor
Provided by @crema/action-bus.
JSON commands dispatch to handlers; producers are LLM tool calls, scripts,
and (optional) WebSocket — all funnel through one bus.
window.commandBus.dispatch({ type: "navigate", path: "/resources" })
window.commandBus.listActions() // every visible [data-action] on screen
Plus a plain-text DSL for humans / LLM:
navigate /resources
wait_for resources-table
click row-acme-corp
expect detail-panel to_contain "Acme"
Hit ⌘⇧P for the script runner dialog. See docs/AI_FIRST.md for the full system tour.
Mightypix theme
Default theme is lib-theme-mightypix —
warm cream surfaces, ink-blue accent, Source Serif 4 for assistant prose.
Swap by editing one @import line in app/app.css. Per-route alt themes
via <AppShell theme="…">. See app/components/layout/THEME_CONTRACT.md.
Sibling-cloning
Crema libs are sibling git repos, not npm packages. Before npm install
you need them cloned alongside this template:
your-workspace/
crema-app-aifirst-template/ ← this repo
lib-action-bus/
lib-aifirst-ui/
lib-chat-ui/
lib-llm-ui/
lib-notification-ui/
lib-theme-mightypix/
Use the crema add CLI from
create-crema-app,
or clone manually. tsconfig paths and app.css @source lines are
pre-wired.
Structure
app/
routes/ # 6 routes: Overview, Resources, Activity, Assistant, Library, Settings
components/
layout/ # AppShell, Appbar, ThemeToggle, THEME_CONTRACT.md
assistant/ # MessageBody (markdown + action-block pill)
scripts-dialog.tsx # ⌘⇧P script runner UI
ui/ # shadcn primitives
lib/
identity.ts # useBrand() / useUser() — swap for real session
llm-settings.ts # persisted base URL / context / response cap
page-meta.ts # `pageTitle("…")` for route <title>
utils.ts # shadcn `cn()`
app.css # active theme @import + tailwind + @source lines
root.tsx # ToastProvider + CommandBusProvider
public/
scripts/
demo-tour.script # sample DSL: tour the rail
demo-search.script # sample DSL: focus + fill search
docs/
AI_FIRST.md # full system tour
Dev scripts
| Command | What it does |
|---|---|
npm run dev |
Vite dev server |
npm run build |
Production build |
npm run start |
Serve the built app |
npm run typecheck |
react-router typegen && tsc |
bash start.sh / bash stop.sh |
Run dev server in the background, log to .demo.log |
Conventions to know
[data-action="<id>"]on every interactive element — turns it into something the LLM, scripts, and tests can target. Naming:nav-*,appbar-*,avatar-*,assistant-*,settings-*, etc.- Tokens, not values.
bg-card,text-foreground,var(--primary)— never hex. - Lib-shaped components live as sibling repos. Edits commit to the lib's
own repo. See
CLAUDE.mdfor polyrepo gotchas.
Further reading
docs/AI_FIRST.md— full system tourapp/components/layout/THEME_CONTRACT.md— token contractCLAUDE.md— orientation for an LLM working in this repo
What's not in here
- Real auth —
useUser()returns a static stub - Real backend —
/resources,/activity,/libraryare placeholder routes - Production safety gates around LLM-driven actions —
[data-action-danger]and confirmation flows are sketched indocs/AI_FIRST.mdbut not built
These are deliberate. The template is the framework; domain content is what you add.