@sudajs/cli 0.5.5 → 0.6.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.5.5",
3
+ "version": "0.6.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "suda": "./bin/suda.js"
@@ -17,7 +17,8 @@
17
17
  },
18
18
  "files": [
19
19
  "dist",
20
- "bin"
20
+ "bin",
21
+ "templates"
21
22
  ],
22
23
  "publishConfig": {
23
24
  "access": "public"
@@ -31,15 +32,20 @@
31
32
  "react": "^19.0.0",
32
33
  "react-dom": "^19.0.0",
33
34
  "zod": "^3.24.1",
34
- "@sudajs/theme-engine": "1.6.1"
35
+ "@sudajs/theme-engine": "2.0.0"
35
36
  },
36
37
  "devDependencies": {
38
+ "@tailwindcss/postcss": "^4.3.0",
37
39
  "@types/node": "^22.10.2",
38
40
  "@types/react": "^19.0.2",
39
41
  "@types/react-dom": "^19.0.2",
42
+ "@vitejs/plugin-react": "^5.1.2",
40
43
  "eslint": "^9.17.0",
44
+ "postcss": "^8.5.15",
45
+ "tailwindcss": "^4.3.0",
41
46
  "tsx": "^4.22.3",
42
47
  "typescript": "^5.7.2",
48
+ "vite": "^7.3.3",
43
49
  "vitest": "^3.2.4",
44
50
  "@suda/build-config": "0.0.0",
45
51
  "@suda/eslint-config": "0.0.0",
@@ -0,0 +1,30 @@
1
+ # Suda Theme Agent Guide
2
+
3
+ This directory is a standalone Vite + React + Tailwind Suda theme generated by `suda theme init`.
4
+
5
+ ## Contract
6
+
7
+ - Keep `renderMode: "ssr"` in `src/manifest.ts`.
8
+ - Keep source entries at `src/index.tsx`, `src/runtime.client.ts`, and `src/styles.css`.
9
+ - Do not edit generated files under `dist/`, root `manifest.json`, or root `styles.css`; run `pnpm build` to regenerate them.
10
+ - React, React DOM, Puck, and `@sudajs/theme-engine` are host-provided peers. Do not bundle private copies into the theme runtime.
11
+
12
+ ## Styling
13
+
14
+ - Tailwind v4 starts in `src/styles.css` with `@import "tailwindcss";` and `@source "./**/*.{ts,tsx}";`.
15
+ - Customize `vite.config.ts`, `postcss.config.mjs`, and `src/styles.css` as needed.
16
+
17
+ ## Commands
18
+
19
+ ```bash
20
+ pnpm install
21
+ pnpm typecheck
22
+ pnpm dev # Vite-powered local preview
23
+ pnpm build # Vite build + Suda artifact finalize + AI metadata check
24
+ pnpm validate
25
+ suda theme check
26
+ ```
27
+
28
+ ## AI metadata
29
+
30
+ Every component and layout component should declare useful `ai.instructions`. Missing component-level instructions fail `suda theme check` and block publish.
@@ -0,0 +1,3 @@
1
+ # Claude Code
2
+
3
+ Read `AGENTS.md` first. It is the canonical guide for this Suda theme project.
@@ -0,0 +1,28 @@
1
+ # **SUDA_THEME_KEY**
2
+
3
+ A standalone Vite + React + Tailwind Suda theme scaffolded with `suda theme init`.
4
+
5
+ ## Setup
6
+
7
+ ```bash
8
+ pnpm install
9
+ ```
10
+
11
+ ## Develop
12
+
13
+ ```bash
14
+ pnpm dev
15
+ pnpm typecheck
16
+ pnpm build
17
+ pnpm validate
18
+ ```
19
+
20
+ `pnpm dev` starts the Vite-powered preview. `pnpm build` produces the Suda artifact contract: `dist/index.js`, `dist/runtime.client.js`, root `manifest.json`, and root `styles.css`.
21
+
22
+ ## Publish
23
+
24
+ ```bash
25
+ pnpm build
26
+ suda theme screenshot # optional
27
+ suda theme publish
28
+ ```
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@suda-themes/__SUDA_THEME_KEY__",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "packageManager": "pnpm@11.6.0",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "scripts": {
10
+ "build": "suda theme build --theme-root .",
11
+ "dev": "suda theme dev --theme-root .",
12
+ "finalize": "suda theme finalize --theme-root .",
13
+ "typecheck": "tsc -p tsconfig.json --noEmit",
14
+ "validate": "suda theme validate --theme-root ."
15
+ },
16
+ "devDependencies": {
17
+ "@tailwindcss/postcss": "^4.3.0",
18
+ "@puckeditor/core": "^0.21.2",
19
+ "@sudajs/cli": "*",
20
+ "@sudajs/theme-engine": "*",
21
+ "@types/node": "^22.0.0",
22
+ "@types/react": "^19.0.0",
23
+ "@types/react-dom": "^19.0.0",
24
+ "@vitejs/plugin-react": "^5.1.2",
25
+ "postcss": "^8.5.15",
26
+ "react": "^19.0.0",
27
+ "react-dom": "^19.0.0",
28
+ "tailwindcss": "^4.3.0",
29
+ "typescript": "^5.6.0",
30
+ "vite": "^7.3.3"
31
+ },
32
+ "peerDependencies": {
33
+ "@puckeditor/core": "^0.21.2",
34
+ "@sudajs/theme-engine": "*",
35
+ "react": "^19.0.0",
36
+ "react-dom": "^19.0.0"
37
+ }
38
+ }
@@ -0,0 +1,8 @@
1
+ # This is NOT a monorepo marker — it only exists because pnpm 11 moved
2
+ # project-level settings such as `allowBuilds` out of package.json. Without
3
+ # a `packages:` field this workspace contains just the current package, so
4
+ # the project remains a standalone single-package theme.
5
+ # See https://pnpm.io/settings and https://pnpm.io/pnpm-workspace_yaml.
6
+ allowBuilds:
7
+ '@tailwindcss/oxide': true
8
+ esbuild: true
@@ -0,0 +1,7 @@
1
+ const config = {
2
+ plugins: {
3
+ "@tailwindcss/postcss": {},
4
+ },
5
+ };
6
+
7
+ export default config;
@@ -0,0 +1,22 @@
1
+ import type { Config, Data } from "@puckeditor/core";
2
+
3
+ import { LAYOUT_COMPONENTS, rootConfig } from "./layout.js";
4
+ import { SECTION_COMPONENTS } from "./sections.js";
5
+
6
+ export const pageConfig: Config = {
7
+ components: SECTION_COMPONENTS,
8
+ };
9
+
10
+ export const layoutConfig: Config = {
11
+ root: rootConfig,
12
+ components: LAYOUT_COMPONENTS,
13
+ };
14
+
15
+ export const defaultLayout: Data = {
16
+ root: { props: { siteName: "__SUDA_THEME_KEY__" } },
17
+ content: [
18
+ { type: "Header", props: { id: "Header-1", siteName: "__SUDA_THEME_KEY__" } },
19
+ { type: "PageOutlet", props: { id: "PageOutlet-1" } },
20
+ { type: "Footer", props: { id: "Footer-1", text: "© __SUDA_THEME_KEY__" } },
21
+ ],
22
+ };
@@ -0,0 +1,23 @@
1
+ import type { ThemeManifest, ThemeModule } from "@sudajs/theme-engine";
2
+
3
+ import pkg from "../package.json" with { type: "json" };
4
+
5
+ import { defaultLayout, layoutConfig, pageConfig } from "./config.js";
6
+ import { sourceManifest } from "./manifest.js";
7
+ import { starterPages } from "./templates.js";
8
+
9
+ // Single source of truth: theme version comes from package.json#version,
10
+ // merged into the source-side manifest. esbuild inlines the JSON import at
11
+ // build time, so the published `dist/index.js` is fully self-contained.
12
+ export const manifest: ThemeManifest = { ...sourceManifest, version: pkg.version };
13
+
14
+ const theme: ThemeModule = {
15
+ manifest,
16
+ pageConfig,
17
+ layoutConfig,
18
+ defaultLayout,
19
+ starterPages,
20
+ };
21
+
22
+ export default theme;
23
+ export { pageConfig, layoutConfig, defaultLayout, starterPages };
@@ -0,0 +1,76 @@
1
+ import type { Config } from "@puckeditor/core";
2
+ import type { SudaComponentConfig } from "@sudajs/theme-engine";
3
+ import { getIcpRecord, getPageSlot, getWhiteLabel } from "@sudajs/theme-engine/runtime";
4
+ import type { ReactElement, ReactNode } from "react";
5
+
6
+ type PuckExtras = { puck?: { metadata?: Record<string, unknown> } };
7
+
8
+ export const rootConfig: NonNullable<Config["root"]> = {
9
+ fields: {
10
+ siteName: { type: "text", label: "Site name" },
11
+ },
12
+ defaultProps: { siteName: "__SUDA_THEME_KEY__" },
13
+ render: ({ children, siteName }: { children?: ReactNode; siteName?: string }) => (
14
+ <div className="__SUDA_THEME_KEY__-root" data-site-name={siteName}>{children}</div>
15
+ ),
16
+ };
17
+
18
+ export const Header: SudaComponentConfig = {
19
+ label: "Header",
20
+ ai: {
21
+ instructions:
22
+ "Site-wide header rendered at the top of every page. " +
23
+ "Place once at the top of the layout (not inside page content). " +
24
+ "Used for branding and primary navigation, not for promotional content.",
25
+ },
26
+ fields: { siteName: { type: "text", label: "Site name" } },
27
+ defaultProps: { siteName: "__SUDA_THEME_KEY__" },
28
+ render: ({ siteName }) => <header className="__SUDA_THEME_KEY__-header">{siteName}</header>,
29
+ };
30
+
31
+ export const PageOutlet: SudaComponentConfig = {
32
+ label: "Page outlet",
33
+ ai: {
34
+ exclude: true,
35
+ instructions:
36
+ "Structural slot where each page's content is injected. " +
37
+ "Managed by the layout, never created or placed by AI.",
38
+ },
39
+ fields: {},
40
+ defaultProps: {},
41
+ render: (props: PuckExtras): ReactElement => <>{getPageSlot(props.puck?.metadata)}</>,
42
+ };
43
+
44
+ export const Footer: SudaComponentConfig = {
45
+ label: "Footer",
46
+ ai: {
47
+ instructions:
48
+ "Site-wide footer rendered at the bottom of every page. " +
49
+ "Place once at the end of the layout. " +
50
+ "Used for legal text, copyright, and secondary links — not for primary CTAs.",
51
+ },
52
+ fields: { text: { type: "text", label: "Text" } },
53
+ defaultProps: { text: "© __SUDA_THEME_KEY__" },
54
+ render: ({ text, puck }: { text?: string } & PuckExtras) => {
55
+ const whiteLabel = getWhiteLabel(puck?.metadata);
56
+ const icp = getIcpRecord(puck?.metadata);
57
+ return (
58
+ <footer className="__SUDA_THEME_KEY__-footer">
59
+ <span>{text}</span>
60
+ {whiteLabel?.visible ? (
61
+ <a href={whiteLabel.href} target="_blank" rel="noreferrer">
62
+ {whiteLabel.logo ? <img src={whiteLabel.logo} alt="" /> : null}
63
+ <span dangerouslySetInnerHTML={{ __html: whiteLabel.text }} />
64
+ </a>
65
+ ) : null}
66
+ {icp ? (
67
+ <a href={icp.href} target="_blank" rel="noreferrer">
68
+ {icp.text}
69
+ </a>
70
+ ) : null}
71
+ </footer>
72
+ );
73
+ },
74
+ };
75
+
76
+ export const LAYOUT_COMPONENTS = { Header, PageOutlet, Footer };
@@ -0,0 +1,18 @@
1
+ import type { ThemeSourceManifest } from "@sudajs/theme-engine";
2
+
3
+ // Source-side manifest — version is intentionally omitted because the
4
+ // authoritative theme version lives in package.json. `src/index.tsx` reads
5
+ // package.json#version and merges it into the published ThemeManifest, so a
6
+ // single `pnpm changeset version` (or `npm version`) bumps everything.
7
+ export const sourceManifest: ThemeSourceManifest = {
8
+ key: "__SUDA_THEME_KEY__",
9
+ name: "__SUDA_THEME_KEY__",
10
+ categories: ["other"],
11
+ minEngineVersion: "0.0.0",
12
+ entry: "dist/index.js",
13
+ clientEntry: "dist/runtime.client.js",
14
+ // Required. SudaCloud currently hosts SSR themes only; CSR/Hybrid postures
15
+ // are on the roadmap. Authoring `renderMode` is the contract a theme uses
16
+ // to declare which posture it expects from the host.
17
+ renderMode: "ssr",
18
+ };
@@ -0,0 +1,5 @@
1
+ "use client";
2
+
3
+ import theme from "./index.js";
4
+
5
+ export default theme;
@@ -0,0 +1,161 @@
1
+ import type { SudaComponentConfig } from "@sudajs/theme-engine";
2
+
3
+ type FeatureItem = { title?: string; description?: string };
4
+ type HeroProps = {
5
+ eyebrow?: string;
6
+ title?: string;
7
+ description?: string;
8
+ primaryLabel?: string;
9
+ primaryHref?: string;
10
+ };
11
+ type FeatureGridProps = {
12
+ title?: string;
13
+ description?: string;
14
+ features?: FeatureItem[];
15
+ };
16
+ type TestimonialProps = {
17
+ quote?: string;
18
+ author?: string;
19
+ role?: string;
20
+ };
21
+ type CallToActionProps = {
22
+ title?: string;
23
+ description?: string;
24
+ buttonLabel?: string;
25
+ buttonHref?: string;
26
+ };
27
+
28
+ export const Hero: SudaComponentConfig = {
29
+ label: "Hero",
30
+ ai: {
31
+ instructions:
32
+ "Primary page introduction used to communicate the main value proposition. " +
33
+ "Place near the beginning of landing, product, service, or campaign pages. " +
34
+ "Include one concise headline, supporting copy, and one primary call to action. " +
35
+ "Use at most once per page. Do not use for ordinary section headings or article content.",
36
+ },
37
+ fields: {
38
+ eyebrow: { type: "text", label: "Eyebrow" },
39
+ title: { type: "text", label: "Title" },
40
+ description: { type: "textarea", label: "Description" },
41
+ primaryLabel: { type: "text", label: "Primary button label" },
42
+ primaryHref: { type: "text", label: "Primary button link" },
43
+ },
44
+ defaultProps: {
45
+ eyebrow: "New theme",
46
+ title: "Build with SudaCloud",
47
+ description: "Edit this starter section in the visual editor.",
48
+ primaryLabel: "Get started",
49
+ primaryHref: "#contact",
50
+ },
51
+ render: ({ eyebrow, title, description, primaryLabel, primaryHref }: HeroProps) => (
52
+ <section className="__SUDA_THEME_KEY__-section __SUDA_THEME_KEY__-hero">
53
+ <p className="__SUDA_THEME_KEY__-eyebrow">{eyebrow}</p>
54
+ <h1>{title}</h1>
55
+ <p>{description}</p>
56
+ <a className="__SUDA_THEME_KEY__-button" href={primaryHref}>{primaryLabel}</a>
57
+ </section>
58
+ ),
59
+ };
60
+
61
+ export const FeatureGrid: SudaComponentConfig = {
62
+ label: "Feature grid",
63
+ ai: {
64
+ instructions:
65
+ "Section that lists 3–6 short feature or benefit cards explaining what the product or service offers. " +
66
+ "Place after the hero / introduction and before the final call-to-action. " +
67
+ "Use when the page needs to communicate multiple distinct value points; do not use for testimonials, FAQs, or step-by-step processes.",
68
+ },
69
+ fields: {
70
+ title: { type: "text", label: "Title" },
71
+ description: { type: "textarea", label: "Description" },
72
+ features: {
73
+ type: "array",
74
+ label: "Features",
75
+ arrayFields: {
76
+ title: { type: "text", label: "Title" },
77
+ description: { type: "textarea", label: "Description" },
78
+ },
79
+ },
80
+ },
81
+ defaultProps: {
82
+ title: "Everything you need to launch",
83
+ description: "Use this section to explain the core value of the project.",
84
+ features: [
85
+ { title: "Fast setup", description: "Start from a clean theme contract." },
86
+ { title: "Visual editing", description: "Expose content fields through Puck." },
87
+ { title: "Publish ready", description: "Build and publish with the Suda CLI." },
88
+ ],
89
+ },
90
+ render: ({ title, description, features = [] }: FeatureGridProps) => (
91
+ <section className="__SUDA_THEME_KEY__-section">
92
+ <h2>{title}</h2>
93
+ <p>{description}</p>
94
+ <div className="__SUDA_THEME_KEY__-grid">
95
+ {features.map((feature: FeatureItem, index: number) => (
96
+ <article className="__SUDA_THEME_KEY__-card" key={index}>
97
+ <h3>{feature.title}</h3>
98
+ <p>{feature.description}</p>
99
+ </article>
100
+ ))}
101
+ </div>
102
+ </section>
103
+ ),
104
+ };
105
+
106
+ export const Testimonial: SudaComponentConfig = {
107
+ label: "Testimonial",
108
+ ai: {
109
+ instructions:
110
+ "Section that quotes a single customer or expert as social proof. " +
111
+ "Place mid-page after a feature or value section, or near the end before the final CTA. " +
112
+ "Do not invent quotes, names, or roles; only use content the user provides.",
113
+ },
114
+ fields: {
115
+ quote: { type: "textarea", label: "Quote" },
116
+ author: { type: "text", label: "Author" },
117
+ role: { type: "text", label: "Role" },
118
+ },
119
+ defaultProps: {
120
+ quote: "SudaCloud gives our team a practical editing workflow without giving up theme control.",
121
+ author: "Alex Chen",
122
+ role: "Founder",
123
+ },
124
+ render: ({ quote, author, role }: TestimonialProps) => (
125
+ <section className="__SUDA_THEME_KEY__-section __SUDA_THEME_KEY__-quote">
126
+ <blockquote>{quote}</blockquote>
127
+ <p>{author} · {role}</p>
128
+ </section>
129
+ ),
130
+ };
131
+
132
+ export const CallToAction: SudaComponentConfig = {
133
+ label: "Call to action",
134
+ ai: {
135
+ instructions:
136
+ "Closing conversion section that invites the visitor to take a specific action (sign up, contact, buy, etc.). " +
137
+ "Place near the end of the page, after supporting content. " +
138
+ "Use at most once per page. Do not use as the page's first introduction — the Hero component fills that role.",
139
+ },
140
+ fields: {
141
+ title: { type: "text", label: "Title" },
142
+ description: { type: "textarea", label: "Description" },
143
+ buttonLabel: { type: "text", label: "Button label" },
144
+ buttonHref: { type: "text", label: "Button link" },
145
+ },
146
+ defaultProps: {
147
+ title: "Ready to build your next page?",
148
+ description: "Use this section as the final conversion block.",
149
+ buttonLabel: "Contact us",
150
+ buttonHref: "#contact",
151
+ },
152
+ render: ({ title, description, buttonLabel, buttonHref }: CallToActionProps) => (
153
+ <section className="__SUDA_THEME_KEY__-section __SUDA_THEME_KEY__-cta" id="contact">
154
+ <h2>{title}</h2>
155
+ <p>{description}</p>
156
+ <a className="__SUDA_THEME_KEY__-button" href={buttonHref}>{buttonLabel}</a>
157
+ </section>
158
+ ),
159
+ };
160
+
161
+ export const SECTION_COMPONENTS = { Hero, FeatureGrid, Testimonial, CallToAction };
@@ -0,0 +1,102 @@
1
+ @import "tailwindcss";
2
+ @source "./**/*.{ts,tsx}";
3
+
4
+ .__SUDA_THEME_KEY__-root {
5
+ font-family: Inter, ui-sans-serif, system-ui, sans-serif;
6
+ color: #111827;
7
+ background: #ffffff;
8
+ }
9
+ .__SUDA_THEME_KEY__-header,
10
+ .__SUDA_THEME_KEY__-footer {
11
+ padding: 20px clamp(20px, 5vw, 64px);
12
+ border-bottom: 1px solid #e5e7eb;
13
+ }
14
+ .__SUDA_THEME_KEY__-footer {
15
+ display: flex;
16
+ flex-wrap: wrap;
17
+ align-items: center;
18
+ gap: 12px 20px;
19
+ border-top: 1px solid #e5e7eb;
20
+ border-bottom: 0;
21
+ color: #6b7280;
22
+ }
23
+ .__SUDA_THEME_KEY__-footer a {
24
+ display: inline-flex;
25
+ align-items: center;
26
+ gap: 6px;
27
+ color: inherit;
28
+ text-decoration: none;
29
+ }
30
+ .__SUDA_THEME_KEY__-footer img {
31
+ height: 16px;
32
+ width: auto;
33
+ }
34
+ .__SUDA_THEME_KEY__-section {
35
+ padding: 64px clamp(20px, 5vw, 64px);
36
+ }
37
+ .__SUDA_THEME_KEY__-hero {
38
+ background: #f8fafc;
39
+ }
40
+ .__SUDA_THEME_KEY__-eyebrow {
41
+ text-transform: uppercase;
42
+ letter-spacing: 0.08em;
43
+ font-size: 12px;
44
+ color: #2563eb;
45
+ font-weight: 700;
46
+ }
47
+ .__SUDA_THEME_KEY__-section h1 {
48
+ max-width: 780px;
49
+ font-size: clamp(40px, 7vw, 72px);
50
+ line-height: 0.95;
51
+ margin: 0 0 20px;
52
+ }
53
+ .__SUDA_THEME_KEY__-section h2 {
54
+ max-width: 720px;
55
+ font-size: 36px;
56
+ line-height: 1.05;
57
+ margin: 0 0 16px;
58
+ }
59
+ .__SUDA_THEME_KEY__-section p {
60
+ max-width: 680px;
61
+ line-height: 1.7;
62
+ color: #4b5563;
63
+ }
64
+ .__SUDA_THEME_KEY__-button {
65
+ display: inline-flex;
66
+ align-items: center;
67
+ min-height: 42px;
68
+ padding: 0 18px;
69
+ border-radius: 8px;
70
+ background: #111827;
71
+ color: #ffffff;
72
+ text-decoration: none;
73
+ font-weight: 700;
74
+ }
75
+ .__SUDA_THEME_KEY__-grid {
76
+ display: grid;
77
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
78
+ gap: 16px;
79
+ margin-top: 28px;
80
+ }
81
+ .__SUDA_THEME_KEY__-card {
82
+ border: 1px solid #e5e7eb;
83
+ border-radius: 8px;
84
+ padding: 20px;
85
+ }
86
+ .__SUDA_THEME_KEY__-quote blockquote {
87
+ max-width: 780px;
88
+ font-size: 28px;
89
+ line-height: 1.25;
90
+ margin: 0 0 16px;
91
+ }
92
+ .__SUDA_THEME_KEY__-cta {
93
+ background: #111827;
94
+ color: #ffffff;
95
+ }
96
+ .__SUDA_THEME_KEY__-cta p {
97
+ color: #d1d5db;
98
+ }
99
+ .__SUDA_THEME_KEY__-cta .__SUDA_THEME_KEY__-button {
100
+ background: #ffffff;
101
+ color: #111827;
102
+ }
@@ -0,0 +1,107 @@
1
+ import type { ThemeStarterPage } from "@sudajs/theme-engine";
2
+
3
+ export const starterPages: ThemeStarterPage[] = [
4
+ {
5
+ slug: "home",
6
+ title: "Home",
7
+ isHome: true,
8
+ data: {
9
+ root: { props: {} },
10
+ content: [
11
+ {
12
+ type: "Hero",
13
+ props: {
14
+ id: "Hero-1",
15
+ eyebrow: "Starter page",
16
+ title: "Welcome to __SUDA_THEME_KEY__",
17
+ description: "This page was generated by suda theme init.",
18
+ primaryLabel: "Explore features",
19
+ primaryHref: "#features",
20
+ },
21
+ },
22
+ {
23
+ type: "FeatureGrid",
24
+ props: {
25
+ id: "FeatureGrid-1",
26
+ title: "Designed for editable sites",
27
+ description: "Starter sections show agents and editors how this theme is structured.",
28
+ features: [
29
+ { title: "Typed fields", description: "Each section exposes a clear field schema." },
30
+ { title: "Starter pages", description: "Templates show realistic section composition." },
31
+ { title: "CLI workflow", description: "Build, validate, preview, and publish from one tool." },
32
+ ],
33
+ },
34
+ },
35
+ {
36
+ type: "CallToAction",
37
+ props: {
38
+ id: "CallToAction-1",
39
+ title: "Launch your first page",
40
+ description: "Customize this starter template or let an agent generate a new draft.",
41
+ buttonLabel: "Get in touch",
42
+ buttonHref: "/contact",
43
+ },
44
+ },
45
+ ],
46
+ },
47
+ },
48
+ {
49
+ slug: "about",
50
+ title: "About",
51
+ data: {
52
+ root: { props: {} },
53
+ content: [
54
+ {
55
+ type: "Hero",
56
+ props: {
57
+ id: "Hero-About",
58
+ eyebrow: "About",
59
+ title: "A clean starting point for your story",
60
+ description: "Use this page to introduce the project, audience, and promise.",
61
+ primaryLabel: "Contact us",
62
+ primaryHref: "/contact",
63
+ },
64
+ },
65
+ {
66
+ type: "Testimonial",
67
+ props: {
68
+ id: "Testimonial-About",
69
+ quote: "This starter theme keeps the editable surface focused and predictable.",
70
+ author: "SudaCloud",
71
+ role: "Theme team",
72
+ },
73
+ },
74
+ ],
75
+ },
76
+ },
77
+ {
78
+ slug: "contact",
79
+ title: "Contact",
80
+ data: {
81
+ root: { props: {} },
82
+ content: [
83
+ {
84
+ type: "Hero",
85
+ props: {
86
+ id: "Hero-Contact",
87
+ eyebrow: "Contact",
88
+ title: "Let's talk",
89
+ description: "Tell visitors how to reach you and what happens next.",
90
+ primaryLabel: "Email us",
91
+ primaryHref: "mailto:hello@example.com",
92
+ },
93
+ },
94
+ {
95
+ type: "CallToAction",
96
+ props: {
97
+ id: "CallToAction-Contact",
98
+ title: "Start the conversation",
99
+ description: "Replace this copy with your preferred contact details or form link.",
100
+ buttonLabel: "Send an email",
101
+ buttonHref: "mailto:hello@example.com",
102
+ },
103
+ },
104
+ ],
105
+ },
106
+ },
107
+ ];