From 8cd58052ddac4e295e0de41b6c71dd7892e19b92 Mon Sep 17 00:00:00 2001 From: jules Date: Mon, 27 Apr 2026 18:47:40 +1000 Subject: [PATCH] feat: scripts/sync-libs.mjs + docs/LIBS.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generates a compact lib catalog from the live crema-manifest, sorted into "wired in this project" and "available to add" tables. The development LLM (Claude Code, Cursor, etc.) reads this when answering "is there a lib for X" — saves it from re-deriving the answer or making one up. The script reads the project's tsconfig.json paths (for wired libs) and app/app.css @import lines (for the active theme), clones the manifest, and emits docs/LIBS.md with stable formatting. CLAUDE.md updated to point at LIBS.md (was pointing directly at the live manifest URL — slower for an LLM that wants a quick scan). Run after `crema add ` or whenever you want a refresh: npm run sync-libs Auto-detects: - Wired libs from tsconfig.json @crema/* paths - Active theme from app/app.css `@import "../../lib-theme-*/theme.css"` lines Output is intentionally compact — terse one-line descriptions, alpha sort, no front-matter. ~9KB for the current 5-wired / 50-available split. Co-Authored-By: Claude Opus 4.7 (1M context) --- .boot.log | 9 ++ docs/LIBS.md | 99 ++++++++++++++++++++ package.json | 3 +- scripts/sync-libs.mjs | 212 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 322 insertions(+), 1 deletion(-) create mode 100644 .boot.log create mode 100644 docs/LIBS.md create mode 100644 scripts/sync-libs.mjs diff --git a/.boot.log b/.boot.log new file mode 100644 index 0000000..7da2e09 --- /dev/null +++ b/.boot.log @@ -0,0 +1,9 @@ + +> dev +> react-router dev + +Port 5173 is in use, trying another one... + ➜ Local: http://localhost:5174/ + ➜ Network: use --host to expose +6:37:06 pm [vite] (client) ✨ new dependencies optimized: lucide-react, @base-ui/react/button, class-variance-authority, @base-ui/react/input, @base-ui/react/avatar, @base-ui/react/dialog, clsx, tailwind-merge, @base-ui/react/menu, react-markdown +6:37:06 pm [vite] (client) ✨ optimized dependencies changed. reloading diff --git a/docs/LIBS.md b/docs/LIBS.md new file mode 100644 index 0000000..4b0f7f9 --- /dev/null +++ b/docs/LIBS.md @@ -0,0 +1,99 @@ +# Available Crema libs + +> Generated by `scripts/sync-libs.mjs` from crema-manifest@3.1.0. +> Run `npm run sync-libs` to refresh. + +Every `@crema/*-ui` lib is its own git repo at +`https://git.sky-ai.com/CremaUIStudio/lib--ui`. To add one, clone it +as a sibling of this project, then add the tsconfig path entry and the +`@source` line to `app/app.css` (the marker comments make this easy). + +## Wired in this project (5) + +These are importable from your code right now (`import { … } from "@crema/"`): + +| Lib | Alias | Purpose | +|---|---|---| +| `action-bus` | `@crema/action-bus` | Anything-can-drive-the-UI command bus. Single dispatch point for LLM tool calls, scripts, and (optional) WebSocket remote control. JSON c… | +| `aifirst-ui` | `@crema/aifirst-ui` | AI-first card primitives: AICard with left-border accent + canonical anatomy (title, metadata, AI rationale, verb-prefixed action buttons… | +| `chat-ui` | `@crema/chat-ui` | Chat threads, message bubbles, composer, channel list | +| `llm-ui` | `@crema/llm-ui` | LLM client + React bindings. Two adapters out of the box: OpenAICompatibleAdapter (LM Studio, Ollama, DeepSeek, OpenAI, Together, Groq, O… | +| `notification-ui` | `@crema/notification-ui` | Toasts, badges, bell, banners, inbox, notification center | + +## Active theme + +| Theme | Dark mode | Purpose | +|---|---|---| +| `mightypix` | supported | Warm AI-first companion to pristine. Cream paper surfaces, deep ink-blue accent, soft flat elevation, asymmetric typography (Inter for UI chrome, Source Seri… | + +## Available to add (50) + +From the manifest. To wire one in: `crema add ` (CLI), or +manually clone the repo + edit `tsconfig.json` paths + `app/app.css` +`@source`. + +| Lib | Alias | Purpose | +|---|---|---| +| `a11y-ui` | `@crema/a11y-ui` | Skip links, focus trap/ring, shortcut overlay, contrast checker | +| `agent-ui` | `@crema/agent-ui` | Agentic UI atoms: action proposals + queue, diff proposals, tool-call audit cards, multi-step run panel with step trail and milestone rai… | +| `artifact-ui` | `@crema/artifact-ui` | AI-generated artifacts as cards: code, file, email, sql, draft, chart, image, dataset. Type-specific previews, draft/reviewing/applied li… | +| `auth-ui` | `@crema/auth-ui` | Sign-in, sign-up, MFA, password reset, OAuth buttons | +| `billing-ui` | `@crema/billing-ui` | Pricing tables, plan comparison, usage meters, invoices, payment methods | +| `calendar-ui` | `@crema/calendar-ui` | Calendar grid, week/day views, event cards, scheduling | +| `callcentre-ui` | `@crema/callcentre-ui` | Agent desktop: softphone, active call card, queue, history, customer lookup, scripts, knowledge search, transcript, notes, disposition, w… | +| `card-ui` | `@crema/card-ui` | Theme-agnostic card primitives: three-zone template (media / body / actions) with portrait, landscape, compact, wide-banner orientations;… | +| `chart-ui` | `@crema/chart-ui` | Themed charting primitives: sparkline, line, bar, donut, heatmap. Pure SVG, currentColor-driven. | +| `code-ui` | `@crema/code-ui` | Code blocks, diff viewer, syntax highlighting, file tree | +| `codereview-ui` | `@crema/codereview-ui` | Code review primitives in two registers, sharing PullRequest/DiffHunk/ReviewComment/Reviewer types. Plain: PullRequestCard (queue row), D… | +| `color-ui` | `@crema/color-ui` | Color picker, swatches, palettes, contrast tooling | +| `command-ui` | `@crema/command-ui` | Command palette (⌘K) with self-registering commands, fuzzy match, keyboard navigation. | +| `comments-ui` | `@crema/comments-ui` | Threaded comments, mentions, reactions, presence | +| `commerce-ui` | `@crema/commerce-ui` | Product cards, cart, checkout, order summary | +| `content-editor-ui` | `@crema/content-editor-ui` | Rich-text editor (Tiptap), blog composer, slash menu, image embeds | +| `content-media-ui` | `@crema/content-media-ui` | Media library, image gallery, video/audio players, lightbox | +| `content-ui` | `@crema/content-ui` | Article display, prose styles, table of contents, callouts | +| `crm-ui` | `@crema/crm-ui` | CRM-domain primitives in two registers sharing the same Deal/Contact/Company/Activity types (Deal includes probability for forecasting; C… | +| `dashboard-ui` | `@crema/dashboard-ui` | Stat cards, KPI tiles, gauges, sparklines, heatmap calendar | +| `data-ui` | `@crema/data-ui` | Lists, key-value, definition rows, descriptive blocks | +| `diagram-ui` | `@crema/diagram-ui` | Node graphs, flow diagrams, swimlanes, sequence diagrams | +| `ehr-ui` | `@crema/ehr-ui` | EHR primitives in two registers, sharing Patient/Vital/Medication/Allergy/LabResult/Order/ProblemListItem/Encounter types. Plain: Patient… | +| `eval-ui` | `@crema/eval-ui` | Eval result UI: score cards, A/B comparison rows, run grids, score distributions. | +| `feedback-ui` | `@crema/feedback-ui` | Alerts, banners, empty states, error boundaries | +| `file-ui` | `@crema/file-ui` | Dropzone, file grid/list, previewers, upload progress, browser | +| `fleetops-ui` | `@crema/fleetops-ui` | Air traffic / fleet ops: radar map, flight strips, status badges, schedule gantt, weather, runway load, aircraft health, crew | +| `flow-ui` | `@crema/flow-ui` | Workflow / state-machine canvas: drag nodes, draw edges, execute with branching decisions. | +| `form-ui` | `@crema/form-ui` | Forms, fields, validation, multi-step wizards | +| `futurecafe-ui` | `@crema/futurecafe-ui` | Near-future café barista dashboard: AI↔AI handshake summary, customer card with mood/vibe, pedestrian approach map, arrival countdown, or… | +| `inflight-aurora-ui` | `@crema/inflight-aurora-ui` | Near-future supersonic cabin UI (second theme): glassmorphism aurora aesthetic — flight arc globe, trip timeline, ETA, altitude strip, ov… | +| `inflight-ui` | `@crema/inflight-ui` | Near-future luxury inflight passenger UI: flight map arc, trip timeline, ETA, altitude strip, gourmet menu, order tray, cabin mood, windo… | +| `kanban-ui` | `@crema/kanban-ui` | Kanban board, draggable cards, columns, swimlanes | +| `layout-ui` | `@crema/layout-ui` | Grids, stacks, dividers, sidebars, scroll areas | +| `log-ui` | `@crema/log-ui` | Streamed log viewer: level filter, structured-field expansion, follow-mode auto-scroll, pause/resume/clear. | +| `map-ui` | `@crema/map-ui` | SVG maps (world, US states), choropleth, spatial primitives, game grid | +| `morph-ui` | `@crema/morph-ui` | Shared-element container primitive: tiles with icon/card/workspace states, FLIP transitions, body-portaled workspace with grid-centered l… | +| `motorsport-ui` | `@crema/motorsport-ui` | F1 / motorsport: animated track map, telemetry cluster, tyre + sector badges, lap timing tower, race control, stint chart, pit stop seque… | +| `onboarding-ui` | `@crema/onboarding-ui` | Welcome cards, checklists, wizards, coachmarks, product tours | +| `presence-ui` | `@crema/presence-ui` | Human + agent presence layer: avatars, ambient strips, rails, workspace panel, proposals with voting, interrupt dock, inline threads, cro… | +| `print-ui` | `@crema/print-ui` | Print provider, page sizes, invoice/receipt/label/badge templates | +| `prompt-ui` | `@crema/prompt-ui` | Prompt + template authoring: variable highlighting, token estimation, version diff. | +| `property-man-ui` | `@crema/property-man-ui` | Real estate listings, property cards, gallery, filter facets, mortgage calculator, agent cards | +| `rag-ui` | `@crema/rag-ui` | Retrieval result UI: ranked chunks with highlighted spans, source attribution, retriever comparison. | +| `search-ui` | `@crema/search-ui` | Search input, command palette, facets, query tokens | +| `settings-ui` | `@crema/settings-ui` | Settings shell, preferences, profile, API keys, danger zone | +| `status-ui` | `@crema/status-ui` | System status board: components with uptime grids, incident timeline, maintenance windows. Renders subgrid-aligned bars across rows. | +| `table-ui` | `@crema/table-ui` | Sortable tables, row selection, pagination, sticky headers | +| `tool-ui` | `@crema/tool-ui` | Agentic tool catalog, schema editor, and mock-execution preview. Pairs with agent-ui (single-call display) as the management surface for … | +| `typography-ui` | `@crema/typography-ui` | Type scale, font specimens, prose blocks | + +## Other themes (5) + +Swap by changing the `@import "../../lib-theme-/theme.css"` line at the top of `app/app.css`. + +| Theme | Dark mode | Purpose | +|---|---|---| +| `arcade` | dark-only | Gaming-shell theme: dark-first cobalt canvas, electric-cyan CTA, neon burst accents, sharper radii, snappier motion. For app surfaces around a game (lobby, s… | +| `caffe-florian` | supported | Editorial theme for content-first apps — cream parchment surfaces, Venetian red accent, Libre Baskerville display + DM Sans body. Generous line-heights, soft… | +| `otium` | supported | Pristine UI's Apple-inspired glass aesthetic with generous, spacious typography. Sharp clean translucent surfaces, hairline borders, vibrancy stack. More rel… | +| `pristine` | supported | Apple-inspired glass design system with translucent surfaces, spring motion, and SF/Inter typography. | +| `swish` | supported | Touchscreen Apple-feel theme for shared surfaces (inflight seatback, automotive passenger, kiosks). Saturated-and-serene sky canvas with opaque matte chiclet… | + diff --git a/package.json b/package.json index 4824f55..3bff5e7 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "build": "react-router build", "dev": "react-router dev", "start": "react-router-serve ./build/server/index.js", - "typecheck": "react-router typegen && tsc" + "typecheck": "react-router typegen && tsc", + "sync-libs": "node scripts/sync-libs.mjs" }, "dependencies": { "@base-ui/react": "^1.4.0", diff --git a/scripts/sync-libs.mjs b/scripts/sync-libs.mjs new file mode 100644 index 0000000..9bbd367 --- /dev/null +++ b/scripts/sync-libs.mjs @@ -0,0 +1,212 @@ +#!/usr/bin/env node +// Refresh docs/LIBS.md from the live crema-manifest. Reads this project's +// tsconfig.json + app.css to figure out which libs/themes are "wired in", +// clones the manifest, and emits a markdown table for each (wired vs +// available). Run after `crema add `, or whenever you want a fresh +// catalog snapshot for the development LLM to consult. +// +// Usage: npm run sync-libs +// +// The output is intentionally compact — terse one-line descriptions, alpha +// sort, no front-matter. CLAUDE.md points at LIBS.md so the LLM finds it. + +import { execSync } from "node:child_process" +import { mkdtempSync, readFileSync, writeFileSync } from "node:fs" +import { tmpdir } from "node:os" +import { join, resolve, dirname } from "node:path" +import { fileURLToPath } from "node:url" + +const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..") +const MANIFEST_REPO = "https://git.sky-ai.com/CremaUIStudio/crema-manifest.git" + +function readJson(path) { + return JSON.parse(readFileSync(path, "utf8")) +} + +function readJsonc(path) { + // tsconfig.json sometimes has // and /* */ comments. Strip them, but only + // outside strings (so https:// URLs inside string values survive). + const raw = readFileSync(path, "utf8") + let out = "" + let i = 0 + let inString = false + while (i < raw.length) { + const c = raw[i] + const c2 = raw[i + 1] + if (inString) { + out += c + if (c === "\\" && i + 1 < raw.length) { + out += raw[i + 1] + i += 2 + continue + } + if (c === '"') inString = false + i++ + continue + } + if (c === '"') { + inString = true + out += c + i++ + continue + } + if (c === "/" && c2 === "/") { + while (i < raw.length && raw[i] !== "\n") i++ + continue + } + if (c === "/" && c2 === "*") { + i += 2 + while (i < raw.length - 1 && !(raw[i] === "*" && raw[i + 1] === "/")) i++ + i += 2 + continue + } + out += c + i++ + } + return JSON.parse(out) +} + +function cloneManifest() { + const dir = mkdtempSync(join(tmpdir(), "crema-manifest-")) + execSync(`git clone --depth 1 --quiet ${MANIFEST_REPO} ${dir}`, { + stdio: "ignore", + }) + return readJson(join(dir, "manifest.json")) +} + +function detectWiredLibs(tsconfigPath) { + const ts = readJsonc(tsconfigPath) + const paths = ts?.compilerOptions?.paths ?? {} + const wired = new Set() + for (const key of Object.keys(paths)) { + const m = /^@crema\/([a-z0-9-]+)$/.exec(key) + if (m) wired.add(m[1]) + } + return [...wired].sort() +} + +function detectWiredThemes(cssPath) { + const css = readFileSync(cssPath, "utf8") + const re = /@import\s+["']\.\.\/\.\.\/lib-theme-([a-z0-9-]+)\/theme\.css["']/g + const wired = new Set() + let m + while ((m = re.exec(css)) !== null) wired.add(m[1]) + return [...wired].sort() +} + +function row(entry) { + const desc = (entry.description ?? "").replace(/\s+/g, " ").trim() + const oneline = desc.length > 140 ? desc.slice(0, 137) + "…" : desc + return `| \`${entry.name}\` | \`${entry.alias ?? `@crema/${entry.name}`}\` | ${oneline} |` +} + +function themeRow(entry) { + const desc = (entry.description ?? "").replace(/\s+/g, " ").trim() + const oneline = desc.length > 160 ? desc.slice(0, 157) + "…" : desc + return `| \`${entry.name}\` | ${entry.darkMode ?? "—"} | ${oneline} |` +} + +function buildMarkdown(manifest, wiredLibs, wiredThemes) { + const libs = [...(manifest.libs ?? [])].sort((a, b) => + a.name.localeCompare(b.name), + ) + const themes = [...(manifest.themes ?? [])].sort((a, b) => + a.name.localeCompare(b.name), + ) + + const wiredSet = new Set(wiredLibs) + const wiredThemeSet = new Set(wiredThemes) + + const wiredLibEntries = libs.filter((l) => wiredSet.has(l.name)) + const availableLibEntries = libs.filter((l) => !wiredSet.has(l.name)) + const wiredThemeEntries = themes.filter((t) => wiredThemeSet.has(t.name)) + const availableThemeEntries = themes.filter((t) => !wiredThemeSet.has(t.name)) + + const wiredOnlyNotInManifest = wiredLibs.filter( + (n) => !libs.some((l) => l.name === n), + ) + + const lines = [] + lines.push( + `# Available Crema libs`, + ``, + `> Generated by \`scripts/sync-libs.mjs\` from crema-manifest@${manifest.version}.`, + `> Run \`npm run sync-libs\` to refresh.`, + ``, + `Every \`@crema/*-ui\` lib is its own git repo at`, + `\`https://git.sky-ai.com/CremaUIStudio/lib--ui\`. To add one, clone it`, + `as a sibling of this project, then add the tsconfig path entry and the`, + `\`@source\` line to \`app/app.css\` (the marker comments make this easy).`, + ``, + `## Wired in this project (${wiredLibEntries.length})`, + ``, + `These are importable from your code right now (\`import { … } from "@crema/"\`):`, + ``, + `| Lib | Alias | Purpose |`, + `|---|---|---|`, + ...wiredLibEntries.map(row), + ``, + ) + + if (wiredOnlyNotInManifest.length) { + lines.push( + `> ⚠ Wired in tsconfig but not in the manifest catalog: ${wiredOnlyNotInManifest.map((n) => `\`${n}\``).join(", ")}. Probably an internal or experimental lib.`, + ``, + ) + } + + lines.push( + `## Active theme${wiredThemeEntries.length === 1 ? "" : "s"}`, + ``, + `| Theme | Dark mode | Purpose |`, + `|---|---|---|`, + ...(wiredThemeEntries.length + ? wiredThemeEntries.map(themeRow) + : ["| (none detected) | — | — |"]), + ``, + `## Available to add (${availableLibEntries.length})`, + ``, + `From the manifest. To wire one in: \`crema add \` (CLI), or`, + `manually clone the repo + edit \`tsconfig.json\` paths + \`app/app.css\``, + `\`@source\`.`, + ``, + `| Lib | Alias | Purpose |`, + `|---|---|---|`, + ...availableLibEntries.map(row), + ``, + ) + + if (availableThemeEntries.length) { + lines.push( + `## Other themes (${availableThemeEntries.length})`, + ``, + `Swap by changing the \`@import "../../lib-theme-/theme.css"\` line at the top of \`app/app.css\`.`, + ``, + `| Theme | Dark mode | Purpose |`, + `|---|---|---|`, + ...availableThemeEntries.map(themeRow), + ``, + ) + } + + return lines.join("\n") +} + +function main() { + console.log("→ cloning manifest…") + const manifest = cloneManifest() + console.log(` manifest@${manifest.version} (${(manifest.libs ?? []).length} libs, ${(manifest.themes ?? []).length} themes)`) + + const wiredLibs = detectWiredLibs(join(ROOT, "tsconfig.json")) + console.log(`→ wired libs: ${wiredLibs.length} (${wiredLibs.join(", ") || "(none)"})`) + + const wiredThemes = detectWiredThemes(join(ROOT, "app", "app.css")) + console.log(`→ wired themes: ${wiredThemes.length} (${wiredThemes.join(", ") || "(none)"})`) + + const md = buildMarkdown(manifest, wiredLibs, wiredThemes) + const outPath = join(ROOT, "docs", "LIBS.md") + writeFileSync(outPath, md + "\n") + console.log(`→ wrote ${outPath} (${md.length} chars)`) +} + +main()