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

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:

  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, 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.md for polyrepo gotchas.

Further reading

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.

Description
Hybrid traditional + AI-first webapp scaffold (sibling of crema-app-template). Pre-wires the Assistant surface, command bus, virtual cursor, and mightypix theme.
Readme 392 KiB
Languages
TypeScript 91.5%
CSS 6.5%
JavaScript 1.8%
Shell 0.2%