@sudajs/cli 0.20.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sudajs/cli",
3
- "version": "0.20.0",
3
+ "version": "0.21.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "suda": "./bin/suda.js"
@@ -33,7 +33,7 @@
33
33
  "react": "^19.2.7",
34
34
  "react-dom": "^19.2.7",
35
35
  "zod": "^3.24.1",
36
- "@sudajs/theme-engine": "6.7.0"
36
+ "@sudajs/theme-engine": "6.9.0"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@tailwindcss/postcss": "^4.3.0",
@@ -1,326 +1,21 @@
1
- # Suda Theme Agent Guide
1
+ # Suda Theme Project Rules
2
2
 
3
3
  This repository is a standalone Vite + React + Tailwind Suda theme generated by
4
- `suda theme init`. Build a complete, publishable theme with theme-specific
5
- sections, realistic templates, scoped styling, assets, and AI metadata.
4
+ `suda theme init`.
6
5
 
7
- ## Required reading
6
+ Install the reusable Suda theme development skill at the repository or
7
+ monorepo root before implementing theme work:
8
8
 
9
- Read this file before every task. Then read the matching focused guide before
10
- editing that area. These guides are part of the contract, not optional
11
- background:
12
-
13
- | Task | Required guide |
14
- | ------------------------------------------------------------------------------------------------------------- | -------------------------------------------- |
15
- | Sections, fields, defaults, menus, icons, AI metadata, or block slots | `docs/agent-guides/component-authoring.md` |
16
- | CMS, posts, starter pages, page data, or locales | `docs/agent-guides/templates-and-locales.md` |
17
- | Header, Footer, PageOutlet, sticky/fixed UI, transparent navigation, carousel, editor CSS, or client behavior | `docs/agent-guides/editor-compatibility.md` |
18
- | Theme contract, layout, design tokens, CSS, assets, or contact forms | `docs/agent-guides/design-and-runtime.md` |
19
-
20
- Read every guide that applies when a change crosses concerns. Follow the
21
- generated types and installed package APIs when they are more specific than an
22
- example. Do not guess contracts from memory.
23
-
24
- ## Non-negotiable rules
25
-
26
- - Keep `renderMode: "ssr"` and export a complete `ThemeModule` from
27
- `src/index.tsx`: `manifest`, `pageConfig`, `layoutConfig`, `defaultLayout`,
28
- `starterPages`, and `cmsTemplates`.
29
- - Keep page sections in `pageConfig` and shared chrome in `layoutConfig`.
30
- Header and Footer render exactly once from the layout, with `PageOutlet`
31
- between them.
32
- - Create theme-specific sections. Do not register `createEngineComponents()`,
33
- `createBaseBlocks()`, or `createContainers()` as the theme's page sections.
34
- Suda adds its generic content blocks separately.
35
- - Keep persisted props JSON-serializable. Never store functions, React nodes,
36
- class instances, media database ids, or absolute local filesystem paths.
37
- - All normal field and prop defaults belong only in component `defaultProps`.
38
- Never invent display defaults inside render code with `||`, `??`, a ternary,
39
- a default function parameter, or a destructuring default.
40
- - Every editor-facing label must use `t(...)` and exist in
41
- `src/locales/en.json`. Public content and `defaultProps` must not use the
42
- editor translation helper.
43
- - Every page and layout component must declare useful `ai.instructions`.
44
- - Top-level page data types must be public keys from `pageConfig.components`,
45
- and every top-level item must have a stable `props.id`.
46
- - Block-slot items use short local kinds such as `"button"`; never author
47
- `__suda_local_block__/...` types or local-block ids.
48
- - Theme assets use `themeAsset("assets/...")` in authored data and
49
- `resolveAsset(...)` when rendering editable media. Never hand-write published
50
- theme asset URLs.
51
- - Keep theme CSS scoped. Do not use global resets or vendor edits that can
52
- damage the Puck editor.
53
- - Do not edit `dist/`; regenerate it through the build.
54
-
55
- ## Project structure
56
-
57
- Keep every page section in its own `.tsx` file. Do not collect multiple section
58
- configs and render implementations in a single `sections.tsx`, `config.tsx`, or
59
- other large module. Use kebab-case names and a small `src/sections/index.ts` to
60
- export configs or assemble the registry.
61
-
62
- ```txt
63
- src/
64
- sections/
65
- hero.tsx
66
- booking.tsx
67
- values.tsx
68
- faq-directory.tsx
69
- review-marquee.tsx
70
- index.ts
71
- ```
72
-
73
- Keep section-specific prop types and tightly coupled helpers with their section.
74
- Extract shared code only when multiple sections genuinely reuse it.
75
-
76
- ## Component fundamentals
77
-
78
- - Name public component keys with concise PascalCase visitor-facing patterns,
79
- such as `HeroImage`, `FeatureCards`, or `TestimonialsCarousel`. Avoid theme
80
- names and filler suffixes such as `Section`, `Component`, `New`, or `Custom`.
81
- - Prefer semantic variant names. Use numbered variants only when the variants
82
- truly share a purpose and no concise name describes the difference.
83
- - Every page section must declare `section.motion`. Use `"reveal"` for ordinary
84
- sections that use the shared viewport entrance animation. Use `"custom"` when
85
- the section owns its own client animation (timeline, carousel, marquee, or
86
- scroll-scrub), and use `"none"` when it must remain static. TypeScript will
87
- report an error when the motion declaration is missing.
88
- - Keep `fields`, TypeScript props, `defaultProps`, and `render` aligned. Every
89
- normal field needs a sensible serializable default.
90
- - Use the most specific field: `url`, `image`, `video`, `media`, `icon`,
91
- `color`, `range`, `spacing`, `posts`, `select`, `radio`, `array`, or `object`.
92
- Do not model structured or semantic values as generic text.
93
- - Use `visibleIf` for synchronous sibling-dependent visibility. Use
94
- `resolveFields` only when `visibleIf` cannot express the behavior.
95
- - Expose a `columns` prop for multi-column grids and lists.
96
- - Use ordinary fields for scalar and structured props. Use `blockSlots` only
97
- for controlled nested items editors and AI may add, remove, or reorder.
98
- - Native Puck slots are reserved for layout/container primitives. Page sections
99
- must not declare native `slot` fields, legacy DropZones, or `zones`.
100
-
101
- Default ownership is strict:
102
-
103
- ```tsx
104
- // Wrong: render invents content.
105
- <div>{val || "defaultValue"}</div>;
106
-
107
- // Correct: defaultProps owns the default.
108
- export const Example: SudaSectionConfig<ExampleProps> = {
109
- section: { category: "features", variant: "example", motion: "reveal" },
110
- fields: { val: { type: "text", label: t("sections.example.fields.val") } },
111
- defaultProps: { val: "defaultValue" },
112
- render: ({ val }) => <div>{val}</div>,
113
- };
9
+ ```bash
10
+ suda theme skill add
114
11
  ```
115
12
 
116
- Conditional rendering is valid when absence intentionally removes optional UI;
117
- it must not substitute placeholder copy, labels, links, icons, or menu items.
118
-
119
- ## Icons
120
-
121
- - Fixed icons are acceptable for interaction and UI-state semantics such as
122
- menu, close, previous/next, expand/collapse, and loading controls.
123
- - Content icons such as feature, service, contact-method, and social-brand
124
- icons are props. Expose `{ type: "icon" }`, type values as `SudaIconName`,
125
- set initial selections in `defaultProps`, and render them with `SudaIcon` from
126
- `@sudajs/theme-engine/icons`. Do not hardcode content icons in `render`.
127
- - Use canonical Lucide names such as `"rocket"` and namespaced Simple Icons
128
- names such as `"simple-icons:github"`. The theme engine supports both; do not
129
- add another icon library unless neither can represent a required icon.
130
-
131
- ## Page data fundamentals
132
-
133
- - Wrap hand-authored page data with `defineSudaPageData(pageConfig, data)` when
134
- practical so TypeScript checks public component keys and block-slot kinds.
135
- - Starter pages live in `src/templates.ts`, use `root: { props: {} }`, contain
136
- realistic content, and include one home page with `isHome: true`.
137
- - Provide exactly the four CMS templates `posts`, `post`, `tags`, and `tag` as
138
- `{ title, data }` entries. Do not invent CMS template variants.
139
- - CMS-only main sections read `getCmsContent(puck?.metadata)`. Ordinary page
140
- post sections use one top-level `posts` field and `getPostResource(...)`.
141
- - Starter page slugs preview at root-like routes such as `/index` and
142
- `/contact-us`; never use `/pages/...` as a preview prefix.
143
-
144
- ## Editor and runtime fundamentals
145
-
146
- - Components return one stable semantic real DOM root when positioning,
147
- selection, spacing, or background matters. Do not rely on a Fragment or
148
- `display: contents` for such roots.
149
- - Derive editor state from `puck?.metadata?.isEditor === true`, expose a stable
150
- theme-root marker, and scope editor fixes below it.
151
- - Puck may place `data-puck-component` and inline `position: relative` on the
152
- component's actual root. Account for that before implementing sticky, fixed,
153
- absolute, overlap, or transparent navigation behavior.
154
- - Do not restore pointer events globally in edit mode. Test interactions in
155
- editor preview and on the public site.
156
- - Browser setup belongs in an optional `clientHooks` export from
157
- `src/client.ts`. Do not create `src/runtime.client.ts(x)`; the CLI owns the
158
- generated runtime.
159
-
160
- ## Design and assets
161
-
162
- - Define one editable design system in `sourceManifest.designSystem`, expose it
163
- at the layout root, resolve it once there, and render components through the
164
- resulting unprefixed CSS variables. Do not add or consume `--suda-*` aliases.
165
- - Set `tokens.layout.contentWidth` in every preset in `src/manifest.ts`. Choose only
166
- `"1024px"`, `"1200px"`, `"1280px"`, or `"1440px"`:
167
-
168
- ```ts
169
- tokens: {
170
- colors: { /* ... */ },
171
- radius: { /* ... */ },
172
- layout: { contentWidth: "1280px" },
173
- }
174
- ```
13
+ The installed `sudacloud-theme` skill contains the section, collection, CMS,
14
+ design system, editor compatibility, localization, and verification guidance.
175
15
 
176
- - Configure the three font slots in every preset's `tokens`. Use font IDs, not
177
- display names:
178
-
179
- ```ts
180
- typography: {
181
- heading: "inter",
182
- body: "noto-sans-sc",
183
- mono: "jetbrains-mono",
184
- },
185
- ```
186
-
187
- Read available IDs from `SUDA_THEME_FONT_FAMILIES`. System fonts such as
188
- `system-sans`, `microsoft-yahei`, and `songti-sc` do not make network requests.
189
-
190
- - Connect the design system field in the layout root's `fields` and
191
- `defaultProps`:
192
-
193
- ```tsx
194
- fields: {
195
- designSystem: designSystemField(t("layout.root.fields.designSystem"), sourceManifest.designSystem),
196
- },
197
- defaultProps: {
198
- designSystem: createThemeDesignDefault(sourceManifest.designSystem),
199
- },
200
- ```
201
-
202
- - Use the resolved CSS variables for theme typography:
203
-
204
- ```css
205
- .my-theme-root {
206
- font-family: var(--font-sans);
207
- }
208
-
209
- .my-theme-root h1,
210
- .my-theme-root h2,
211
- .my-theme-root h3,
212
- .my-theme-root h4,
213
- .my-theme-root h5,
214
- .my-theme-root h6 {
215
- font-family: var(--font-heading);
216
- }
217
-
218
- .my-theme-root code,
219
- .my-theme-root pre {
220
- font-family: var(--font-mono);
221
- }
222
- ```
223
-
224
- - In the layout root, resolve the selected preset and apply its CSS variables
225
- to the element that wraps `children`. Use this exact pattern:
226
-
227
- ```tsx
228
- render: ({ children, designSystem }) => {
229
- const tokens = resolveThemeDesignTokens(sourceManifest.designSystem, designSystem);
230
- return (
231
- <div
232
- className="my-theme-root"
233
- style={createThemeDesignCssVariables(tokens)}
234
- >
235
- {children}
236
- </div>
237
- );
238
- },
239
- ```
240
-
241
- - Do not set `max-width` on the layout root or `PageOutlet`; doing so prevents
242
- full-width sections. Apply `--content-max-width` only to inner content
243
- containers. Wrap Header and Footer contents in that same container when they
244
- must align with page sections.
245
-
246
- - Every page section root must include `w-full`. Put the section background,
247
- border, and full-bleed media on this root. Do not set `max-width` on it.
248
- - Put normal section content inside one shared container class and define that
249
- class once in `src/styles.css`:
250
-
251
- ```css
252
- .my-theme-container {
253
- width: min(var(--content-max-width), 100%);
254
- margin-inline: auto;
255
- }
256
- ```
257
-
258
- - Use the same container inside full-width Hero and band sections when their
259
- text, buttons, cards, or navigation must align with ordinary sections. Omit
260
- the inner container only when the section content itself must be edge to
261
- edge. Do not repeat `1024px`, `1200px`, `1280px`, or `1440px` in section CSS.
262
- - `--background` / `--foreground`: default page surface and readable default
263
- content. `--primary` / `--primary-foreground`: main brand and action surface
264
- plus readable content on it. `--secondary` / `--secondary-foreground`:
265
- supporting surface plus its content; it is not assumed light or dark.
266
- - `--accent` / `--accent-foreground`: high-attention emphasis, selection, or
267
- decorative surface plus its content, not a default CTA substitute.
268
- `--muted` / `--muted-foreground`: subdued surface and secondary text/icons.
269
- Always pair a chosen surface with its corresponding foreground token.
270
- - `--radius` is the generic fallback; use `--radius-card`,
271
- `--radius-button`, and `--radius-input` for cards, command buttons, and form
272
- controls. Tailwind token mappings use `@theme inline`; hand-written CSS may
273
- consume these variables directly.
274
- - The theme decides which semantic surface each of its components uses. Do not
275
- alter built-in section styling to accommodate a single theme palette, and do
276
- not hardcode replacement colors in individual sections.
277
- - Keep typography, spacing, containers, buttons, cards, forms, and media frames
278
- consistent across ordinary sections, CMS sections, and starter pages.
279
- - Theme-local assets live under top-level `assets/`. Required preview images are
280
- `assets/preview/desktop.png`, `tablet.png`, and `mobile.png`.
281
- - Contact sections render host-provided `metadata.contactForm`; the platform
282
- owns configuration, validation, submission, notifications, and limits.
283
-
284
- ## Workflow
285
-
286
- Before editing:
287
-
288
- 1. Read the required focused guide(s).
289
- 2. Inspect the existing source, generated types, and established theme helpers.
290
- 3. Identify every affected contract: fields/defaults/render, locales, page data,
291
- assets, editor behavior, and templates.
292
-
293
- When adding or changing a section:
294
-
295
- 1. Define serializable props in its dedicated `.tsx` file.
296
- 2. Add `section` metadata with `category`, semantic `variant`, and an explicit
297
- `motion` mode (`reveal`, `custom`, or `none`).
298
- 3. Add `label`, useful `ai.instructions`, typed `fields`, optional
299
- `blockSlots`, `defaultProps`, and `render`.
300
- 4. Add all editor label keys to `src/locales/en.json`.
301
- 5. Register it in `pageConfig` and the appropriate translated category.
302
- 6. Add realistic usage to starter pages or CMS templates where appropriate.
303
- 7. Verify public rendering plus editor desktop, tablet, and mobile behavior.
304
-
305
- Before handoff:
306
-
307
- ```bash
308
- pnpm lint
309
- pnpm typecheck
310
- pnpm build
311
- pnpm validate
312
- suda theme check
313
- suda theme visual-check
314
- ```
16
+ ## Always required
315
17
 
316
- Run `suda theme visual-check` after developing or substantially changing a
317
- theme. It renders every page component declared by the theme's
318
- `pageConfig.components` with each declared design preset at desktop, tablet,
319
- and mobile sizes, writes screenshots and `report.json` to
320
- `.suda-build/visual-check/`, and fails on token contrast, semantic surface,
321
- or page-overflow errors. Fixed-header overlap is reported as a layout warning;
322
- solve it in the theme layout. Platform built-in sections are covered by
323
- theme-engine tests, not repeated for every theme. Run `suda theme capture` when
324
- publish-preview visuals change.
325
- Do not use removed skip flags or bypass build, validation, AI metadata, locale,
326
- visual, or screenshot checks.
18
+ - Keep `renderMode: "ssr"` and export the complete `ThemeModule` contract.
19
+ - Keep persisted props JSON-serializable and put normal field defaults only in
20
+ component `defaultProps`.
21
+ - Do not edit generated files in `dist/`; regenerate them through the build.
@@ -1,3 +1,5 @@
1
1
  # Claude Code
2
2
 
3
- Read `AGENTS.md` first. It is the canonical guide for this Suda theme project.
3
+ Read `AGENTS.md` first. Then use the installed `sudacloud-theme` skill for
4
+ theme development guidance. If it is missing, run `suda theme skill add` from
5
+ the repository or monorepo root.
@@ -8,6 +8,19 @@ A standalone Vite + React + Tailwind Suda theme scaffolded with `suda theme init
8
8
  pnpm install
