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 +300 -0
- package/package.json +28 -0
- package/templates/DESIGN.md +71 -0
- package/templates/jay-config.yaml +4 -0
- package/templates/jay-skill.md +123 -0
- package/templates/page.jay-contract +12 -0
- package/templates/page.jay-html +35 -0
- package/templates/page.ts +12 -0
- package/templates/theme.css +36 -0
- package/templates/tsconfig.json +7 -0
- package/templates/vite.config.ts +12 -0
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,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,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,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
|
+
});
|