AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
翻譯準備中
設計系統您生成並擁有,加上能保留所有後續變更的確定性引擎,無論是人類或程式碼代理所寫。
AI 翻譯
A design system you generate and own, plus a deterministic engine that holds every later change to it, whether a person or a coding agent wrote it.
取自儲存庫 README
正在載入完整 README。 以下為已儲存的摘錄。
An open-source conformance layer for design systems in the age of coding agents.
A design system is a set of rules nobody can enforce at the moment the code is written. Zengin exposes those rules as a deterministic engine: code goes in, structured violations with suggested corrections come out. The same engine serves an agent mid-generation, a developer at the keyboard, and CI on every pull request.
Everyone else serves context. Zengin serves constraints.檢視完整 README ↗An open-source conformance layer for design systems in the age of coding agents.
A design system is a set of rules nobody can enforce at the moment the code is written. Zengin exposes those rules as a deterministic engine: code goes in, structured violations with suggested corrections come out. The same engine serves an agent mid-generation, a developer at the keyboard, and CI on every pull request.
Everyone else serves context. Zengin serves constraints.
| Package | Status | Purpose |
|---|---|---|
@zenginui/engine | Phase 1, seven rule kinds | The rule engine. Parses TSX and CSS, resolves class names through the project's own stylesheets (or an optional Tailwind adapter), checks declarations against a system's tokens and component manifest. |
@zenginui/mcp | Phase 1, four tools | stdio MCP server: zengin_check_code, zengin_get_violations, zengin_describe_system, zengin_explain_rules. |
@zenginui/hook | Phase 1 | Claude Code PostToolUse hook. Checks every file write; blocks with the violations as the reason. |
@zenginui/cli | Phase 1 | zengin check for pre-commit and CI, with --changed, --staged, and GitHub annotations. explain, init. |
@zenginui/adapter-shadcn | Phase 2 | zengin init --from shadcn: derives tokens, the component manifest and a config from a shadcn/ui project. Reproduces the taxonomy field test exactly. |
@zenginui/adapter-css | Phase 2 | zengin init --from package <name>: derives them from any installed design-system package, tokens from its CSS variables with the names kept, manifest from its .d.ts. Verified on umami. |
@zenginui/rollup | Phase 2 | zengin report in each consuming repo, zengin rollup across them: drift, adoption, suppressions, owned forks, pinned versions, deltas. Markdown, JSON, or a self-contained HTML page. |
@zenginui/registry | Phase 3 | The registry and the generator: zengin create scaffolds a project that owns its components shadcn-style, zengin add brings in more, zengin tokens compiles the token JSON. Items are built from packages/ui and examples/; the marketing site serves the public registry. |
@zenginui/mock | Phase 3 | zengin mock: typed, seeded mock data generated as plain TypeScript into the project. Presets for the entities apps show, a small schema for the rest, no runtime dependency. |
@zenginui/figma | Phase 3 | Figma both ways: tokens to Figma variables (Light and Dark modes, code syntax set to the CSS variable) and back with a report, Code Connect files from the component manifest, and a plugin that imports and exports variables in any file. |
@zenginui/ui | Phase 1, thirty-nine components | The reference design system: plain CSS, custom-property tokens, light and dark themes, Radix behavior, Storybook with manifest-driven stories. Ships the zengin/ definitions the engine enforces against, and checks itself with the engine. |
npm create zengin@latest acme -- --template saas # or: chat, auth, docs, storefront, blank, marketing, review; --framework next for the App Router
npm run mock # regenerate the SaaS template's rows from mock.json
npx zengin upgrade --write # take what the system changed since you copied it; a local edit is yours, a conflict shows its diff
cd acme && npm install && npm run dev
npm run add -- dialog tooltip
npx zengin theme plex # or: default, meadow, spec-sheet, brutal, zengin
npx zengin fonts fraunces # a font pairing: headlines, text, code; --self-host keeps Google out of the runtime
npx zengin icons tabler # the icon vocabulary drawn by a react-icons set; the names in your code stay
npx zengin define # a component you wrote yourself joins the manifest: props from its types, owns from its CSS
npx zengin brand --name Acme --logo logo.svg # your own palette, favicon and wordmark from one color
npx zengin doctor # the project itself: agent wiring, pins, generated files; --fix repairs what Zengin wrote
The project owns its components (src/components/ui, each file carrying the version it was copied from), its definitions (zengin/), a brand file, Storybook, and the MCP server and hook. The generator runs the engine on the result before it returns: a fresh project reports zero violations. Until the first npm release, run the CLI from a checkout with --local <path>.
The vision asks for one marketing page and one application workflow from the same foundations with distinct visual treatments. Both are workspace examples built on @zenginui/ui, and both are checked by the engine in CI.
examples/review-workspace is a review queue with the MCP server, hook and CLI wired in, in the default theme. Its DEMO.md replays the enforcement loop: an off-system component the way an agent writes it, the engine's 19 violations, the corrected component, zero violations, and both renders. The replay runs in CI with assertions.
examples/chat is the AI chat template: a conversation with streamed markdown, reasoning, tool calls and sources, a prompt with suggestions and a model picker, on the Vercel AI SDK with a scripted transport so it runs without a key. It is what brought the AI kit into Zengin UI. examples/saas is the SaaS dashboard template: an overview with stat cards and charts, a customers table with row actions and a detail sheet, billing with quotas, settings that save with a toast; sidebar, top bar, both schemes. It is what brought the charts, the motion presets and the breakpoint tokens into Zengin UI. examples/auth is the auth template: sign in, create account, reset and verify, one card with real validation against mock accounts. examples/docs is the docs template: sections in a sidebar, markdown pages with code and tables, an on-this-page outline, search, previous and next. examples/storefront is the storefront template: a product grid with search, filters and sort, a cart sheet with quantities and totals, a checkout dialog that places the order. examples/blank is the blank template, one card and one button. examples/marketing-site is Zengin's own marketing page, and it shows the templates as live previews with a theme picker, built from these example apps and served beside the page. Its brand is one file of token overrides (an expanded grotesk for headlines, square corners, black rules, cobalt as the single accent, both color schemes); the components have no idea. The hero panel renders real engine output for a sample file, the four surfaces sit in a Tabs component, and the page's own check passes with zero violations and zero suppressions. Building the page is what added Tabs, the display typeface token, display text sizes and the larger spacing steps to Zengin UI.
docs/field-tests/ records runs against real external codebases, every violation classified by hand, and the engine changes each run produced. First: shadcn/taxonomy, 41 violations of which 10 were false positives, then 35 with none after the fixes; the shadcn adapter reproduces that run from one command. Second: vercel/ai-chatbot on Tailwind 4, 128 then 109 with none, no hand-authored definitions, and a migration bug found that nobody had noticed. Third: umami, the first non-shadcn system (@umami/react-zen, read from the package by zengin init --from package), 255 then 147 with none, an invalid DOM attribute and a var() whose fallback is what renders, both real.
Every example app is a consumer of Zengin UI and reports on every push to main (.github/workflows/rollup.yml, scripts/report-examples.mjs); the snapshots live in reports/ and the marketing site rolls them up at build time into zengin.timurtek.com/rollup/: drift, adoption and suppressions over time, a sparkline per repository. The same two commands, zengin report --into and zengin rollup <dir>, do it for any set of repositories.
pnpm install
pnpm build
pnpm test
pnpm typecheck
pnpm --filter @zenginui/ui storybook
pnpm smoke # what the deployed site actually serves
Node 22 and pnpm 10.
pnpm smoke checks a running deployment rather than a build: every page the site's navigation promises,
the JSON the CLI reads, and the assets each page asks for, resolved the way a browser would resolve them.
It exists because the rest of the pipeline never opens a URL, so a hosting rule that rewrites a path can
break a page while the engine, the tests and CI all stay green. Pass a base URL to point it elsewhere:
node scripts/smoke.mjs http://localhost:5174. It runs on its own after every production deployment
(.github/workflows/smoke.yml) and once a day, because hosting, DNS and certificates change without a
commit.
skills/zengin/SKILL.md teaches a coding agent the loop: learn the system, write, check, apply fixes by confidence, re-check, and never suppress without a reason. Copy the directory into a project's .claude/skills/ (or wherever your agent loads skills from) alongside the MCP server or hook.
cp -r skills/zengin .claude/skills/zengin
Releases are automated with Changesets. A change a consumer should know about ships with a changeset file in .changeset/ naming the packages and bumps. On push to main, the release workflow opens a "Version packages" pull request that applies the pending bumps and changelogs; merging it publishes the affected packages to npm with provenance. Internal dependents are bumped automatically, so a change to the engine releases new patch versions of the surfaces that depend on it.
pnpm changeset # describe a change (or write the file by hand; see .changeset/README.md)
pnpm version-packages # what the release PR does, locally, if you ever need to
pnpm release # what merging the release PR does
Publishing needs an NPM_TOKEN repository secret with publish rights on the @zenginui scope.
The engine was designed against three hand-written violation examples before any of it existed: an off-system version and a corrected one that render identically, with the rule that separates them written down. Those three are the engine's fixtures, in packages/engine/test/fixtures, and returning exactly those violations on every run was its first milestone. The field tests in docs/field-tests are the same exercise against codebases nobody here wrote.