9
9
  ```
10
10
 
11
+ ## Theme development skill
12
+
13
+ Install the shared Suda theme development guidance once at the repository or
14
+ monorepo root:
15
+
16
+ ```bash
17
+ suda theme skill add
18
+ ```
19
+
20
+ The generated `AGENTS.md` keeps only project rules that must always apply. The
21
+ installed `sudacloud-theme` skill provides the detailed section, collection,
22
+ CMS, design system, editor, and localization guidance.
23
+
11
24
  ## Develop
12
25
 
13
26
  ```bash
@@ -65,6 +65,9 @@ Use the most specific supported field:
65
65
  - `select`, `radio`: stable serializable choices.
66
66
  - `object`, `array`: grouped and repeatable structured values.
67
67
  - `posts`: one dynamic post query on an ordinary page section.
68
+ - `collection`: a project-scoped dynamic collection binding with semantic role
69
+ mappings. The current contract resolves a published list and `limit`; do not
70
+ invent manual selection, filter/sort, or detail-route fields in PageData.
68
71
 
69
72
  Rules:
70
73
 
@@ -126,6 +129,38 @@ defaultProps: {
126
129
  },
127
130
  ```
128
131
 
132
+ ## Collection-backed sections
133
+
134
+ The theme engine includes three platform-owned section families:
135
+
136
+ - `SudaCollectionGrid` for multi-column cards;
137
+ - `SudaCollectionList` for compact directories;
138
+ - `SudaCollectionSpotlight` for one prominent entry and optional supporting entries.
139
+
140
+ When a theme owns a custom collection layout, declare semantic roles instead of
141
+ assuming every Collection has fields named `title`, `image`, or `featured`:
142
+
143
+ ```ts
144
+ source: {
145
+ type: "collection",
146
+ roles: {
147
+ title: { types: ["text", "textarea"], required: true },
148
+ description: { types: ["text", "textarea", "richText"] },
149
+ image: { types: ["media"] },
150
+ href: { types: ["url"] },
151
+ },
152
+ defaultLimit: 6,
153
+ maxLimit: 12,
154
+ }
155
+ ```
156
+
157
+ Read resolved entries with `getCollectionResource(props.puck?.metadata, {
158
+ componentId: props.id, fieldKey: "source" })` from
159
+ `@sudajs/theme-engine/runtime`. The host runtime supplies published entries for
160
+ the current locale and resolves media URLs. A theme must not access Prisma or
161
+ filter project data in the browser. The platform documentation describes the
162
+ complete contract and planned query/detail extensions.
163
+
129
164
  ## Navigation and footer menus
130
165
 
131
166
  Navigation and footer menus are typed arrays. Do not use a legacy menu field,
@@ -0,0 +1,63 @@
1
+ ---
2
+ name: sudacloud-theme
3
+ description: Use when building, editing, reviewing, validating, or publishing a SudaCloud Vite theme, including sections, collection bindings, CMS templates, design tokens, Puck editor compatibility, starter pages, and theme localization.
4
+ ---
5
+
6
+ # SudaCloud Theme Development
7
+
8
+ Use this skill for a standalone Suda theme created by `suda theme init`.
9
+ It supplies the reusable development contract that should be installed once at
10
+ the repository or monorepo root with `suda theme skill add`.
11
+
12
+ ## Read first
13
+
14
+ Read the references that match the task before editing. Read more than one when
15
+ a change crosses concerns.
16
+
17
+ | Task | Required reference |
18
+ | ---------------------------------------------------------------------------------------- | ------------------------------------- |
19
+ | Sections, fields, defaults, menus, icons, AI metadata, block slots, or collections | `references/component-authoring.md` |
20
+ | CMS templates, posts, starter pages, PageData, or locales | `references/templates-and-locales.md` |
21
+ | Header, Footer, PageOutlet, sticky or fixed UI, carousel, editor CSS, or client behavior | `references/editor-compatibility.md` |
22
+ | Theme contract, manifest, design tokens, CSS, assets, contact forms, or runtime metadata | `references/design-and-runtime.md` |
23
+
24
+ Use generated TypeScript types and installed package APIs as the source of truth
25
+ when they are more specific than these references. Do not guess contracts.
26
+
27
+ ## Non-negotiable requirements
28
+
29
+ - Keep `renderMode: "ssr"` and export a complete `ThemeModule` with `manifest`,
30
+ `pageConfig`, `layoutConfig`, `defaultLayout`, `starterPages`, and
31
+ `cmsTemplates`.
32
+ - Keep page sections in `pageConfig`; render shared chrome once from the layout
33
+ with `PageOutlet` between Header and Footer.
34
+ - Persist only JSON-serializable props. Use `defaultProps` as the sole owner of
35
+ normal field defaults; render code must not invent fallback content.
36
+ - Every editor-facing label uses `t(...)` and has an `en.json` entry. Public
37
+ content and `defaultProps` do not use the editor translation helper.
38
+ - Authored PageData uses public component keys with stable top-level `props.id`.
39
+ Block slots use their short local kinds, never internal generated types.
40
+ - Resolve theme assets with `themeAsset(...)` in authored data and
41
+ `resolveAsset(...)` for editable rendered media.
42
+ - Keep CSS scoped to the theme root and preserve Puck editor compatibility.
43
+ - Do not edit `dist/`; regenerate it with the theme build.
44
+
45
+ ## Collection sections
46
+
47
+ Prefer the platform-owned `SudaCollectionGrid`, `SudaCollectionList`, and
48
+ `SudaCollectionSpotlight` for standard collection displays. For a custom
49
+ collection layout, declare semantic collection roles and read the published
50
+ project-scoped resource through `getCollectionResource(...)`; do not query
51
+ database data or implement client-side project filtering.
52
+
53
+ ## Verification
54
+
55
+ Run the relevant theme checks before publishing:
56
+
57
+ ```bash
58
+ pnpm lint:fix
59
+ pnpm typecheck
60
+ suda theme visual-check
61
+ suda theme capture
62
+ pnpm build
63
+ ```