Skip to content

Commit 487dd3d

Browse files
feat(ui): publish @decocms/ui as an open-source design system with Storybook and Claude Code skill (#5867)
* feat(ui): make @decocms/ui a publishable open-source package - Rename @deco/ui -> @decocms/ui (npm scope owned by decocms) - Move Studio-domain code out of the design system: github url helpers and the sound engine now live in apps/web; delete dead llm-model-selector and models-binding-provider (no consumers) - Rewrite internal self-package imports to relative paths - Publishing metadata: MIT license, repository, files, publishConfig, sideEffects; react/react-dom/react-hook-form/sonner become peerDependencies; drop unused date-fns - Add tsc dist build (ESM + d.ts). Dual exports: extension-suffixed subpaths resolve to TS source (monorepo DX), extensionless subpaths resolve to compiled dist (external consumers) - components.json: rsc false (SPA library) * feat(ui): add Storybook 10 with stories for every component - Storybook 10 (react-vite) in packages/ui: docs, a11y, and theme addons; light/dark toggle via the design system's .dark class; Tailwind v4 through @tailwindcss/vite - Stories for all 67 components, co-located as src/components/*.stories.tsx (excluded from the npm tarball and the dist build) - Design System foundation pages: Welcome (install + principles), Colors (semantic token reference), Typography (families, weights, scale) - bun run --cwd=packages/ui storybook to develop, build-storybook for the static site * feat(ui): npm publish workflow, Storybook Pages deploy, and Claude Code skill - publish-ui-npm.yaml: auto-publish @decocms/ui on version change (mirrors the bindings publish flow, OIDC provenance) - deploy-storybook.yml: build and deploy the Storybook to GitHub Pages on pushes to main touching packages/ui - Claude Code plugin marketplace at the repo root with a decocms-ui plugin; its skill teaches agents to install and use the design system (tokens, imports, component inventory, conventions) * fix(ui): deploy Storybook to Cloudflare Pages instead of GitHub Pages decocms-ui.pages.dev reads as the design system's own home; the GitHub Pages URL would be pinned under the studio repo path. Reuses the CF credentials already used by deploy-docs. * feat(ui): attach designsystem.decocms.com to the Storybook Pages project Adds an idempotent workflow step that attaches the custom domain via the Cloudflare API (wrangler has no pages-domain command) and makes it the canonical docs URL in the skill, plugin metadata, and release notes. * refactor(ui): deploy Storybook as Cloudflare Worker static assets Replaces the Pages project + curl domain step with a declarative wrangler.jsonc: assets-only Worker with designsystem.decocms.com as a custom_domain route. Validated with wrangler deploy --dry-run. * fix(ui): delete dead code surfaced by knip after the sound/github move Inside packages/ui these files had no knip entry config, so their reachability was never analyzed; moving them into apps/web exposed them. Removes the three unreferenced sound assets and the uncalled fetchGitHubReadme, and narrows sound-engine helpers to module-private.
1 parent e6b756a commit 487dd3d

586 files changed

Lines changed: 8323 additions & 1745 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude-plugin/marketplace.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "decocms",
3+
"owner": {
4+
"name": "decocms",
5+
"url": "https://github.com/decocms"
6+
},
7+
"plugins": [
8+
{
9+
"name": "decocms-ui",
10+
"source": "./packages/ui",
11+
"description": "Build UI with the decocms product design system (@decocms/ui): install, tokens, components, and conventions.",
12+
"author": { "name": "decocms" },
13+
"homepage": "https://designsystem.decocms.com/"
14+
}
15+
]
16+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Deploy Storybook
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- "packages/ui/**"
8+
workflow_dispatch:
9+
10+
jobs:
11+
deploy:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Checkout repository
15+
uses: actions/checkout@v4
16+
17+
- name: Setup Bun and install dependencies
18+
uses: ./.github/actions/setup-bun
19+
20+
- name: Build Storybook
21+
run: bun run build-storybook
22+
working-directory: packages/ui
23+
24+
- name: Deploy to Cloudflare Workers (static assets)
25+
run: bunx wrangler deploy
26+
working-directory: packages/ui
27+
env:
28+
CLOUDFLARE_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
29+
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
name: Publish @decocms/ui
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- "packages/ui/**"
8+
workflow_dispatch:
9+
10+
permissions:
11+
contents: write
12+
id-token: write
13+
14+
jobs:
15+
publish:
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: Checkout code
19+
uses: actions/checkout@v4
20+
with:
21+
fetch-depth: 0
22+
23+
- name: Setup Node.js for npm registry
24+
uses: actions/setup-node@v4
25+
with:
26+
node-version: "24"
27+
registry-url: "https://registry.npmjs.org"
28+
29+
- name: Setup Bun and install dependencies
30+
uses: ./.github/actions/setup-bun
31+
32+
- name: Check if version changed
33+
id: version-check
34+
run: |
35+
# Get the current version from package.json
36+
CURRENT_VERSION=$(bun -e "console.log(require('./package.json').version)")
37+
38+
# Check if this specific version already exists in npm
39+
# This works for both stable and prerelease versions (unlike checking 'latest' tag)
40+
if npm view @decocms/ui@$CURRENT_VERSION version >/dev/null 2>&1; then
41+
echo "version-changed=false" >> $GITHUB_OUTPUT
42+
echo "⏭️ Version $CURRENT_VERSION already published, skipping publish"
43+
else
44+
echo "version-changed=true" >> $GITHUB_OUTPUT
45+
echo "✅ Version $CURRENT_VERSION not found in npm, will publish"
46+
fi
47+
48+
echo "current-version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
49+
50+
# Check if this is a prerelease version (contains a hyphen)
51+
if [[ "$CURRENT_VERSION" == *-* ]]; then
52+
echo "npm-tag=next" >> $GITHUB_OUTPUT
53+
echo "📦 Prerelease version detected, will publish with tag 'next'"
54+
else
55+
echo "npm-tag=latest" >> $GITHUB_OUTPUT
56+
echo "📦 Stable version detected, will publish with tag 'latest'"
57+
fi
58+
working-directory: packages/ui
59+
60+
- name: Publish to npm
61+
if: steps.version-check.outputs.version-changed == 'true'
62+
run: npm publish --access public --tag ${{ steps.version-check.outputs.npm-tag }} --provenance
63+
working-directory: packages/ui
64+
65+
- name: Create Release
66+
if: steps.version-check.outputs.version-changed == 'true'
67+
env:
68+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
69+
run: |
70+
gh release create "ui-v${{ steps.version-check.outputs.current-version }}" \
71+
--title "@decocms/ui v${{ steps.version-check.outputs.current-version }}" \
72+
--notes "## Changes
73+
74+
Automated release of the @decocms/ui design system.
75+
76+
### Installation
77+
\`\`\`bash
78+
bun add @decocms/ui react react-dom
79+
\`\`\`
80+
81+
### Docs
82+
https://designsystem.decocms.com/"

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,6 @@ deploy/helm/sandbox-env/charts/
124124
# (nats, opentelemetry-collector) as .tgz under charts/. They stay tracked
125125
# because the chart pins specific versions and offline installs depend on
126126
# them being present.
127+
128+
# Storybook static build
129+
storybook-static

apps/web/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ bun run build:studio
7373
providers; `src/index.web.tsx` is the browser entry that renders it (the Tauri
7474
desktop build has its own entry, `src/index.native.tsx`). Route components load
7575
lazily, TanStack Query manages remote state, and shared UI primitives come from
76-
`@deco/ui`.
76+
`@decocms/ui`.
7777

7878
```text
7979
TanStack Router
@@ -147,7 +147,7 @@ Do not change it to `bun --bun vite dev`: the proxy depends on Node's
147147
isomorphic contracts in explicit `@decocms/shared/*` exports.
148148
- Keep React hooks, contexts, and other browser runtime code in `apps/web`,
149149
including `src/sdk`; do not move them into the shared package.
150-
- Consume design-system primitives from `@deco/ui` and use design tokens rather
150+
- Consume design-system primitives from `@decocms/ui` and use design tokens rather
151151
than raw palette values.
152152
- Route every user-facing string through `useT()`. Add matching English and
153153
Brazilian Portuguese dictionary entries.

apps/web/ct/playwright/index.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
/*
44
* Tailwind v4 auto-scans the project root but EXCLUDES node_modules — and
5-
* @deco/ui (where Switch, Button, Select, etc. live) is a workspace package
5+
* @decocms/ui (where Switch, Button, Select, etc. live) is a workspace package
66
* resolved through node_modules. Without scanning it, sizing utilities like the
77
* Switch's `h-[1.15rem] w-8` are never generated, so icon-only buttons collapse
88
* to 0x0 and Playwright treats them as hidden. Point @source at the real UI

apps/web/ct/playwright/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { beforeMount } from "@playwright/experimental-ct-react/hooks";
22
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
3-
import { TooltipProvider } from "@deco/ui/components/tooltip.tsx";
3+
import { TooltipProvider } from "@decocms/ui/components/tooltip.tsx";
44
import "./index.css";
55

66
// One client per page load; retries off so failed (stubbed) queries settle fast.

apps/web/index.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@import "@deco/ui/styles/global.css";
1+
@import "@decocms/ui/styles/global.css";
22
@import "@daveyplate/better-auth-ui/css";
33

44
@theme {

apps/web/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"@ai-sdk/react": "^3.0.210",
2222
"@better-auth/sso": "1.4.1",
2323
"@daveyplate/better-auth-ui": "^3.2.7",
24-
"@deco/ui": "workspace:*",
24+
"@decocms/ui": "workspace:*",
2525
"@decocms/bindings": "workspace:*",
2626
"@decocms/mcp-utils": "workspace:*",
2727
"@decocms/sandbox": "workspace:*",

apps/web/playwright-ct.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export default defineConfig({
7171
},
7272
// General `@/* -> src/*` alias. MUST come after the stub aliases
7373
// above so Vite (first-match-wins) resolves those first. Matches
74-
// only `@/`-prefixed ids, so `@deco/ui`, `@tanstack/*` etc. are
74+
// only `@/`-prefixed ids, so `@decocms/ui`, `@tanstack/*` etc. are
7575
// untouched.
7676
{ find: "@/", replacement: `${path.join(here, "src")}/` },
7777
],

0 commit comments

Comments
 (0)