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>
161 lines
6.0 KiB
Markdown
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.
|