Add moi shadcn spec and applet Tailwind experiment - #78
Conversation
Experiment log from running shadcn against the applet pipeline (CLI probes, buildApplet builds, live browser verification), plus the EXPERIMENT-marked patch inlining tw-animate-css and shadcn/tailwind.css into the synthetic Tailwind entry so shadcn markup compiles in applets. Key findings: baseline drops every shadcn idiom silently; the patch restores them for +11 KB scoped CSS; the secondary token is missing in the host today; portaled overlays inherit mismatched host styles and Base UI's container prop fixes it; local/HTTP registry items install with deps, so a moi-blessed registry is viable with zero workspace config. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JktaFqESZKUaoiKttzLnW4
Two one-page proposals for how agents get shadcn components in workspaces — 0001 a moi-curated blessed registry behind `moi ui add`, 0002 the vanilla shadcn CLI over moi-scaffolded config — plus an index with the shared foundation and a decision table. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JktaFqESZKUaoiKttzLnW4
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JktaFqESZKUaoiKttzLnW4
Source dive into the shadcn package: the registry/transform engine is exported programmatically and every function accepts an in-memory config, so components.json and tsconfig.json exist only for the CLI layer. RFC 0003 proposes `moi ui add` as a thin shim over that engine — upstream catalog, shadcn's own icon transform to tabler, zero workspace config, no moi-maintained registry. Marks 0001/0002 rejected, updates the index comparison and the experiment log with round-2 findings and the verified zero-config installer PoC. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JktaFqESZKUaoiKttzLnW4
Round 3 of the shadcn research: registry addressing and URL-template model, REGISTRY_URL mirror lever, auth/error taxonomy, well-known endpoints, which CLI commands moi can re-ship over the engine, the MCP server tools, and the verified markdown docs + example-item endpoints. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JktaFqESZKUaoiKttzLnW4
Consolidates the decision for the call: Strategy A (live shadcn engine, was RFC 0003) vs Strategy B (moi-bundled component set with moi ui as a super-lite shadcn), head-to-head table, and the REGISTRY_URL hybrid that combines B's supply with A's machinery. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JktaFqESZKUaoiKttzLnW4
Captures the decided direction — moi shadcn as an opinionated shadcn-lite proxy over the pinned engine (add/docs/list, no config files, Base UI only, components in .moi/ui with relative imports, a one-file references/shadcn.md) — plus the mechanical gaps the outline missed (portal codemod in add, self-managed deps and utils.ts, forced rebuild, prerequisite patches) and the policies to settle (overwrite semantics, relative-import backstop, version/style pinning, offline UX, widget blacklist, reference regeneration). Updates the RFC index. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JktaFqESZKUaoiKttzLnW4
Dumb-on-purpose command: scaffold pre-seeds base deps, agent owns install and rebuild, add fails on existing files with a --force hint, skill-level import rule, no offline support, portals parked for a dedicated review. Adds plain-language notes on version pinning and reference-file regeneration. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JktaFqESZKUaoiKttzLnW4
Pre-seeding base deps at init is the ideal path, not a requirement: old workspaces rely on the skill listing the required deps and the agent installing them when the build fails. Reference one-pager updates ruled manual. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JktaFqESZKUaoiKttzLnW4
Round 4: measured that all paint in compiled shadcn widget CSS flows through host-inherited semantic tokens (4 hardcoded literals, all transparent), and verified live that workspace color themes never reach force-dark widgets — the frame's .dark class shadows every color token while fonts pass through. Root cause of the black-and-white-widgets feedback. Proposes separating hue from mode: derive light and dark value sets from the single theme primary. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JktaFqESZKUaoiKttzLnW4
Consolidates the decided design in one living document: opinions, command surface and exact add semantics, dependency model with the old-workspace fallback, workspace layout and skill wiring, the synthetic Tailwind patch, theming/inheritance findings with the hue-vs-mode foundation work, pinning policy, open items, and the ship plan. RFC directory demoted to decision history. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JktaFqESZKUaoiKttzLnW4
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JktaFqESZKUaoiKttzLnW4
Remove the RFC directory and the experiment log; the spec is self-contained and the research trail stays in the pull request. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JktaFqESZKUaoiKttzLnW4
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a0f3f98c4c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const contents = [ | ||
| `@import 'tailwindcss';`, | ||
| twAnimate, | ||
| shadcnTailwind, |
There was a problem hiding this comment.
Add the shared UI directory to Tailwind sources
When an applet follows the new spec and imports generated controls from ../ui/button, the class strings inside .moi/ui/button.tsx are outside sourceDir (.moi/widgets or .moi/views). This patch inlines shadcn's Tailwind extensions, but the synthetic CSS still only sources the applet directory, so Tailwind emits these variants/utilities only if the same class names also appear in the widget/view file; most installed component styling will be silently dropped. Add .moi/ui (or the walked local import graph) as a Tailwind source before this can support .moi/ui components.
Useful? React with 👍 / 👎.
| // host's index.css `:root`/`.dark` (demo values here — scoping rewrites | ||
| // `:root` onto the applet container). | ||
| `@theme inline { --color-secondary: var(--secondary); --color-secondary-foreground: var(--secondary-foreground); }`, | ||
| `:root { --secondary: oklch(0.269 0 0); --secondary-foreground: oklch(0.985 0 0); }`, |
There was a problem hiding this comment.
Keep secondary values inherited from the host theme
For any applet using bg-secondary/text-secondary-foreground, this synthetic :root rule is later scoped to the applet container by scopeAppletCss, so every applet gets fixed neutral secondary colors instead of inheriting workspace theme tokens. It also masks a future host-level --secondary because the container-scoped declaration is closer in the cascade. Keep this entry to @theme aliases only and put the actual defaults/derivations in the host theme where other tokens live.
Useful? React with 👍 / 👎.
The spec is the only deliverable on this branch; the patch ships with the foundation PR. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JktaFqESZKUaoiKttzLnW4
The earlier revert used a stale origin/main ref and downgraded the file below current main; the spec is the only change on this branch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JktaFqESZKUaoiKttzLnW4
Verified: shadcn aliases cannot be relative paths — the CLI validates them against tsconfig paths or package.json imports and rejects ./utils; registry content hardcodes @/registry/<style> paths and the alias rewrite is CLI-internal. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JktaFqESZKUaoiKttzLnW4
Rewrite module specifiers on the SourceFile already built for the icon transform instead of string replacement — AST-accurate, covers re-exports, no added dependency. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JktaFqESZKUaoiKttzLnW4
Documents the decided shadcn strategy for applets in a single spec,
docs/moi-shadcn.md—moi shadcn, a shadcn-lite proxy over theshadcnpackage's programmatic engine: zero config files in the workspace, always Base UI, components in.moi/ui/, and a deliberately dumb command that writes source files and prints next steps. Every empirical claim in the spec was verified by experiment during this session (research trail in the session log below).The one behavior change is a small
EXPERIMENT-marked patch to the applet build:Without it, every shadcn idiom is silently dropped by Tailwind v4 (verified); with it, all emit correctly scoped, +11 KB usage-driven.
Worth a close look:
server/bundler/build-applet.ts— the only code change; affects every applet build. Includes demo--secondaryvalues that belong in the host theme and will move there in the foundation PR.docs/moi-shadcn.md§Theming — records a live host bug (workspace color themes never reach force-dark widgets; only fonts pass through) with the proposed hue-vs-mode fix.adddoes — the command's non-responsibilities (no install, no rebuild, no overwrite) are load-bearing design decisions, not omissions.Verified:
bun test server/test/build-applet.test.ts server/test/applet-css.test.ts— 54 pass, 0 fail; live browser runs confirm the portal finding and the theme cascade; a zero-config installer PoC installed 4 registry components end to end through the moi build.🤖 Generated with Claude Code
https://claude.ai/code/session_01JktaFqESZKUaoiKttzLnW4