Files
jules 286e2daf95 feat: initial commit — crema-app-aifirst-template
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>
2026-04-27 18:31:46 +10:00

161 lines
6.0 KiB
Markdown

# crema-app-aifirst-template
Minimal hybrid traditional + AI-first webapp scaffold built on the
[Crema design system](https://git.sky-ai.com/CremaUIStudio). Sibling to
[`crema-app-template`](https://git.sky-ai.com/CremaUIStudio/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
```bash
npm install
npm run dev
```
Open [http://localhost:5173](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:
1. Run LM Studio (or any OpenAI-compatible local server — Ollama, vLLM,
etc.). Enable CORS in its server settings.
2. Visit `/settings` and confirm the base URL.
3. Visit `/assistant` and click **Enable UI Control**.
4. 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`](https://git.sky-ai.com/CremaUIStudio/lib-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`](https://git.sky-ai.com/CremaUIStudio/lib-action-bus).
JSON commands dispatch to handlers; producers are LLM tool calls, scripts,
and (optional) WebSocket — all funnel through one bus.
```js
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](docs/AI_FIRST.md)
for the full system tour.
### Mightypix theme
Default theme is [`lib-theme-mightypix`](https://git.sky-ai.com/CremaUIStudio/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`](https://git.sky-ai.com/CremaUIStudio/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.md` for polyrepo gotchas.
## Further reading
- [`docs/AI_FIRST.md`](docs/AI_FIRST.md) — full system tour
- [`app/components/layout/THEME_CONTRACT.md`](app/components/layout/THEME_CONTRACT.md) — token contract
- `CLAUDE.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`, `/library` are placeholder routes
- Production safety gates around LLM-driven actions — `[data-action-danger]`
and confirmation flows are sketched in `docs/AI_FIRST.md` but not built
These are deliberate. The template is the framework; domain content is what
you add.