create-jay 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/dist/index.js ADDED
@@ -0,0 +1,300 @@
1
+ #!/usr/bin/env node
2
+
3
+ // lib/index.ts
4
+ import path2 from "node:path";
5
+ import { execSync } from "node:child_process";
6
+ import chalk from "chalk";
7
+
8
+ // lib/prompts.ts
9
+ import { input, checkbox } from "@inquirer/prompts";
10
+
11
+ // lib/plugins.ts
12
+ var PLUGINS = [
13
+ {
14
+ name: "@jay-framework/ui-kit",
15
+ label: "UI Kit",
16
+ description: "Headless primitives: popover, carousel, tabs, clipboard, split text",
17
+ group: "Jay Framework",
18
+ checked: true,
19
+ isDep: true
20
+ },
21
+ {
22
+ name: "@jay-framework/a11y-validator",
23
+ label: "Accessibility validator",
24
+ description: "WCAG accessibility checks for jay-html templates",
25
+ group: "Jay Framework",
26
+ checked: true,
27
+ isDep: false
28
+ },
29
+ {
30
+ name: "@jay-framework/seo-validator",
31
+ label: "SEO validator",
32
+ description: "SEO best practices: meta tags, heading hierarchy, image optimization",
33
+ group: "Jay Framework",
34
+ checked: true,
35
+ isDep: false
36
+ },
37
+ {
38
+ name: "@jay-framework/design-system-validator",
39
+ label: "Design system validator",
40
+ description: "Validates CSS against DESIGN.md tokens",
41
+ group: "Jay Framework",
42
+ checked: true,
43
+ isDep: false
44
+ },
45
+ {
46
+ name: "@jay-framework/wix-stores",
47
+ label: "Wix Stores",
48
+ description: "E-commerce: products, categories, search, product pages",
49
+ group: "Wix",
50
+ checked: false,
51
+ isDep: true
52
+ },
53
+ {
54
+ name: "@jay-framework/wix-cart",
55
+ label: "Wix Cart",
56
+ description: "Shopping cart: add/remove items, checkout, order summary",
57
+ group: "Wix",
58
+ checked: false,
59
+ isDep: true
60
+ },
61
+ {
62
+ name: "@jay-framework/wix-members",
63
+ label: "Wix Members",
64
+ description: "Authentication: login, register, member profiles, auth callback",
65
+ group: "Wix",
66
+ checked: false,
67
+ isDep: true
68
+ },
69
+ {
70
+ name: "@jay-framework/wix-media",
71
+ label: "Wix Media",
72
+ description: "Image optimization, media galleries, responsive images",
73
+ group: "Wix",
74
+ checked: false,
75
+ isDep: true
76
+ },
77
+ {
78
+ name: "@jay-framework/wix-data",
79
+ label: "Wix Data",
80
+ description: "CMS collections: dynamic pages, content management",
81
+ group: "Wix",
82
+ checked: false,
83
+ isDep: true
84
+ },
85
+ {
86
+ name: "@jay-framework/wix-deploy",
87
+ label: "Wix Deploy",
88
+ description: "Deployment to Wix infrastructure: CDN, hosting, domains",
89
+ group: "Wix",
90
+ checked: false,
91
+ isDep: true
92
+ },
93
+ {
94
+ name: "@jay-framework/wix-server-client",
95
+ label: "Wix Server Client",
96
+ description: "Server-side Wix API client: authentication, API access",
97
+ group: "Wix",
98
+ checked: false,
99
+ isDep: true
100
+ },
101
+ {
102
+ name: "@jay-framework/aiditor",
103
+ label: "AIditor",
104
+ description: "Visual AI editor: point-and-shoot editing with Claude",
105
+ group: "AIditor",
106
+ checked: false,
107
+ isDep: true
108
+ }
109
+ ];
110
+ var CORE_DEPS = [
111
+ "@jay-framework/fullstack-component",
112
+ "@jay-framework/runtime",
113
+ "@jay-framework/stack-client-runtime",
114
+ "@jay-framework/stack-server-runtime"
115
+ ];
116
+ var CORE_DEV_DEPS = [
117
+ "@jay-framework/jay-stack-cli",
118
+ "@jay-framework/compiler-jay-stack",
119
+ "@jay-framework/dev-environment",
120
+ "@jay-framework/jay-cli",
121
+ "typescript",
122
+ "vite"
123
+ ];
124
+
125
+ // lib/prompts.ts
126
+ async function runPrompts() {
127
+ const name = await input({
128
+ message: "Project name:",
129
+ validate: (value) => {
130
+ if (!value.trim())
131
+ return "Project name is required";
132
+ if (!/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(value.trim())) {
133
+ return "Use lowercase letters, numbers, and hyphens (e.g., my-store)";
134
+ }
135
+ return true;
136
+ }
137
+ });
138
+ const groups = /* @__PURE__ */ new Map();
139
+ for (const plugin of PLUGINS) {
140
+ const group = groups.get(plugin.group) || [];
141
+ group.push(plugin);
142
+ groups.set(plugin.group, group);
143
+ }
144
+ const choices = [];
145
+ for (const [group, plugins] of groups) {
146
+ choices.push({ name: `\u2500\u2500 ${group} \u2500\u2500`, value: "__separator__", disabled: "" });
147
+ for (const plugin of plugins) {
148
+ choices.push({
149
+ name: `${plugin.label} \u2014 ${plugin.description}`,
150
+ value: plugin.name,
151
+ checked: plugin.checked
152
+ });
153
+ }
154
+ }
155
+ const selected = await checkbox({
156
+ message: "Select plugins to install:",
157
+ choices
158
+ });
159
+ const selectedPlugins = PLUGINS.filter((p) => selected.includes(p.name));
160
+ return { name: name.trim(), selectedPlugins };
161
+ }
162
+
163
+ // lib/scaffold.ts
164
+ import fs from "node:fs";
165
+ import path from "node:path";
166
+ import { fileURLToPath } from "node:url";
167
+ var __dirname = path.dirname(fileURLToPath(import.meta.url));
168
+ function templatesDir() {
169
+ const fromDist = path.join(__dirname, "..", "templates");
170
+ if (fs.existsSync(fromDist))
171
+ return fromDist;
172
+ return path.join(__dirname, "templates");
173
+ }
174
+ function readTemplate(name) {
175
+ return fs.readFileSync(path.join(templatesDir(), name), "utf-8");
176
+ }
177
+ function writeFile(projectDir, relativePath, content) {
178
+ const fullPath = path.join(projectDir, relativePath);
179
+ fs.mkdirSync(path.dirname(fullPath), { recursive: true });
180
+ fs.writeFileSync(fullPath, content, "utf-8");
181
+ }
182
+ function generatePackageJson(name, selectedPlugins) {
183
+ const deps = {};
184
+ for (const dep of CORE_DEPS) {
185
+ deps[dep] = "latest";
186
+ }
187
+ for (const plugin of selectedPlugins) {
188
+ if (plugin.isDep)
189
+ deps[plugin.name] = "latest";
190
+ }
191
+ const devDeps = {};
192
+ for (const dep of CORE_DEV_DEPS) {
193
+ devDeps[dep] = "latest";
194
+ }
195
+ for (const plugin of selectedPlugins) {
196
+ if (!plugin.isDep)
197
+ devDeps[plugin.name] = "latest";
198
+ }
199
+ const pkg = {
200
+ name,
201
+ version: "0.1.0",
202
+ type: "module",
203
+ private: true,
204
+ scripts: {
205
+ dev: "jay-stack dev",
206
+ build: "jay-cli definitions src && jay-stack build",
207
+ serve: "jay-stack serve",
208
+ validate: "jay-stack validate",
209
+ "agent-kit": "jay-stack agent-kit",
210
+ setup: "jay-stack setup",
211
+ clean: "rimraf dist && rimraf build"
212
+ },
213
+ dependencies: sortKeys(deps),
214
+ devDependencies: sortKeys(devDeps)
215
+ };
216
+ return JSON.stringify(pkg, null, 2) + "\n";
217
+ }
218
+ function sortKeys(obj) {
219
+ const sorted = {};
220
+ for (const key of Object.keys(obj).sort()) {
221
+ sorted[key] = obj[key];
222
+ }
223
+ return sorted;
224
+ }
225
+ function scaffoldProject(projectDir, name, selectedPlugins) {
226
+ fs.mkdirSync(projectDir, { recursive: true });
227
+ writeFile(projectDir, "package.json", generatePackageJson(name, selectedPlugins));
228
+ writeFile(projectDir, "src/pages/page.jay-html", readTemplate("page.jay-html").replace(/\{\{name\}\}/g, name));
229
+ writeFile(projectDir, "src/pages/page.ts", readTemplate("page.ts"));
230
+ writeFile(projectDir, "src/pages/page.jay-contract", readTemplate("page.jay-contract"));
231
+ writeFile(projectDir, "src/styles/theme.css", readTemplate("theme.css"));
232
+ writeFile(projectDir, ".jay", readTemplate("jay-config.yaml"));
233
+ writeFile(projectDir, "vite.config.ts", readTemplate("vite.config.ts"));
234
+ writeFile(projectDir, "tsconfig.json", readTemplate("tsconfig.json"));
235
+ const jaySkillPath = path.join(templatesDir(), "jay-skill.md");
236
+ if (fs.existsSync(jaySkillPath)) {
237
+ writeFile(projectDir, "jay-skill.md", fs.readFileSync(jaySkillPath, "utf-8"));
238
+ }
239
+ const hasDesignValidator = selectedPlugins.some(
240
+ (p) => p.name === "@jay-framework/design-system-validator"
241
+ );
242
+ if (hasDesignValidator) {
243
+ writeFile(projectDir, "DESIGN.md", readTemplate("DESIGN.md"));
244
+ }
245
+ }
246
+
247
+ // lib/index.ts
248
+ function detectPackageManager() {
249
+ const agent = process.env.npm_config_user_agent || "";
250
+ if (agent.startsWith("yarn"))
251
+ return "yarn";
252
+ return "npm";
253
+ }
254
+ function run(cmd, cwd) {
255
+ execSync(cmd, { cwd, stdio: "inherit" });
256
+ }
257
+ async function main() {
258
+ const pm = detectPackageManager();
259
+ console.log("");
260
+ console.log(chalk.bold(" Create Jay Stack Project"));
261
+ console.log("");
262
+ const config = await runPrompts();
263
+ const projectDir = path2.resolve(process.cwd(), config.name);
264
+ console.log("");
265
+ console.log(`Creating project in ${chalk.cyan(`./${config.name}`)}...`);
266
+ scaffoldProject(projectDir, config.name, config.selectedPlugins);
267
+ console.log(chalk.green(" \u2713 Created project structure"));
268
+ console.log(chalk.dim(" Installing dependencies..."));
269
+ run(pm === "yarn" ? "yarn install" : "npm install", projectDir);
270
+ console.log(chalk.green(" \u2713 Installed dependencies"));
271
+ console.log(chalk.dim(" Generating agent-kit..."));
272
+ try {
273
+ run("npx jay-stack agent-kit", projectDir);
274
+ console.log(chalk.green(" \u2713 Generated agent-kit"));
275
+ } catch {
276
+ console.log(chalk.yellow(" \u26A0 Agent-kit generation skipped (can run later with: jay-stack agent-kit)"));
277
+ }
278
+ console.log(chalk.dim(" Running plugin setup..."));
279
+ try {
280
+ run("npx jay-stack setup", projectDir);
281
+ console.log(chalk.green(" \u2713 Plugin setup complete"));
282
+ } catch {
283
+ console.log(chalk.yellow(" \u26A0 Setup incomplete (can run later with: jay-stack setup)"));
284
+ }
285
+ const runCmd = pm === "yarn" ? "yarn dev" : "npm run dev";
286
+ console.log("");
287
+ console.log(chalk.bold(" Ready!"));
288
+ console.log("");
289
+ console.log(` ${chalk.cyan(`cd ${config.name}`)}`);
290
+ console.log(` ${chalk.cyan(runCmd)}`);
291
+ console.log("");
292
+ }
293
+ main().catch((err) => {
294
+ if (err.message?.includes("User force closed")) {
295
+ console.log("\nAborted.");
296
+ process.exit(0);
297
+ }
298
+ console.error(chalk.red("Error:"), err.message);
299
+ process.exit(1);
300
+ });
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "create-jay",
3
+ "version": "0.21.0",
4
+ "type": "module",
5
+ "description": "Create a new Jay Stack project",
6
+ "license": "Apache-2.0",
7
+ "bin": "./dist/index.js",
8
+ "files": [
9
+ "dist",
10
+ "templates"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsup",
14
+ "clean": "rimraf dist",
15
+ "confirm": "npm run clean && npm run build",
16
+ "test": ":"
17
+ },
18
+ "dependencies": {
19
+ "@inquirer/prompts": "^7.0.0",
20
+ "chalk": "^5.3.0"
21
+ },
22
+ "devDependencies": {
23
+ "@types/node": "^22.15.21",
24
+ "rimraf": "^5.0.5",
25
+ "tsup": "^8.0.1",
26
+ "typescript": "^5.3.3"
27
+ }
28
+ }
@@ -0,0 +1,71 @@
1
+ ---
2
+ name: My Design System
3
+
4
+ colors:
5
+ primary: '#2563eb'
6
+ primary-hover: '#1d4ed8'
7
+ secondary: '#64748b'
8
+ text: '#0f172a'
9
+ text-muted: '#64748b'
10
+ background: '#ffffff'
11
+ surface: '#f8fafc'
12
+ border: '#e2e8f0'
13
+ error: '#dc2626'
14
+ success: '#16a34a'
15
+
16
+ typography:
17
+ headline-lg:
18
+ fontFamily: system-ui, sans-serif
19
+ fontSize: 2.5rem
20
+ fontWeight: 700
21
+ lineHeight: 1.2
22
+ headline-md:
23
+ fontFamily: system-ui, sans-serif
24
+ fontSize: 2rem
25
+ fontWeight: 600
26
+ lineHeight: 1.3
27
+ body-md:
28
+ fontFamily: system-ui, sans-serif
29
+ fontSize: 1rem
30
+ fontWeight: 400
31
+ lineHeight: 1.6
32
+ label-sm:
33
+ fontFamily: system-ui, sans-serif
34
+ fontSize: 0.875rem
35
+ fontWeight: 500
36
+ lineHeight: 1.5
37
+
38
+ spacing:
39
+ xs: 0.25rem
40
+ sm: 0.5rem
41
+ md: 1rem
42
+ lg: 1.5rem
43
+ xl: 2rem
44
+ 2xl: 3rem
45
+
46
+ rounded:
47
+ none: 0
48
+ sm: 0.25rem
49
+ md: 0.5rem
50
+ lg: 0.75rem
51
+ full: 9999px
52
+
53
+ animations:
54
+ micro:
55
+ duration: 150ms
56
+ easing: ease-in-out
57
+ normal:
58
+ duration: 300ms
59
+ easing: cubic-bezier(0, 0, 0.2, 1)
60
+
61
+ rules:
62
+ max-font-weights: 3
63
+ max-primary-buttons: 1
64
+ require-contrast-aa: true
65
+ ---
66
+
67
+ # My Design System
68
+
69
+ Edit this file to define your design tokens. The design-system-validator plugin validates your CSS against these tokens during `jay-stack validate`.
70
+
71
+ See `agent-kit/designer/design-system.md` for usage guide.
@@ -0,0 +1,4 @@
1
+ devServer:
2
+ portRange: [3000, 3010]
3
+ pagesBase: './src/pages'
4
+ publicFolder: './public'
@@ -0,0 +1,123 @@
1
+ ---
2
+ name: jay
3
+ description: Getting started with Jay Stack projects. Covers plugin setup, agent-kit generation, the four roles (designer, developer, plugin, devops), and key CLI commands.
4
+ ---
5
+
6
+ # Jay Stack — Agent Skill
7
+
8
+ Jay Stack is a full-stack framework. Plugins provide headless components (data + logic, no UI). Designers build UI in jay-html templates that bind to plugin contracts. Developers write page logic and services.
9
+
10
+ ## Getting Started with a Jay Project
11
+
12
+ ### Step 1: Setup plugins
13
+
14
+ ```bash
15
+ yarn jay-stack-cli setup
16
+ ```
17
+
18
+ This configures plugins — creates config templates, validates credentials, connects to external services. Run this once when starting a new project or after adding a plugin.
19
+
20
+ ### Step 2: Generate the agent kit
21
+
22
+ ```bash
23
+ yarn jay-stack-cli agent-kit
24
+ ```
25
+
26
+ This materializes contracts, generates reference data, and copies role guides into `agent-kit/`. Run this after setup, or any time you need fresh contract data.
27
+
28
+ ### Step 3: Read the agent kit
29
+
30
+ The agent kit is your entry point. Start here:
31
+
32
+ **`agent-kit/plugins-index.yaml`** — lists every plugin and what it provides:
33
+
34
+ ```yaml
35
+ plugins:
36
+ - name: wix-stores
37
+ contracts:
38
+ - name: product-page
39
+ description: Product detail page with SSR
40
+ actions:
41
+ - name: searchProducts
42
+ description: Search the product catalog
43
+ services:
44
+ - name: products-db
45
+ description: Product catalog API
46
+ commands:
47
+ - name: sync-catalog
48
+ description: Sync product catalog from CMS
49
+ ```
50
+
51
+ Use this file to discover what's available before writing any code.
52
+
53
+ **`agent-kit/materialized-contracts/`** — the actual `.jay-contract` files. Read these to understand the data shapes, rendering phases, and refs for each component.
54
+
55
+ **`agent-kit/references/<plugin>/`** — pre-generated discovery data (product catalogs, collection schemas, etc.). Check here before running CLI commands — it's faster.
56
+
57
+ ## The Four Roles
58
+
59
+ The agent kit contains guides organized by role. Read the role that matches your task:
60
+
61
+ | Folder | Role | When to read |
62
+ | ---------------------- | ---------------- | ----------------------------------------------------------------- |
63
+ | `agent-kit/designer/` | Designer | Creating or editing `.jay-html` pages, styling, template syntax |
64
+ | `agent-kit/developer/` | Developer | Writing `page.ts` components, services, state management, routing |
65
+ | `agent-kit/plugin/` | Plugin Developer | Creating headless components, contracts, actions, CLI commands |
66
+ | `agent-kit/devops/` | DevOps | Building, deploying, serving in production, invalidation |
67
+
68
+ Each folder has an `INSTRUCTIONS.md` that lists all available guides. Start there.
69
+
70
+ ## Key CLI Commands
71
+
72
+ ```bash
73
+ # Development
74
+ yarn jay-stack-cli dev # Start dev server
75
+ yarn jay-stack-cli dev -v # Verbose mode
76
+
77
+ # Validation
78
+ yarn jay-stack-cli validate # Validate all jay-html, contracts, actions
79
+
80
+ # Discovery
81
+ yarn jay-stack-cli agent-kit --list # List available contracts
82
+ yarn jay-stack-cli params <plugin>/<contract> # Discover URL params for a contract
83
+ yarn jay-stack-cli action <plugin>/<action> --input '{}' # Run a plugin action
84
+
85
+ # Plugin commands (admin/batch operations)
86
+ yarn jay-stack-cli run --list # List available plugin commands
87
+ yarn jay-stack-cli run <plugin>/<command> # Run a plugin command
88
+
89
+ # Production
90
+ yarn jay-stack-cli build # Build production artifacts
91
+ yarn jay-stack-cli serve # Start production server
92
+ ```
93
+
94
+ ## Project Structure
95
+
96
+ ```
97
+ src/
98
+ pages/ # File-system routing
99
+ page.jay-html # Root page (/)
100
+ products/
101
+ page.jay-html # /products
102
+ [slug]/
103
+ page.jay-html # /products/:slug
104
+ page.ts # Page component (optional)
105
+ plugins/ # Local plugins
106
+ components/ # Headfull components
107
+ init.ts # Project service initialization
108
+ agent-kit/ # Generated by jay-stack agent-kit
109
+ plugins-index.yaml # Discovery index
110
+ designer/ # Designer role guides
111
+ developer/ # Developer role guides
112
+ plugin/ # Plugin developer guides
113
+ devops/ # DevOps guides
114
+ materialized-contracts/
115
+ references/
116
+ ```
117
+
118
+ ## Before Writing Code
119
+
120
+ 1. Read `agent-kit/plugins-index.yaml` to see what plugins and contracts exist
121
+ 2. Read the relevant contract file to understand the data shape
122
+ 3. Read the role guide that matches your task (designer/developer/plugin/devops)
123
+ 4. Check `agent-kit/references/<plugin>/` for pre-generated data before using CLI commands
@@ -0,0 +1,12 @@
1
+ name: page
2
+
3
+ tags:
4
+ - tag: title
5
+ type: data
6
+ dataType: string
7
+ phase: slow
8
+
9
+ - tag: description
10
+ type: data
11
+ dataType: string
12
+ phase: slow
@@ -0,0 +1,35 @@
1
+ <html lang="en">
2
+ <head>
3
+ <title>{{name}}</title>
4
+ <meta name="description" content="A Jay Stack project">
5
+ <script type="application/jay-data" contract="./page.jay-contract"></script>
6
+ <link rel="stylesheet" href="../styles/theme.css" />
7
+ <style>
8
+ .hero {
9
+ display: flex;
10
+ flex-direction: column;
11
+ align-items: center;
12
+ justify-content: center;
13
+ min-height: 80vh;
14
+ text-align: center;
15
+ padding: 2rem;
16
+ }
17
+ .hero h1 {
18
+ font-size: 2.5rem;
19
+ font-weight: 700;
20
+ margin-bottom: 1rem;
21
+ }
22
+ .hero p {
23
+ font-size: 1.25rem;
24
+ color: #64748b;
25
+ max-width: 600px;
26
+ }
27
+ </style>
28
+ </head>
29
+ <body>
30
+ <main class="hero">
31
+ <h1>{title}</h1>
32
+ <p>{description}</p>
33
+ </main>
34
+ </body>
35
+ </html>
@@ -0,0 +1,12 @@
1
+ import { makeJayStackComponent, phaseOutput } from '@jay-framework/fullstack-component';
2
+ import type { PageContract } from './page.jay-contract';
3
+
4
+ export const page = makeJayStackComponent<PageContract>().withSlowlyRender(async () => {
5
+ return phaseOutput(
6
+ {
7
+ title: 'Welcome to Jay',
8
+ description: 'Your project is ready. Edit src/pages/page.jay-html to get started.',
9
+ },
10
+ {},
11
+ );
12
+ });
@@ -0,0 +1,36 @@
1
+ :root {
2
+ --color-text: #0f172a;
3
+ --color-text-muted: #64748b;
4
+ --color-bg: #ffffff;
5
+ --color-surface: #f8fafc;
6
+ --color-border: #e2e8f0;
7
+ --color-primary: #2563eb;
8
+ }
9
+
10
+ *,
11
+ *::before,
12
+ *::after {
13
+ box-sizing: border-box;
14
+ margin: 0;
15
+ padding: 0;
16
+ }
17
+
18
+ body {
19
+ font-family:
20
+ system-ui,
21
+ -apple-system,
22
+ sans-serif;
23
+ color: var(--color-text);
24
+ background: var(--color-bg);
25
+ line-height: 1.6;
26
+ -webkit-font-smoothing: antialiased;
27
+ }
28
+
29
+ a {
30
+ color: var(--color-primary);
31
+ text-decoration: none;
32
+ }
33
+
34
+ a:hover {
35
+ text-decoration: underline;
36
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "extends": "@jay-framework/dev-environment/examples/tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "dist",
5
+ },
6
+ "include": ["src"],
7
+ }
@@ -0,0 +1,12 @@
1
+ import { resolve } from 'path';
2
+ import { defineConfig } from 'vite';
3
+ import { jayStackCompiler } from '@jay-framework/compiler-jay-stack';
4
+
5
+ const jayOptions = {
6
+ tsConfigFilePath: resolve(__dirname, 'tsconfig.json'),
7
+ outputDir: 'build',
8
+ };
9
+
10
+ export default defineConfig({
11
+ plugins: [...jayStackCompiler(jayOptions)],
12
+ });