create-jay 0.21.0 → 0.22.1
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 +122 -73
- package/package.json +1 -1
- package/templates/CLAUDE.md +13 -0
- package/templates/auth-callback.jay-html +56 -0
- package/templates/jay-skill.md +1 -1
- package/templates/page.jay-html +162 -14
- package/templates/page.ts +1 -1
- package/templates/tsconfig.json +12 -1
package/dist/index.js
CHANGED
|
@@ -50,14 +50,6 @@ var PLUGINS = [
|
|
|
50
50
|
checked: false,
|
|
51
51
|
isDep: true
|
|
52
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
53
|
{
|
|
62
54
|
name: "@jay-framework/wix-members",
|
|
63
55
|
label: "Wix Members",
|
|
@@ -89,51 +81,37 @@ var PLUGINS = [
|
|
|
89
81
|
group: "Wix",
|
|
90
82
|
checked: false,
|
|
91
83
|
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
84
|
}
|
|
109
85
|
];
|
|
110
|
-
var CORE_DEPS =
|
|
111
|
-
"@jay-framework/fullstack-component",
|
|
112
|
-
"@jay-framework/
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
"@
|
|
118
|
-
"
|
|
119
|
-
"
|
|
120
|
-
"
|
|
121
|
-
|
|
122
|
-
"vite"
|
|
123
|
-
];
|
|
86
|
+
var CORE_DEPS = {
|
|
87
|
+
"@jay-framework/fullstack-component": "^0.21.0",
|
|
88
|
+
"@jay-framework/jay-stack-cli": "^0.21.0"
|
|
89
|
+
};
|
|
90
|
+
var CORE_DEV_DEPS = {
|
|
91
|
+
"@jay-framework/aiditor": "^0.21.0",
|
|
92
|
+
"@jay-framework/jay-cli": "^0.21.0",
|
|
93
|
+
"@types/node": "^22.10.0",
|
|
94
|
+
rimraf: "^6.0.0",
|
|
95
|
+
typescript: "~5.7.2",
|
|
96
|
+
vite: "^6.0.1"
|
|
97
|
+
};
|
|
124
98
|
|
|
125
99
|
// lib/prompts.ts
|
|
100
|
+
function validateProjectName(value) {
|
|
101
|
+
const name = value.trim();
|
|
102
|
+
if (!name)
|
|
103
|
+
return "Project name is required";
|
|
104
|
+
if (name.length < 3)
|
|
105
|
+
return "Project name must be at least 3 characters";
|
|
106
|
+
if (!/^[a-z0-9][a-z0-9-]*[a-z0-9]$/.test(name)) {
|
|
107
|
+
return "Use lowercase letters, numbers, and hyphens \u2014 must start and end with a letter or number (e.g., my-store)";
|
|
108
|
+
}
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
126
111
|
async function runPrompts() {
|
|
127
112
|
const name = await input({
|
|
128
113
|
message: "Project name:",
|
|
129
|
-
validate:
|
|
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
|
-
}
|
|
114
|
+
validate: validateProjectName
|
|
137
115
|
});
|
|
138
116
|
const groups = /* @__PURE__ */ new Map();
|
|
139
117
|
for (const plugin of PLUGINS) {
|
|
@@ -143,7 +121,7 @@ async function runPrompts() {
|
|
|
143
121
|
}
|
|
144
122
|
const choices = [];
|
|
145
123
|
for (const [group, plugins] of groups) {
|
|
146
|
-
choices.push({ name: `\u2500\u2500 ${group} \u2500\u2500`, value: "__separator__", disabled: "" });
|
|
124
|
+
choices.push({ name: `\u2500\u2500 ${group} \u2500\u2500`, value: "__separator__", disabled: " " });
|
|
147
125
|
for (const plugin of plugins) {
|
|
148
126
|
choices.push({
|
|
149
127
|
name: `${plugin.label} \u2014 ${plugin.description}`,
|
|
@@ -154,7 +132,8 @@ async function runPrompts() {
|
|
|
154
132
|
}
|
|
155
133
|
const selected = await checkbox({
|
|
156
134
|
message: "Select plugins to install:",
|
|
157
|
-
choices
|
|
135
|
+
choices,
|
|
136
|
+
pageSize: process.stdout.rows ? process.stdout.rows - 5 : 20
|
|
158
137
|
});
|
|
159
138
|
const selectedPlugins = PLUGINS.filter((p) => selected.includes(p.name));
|
|
160
139
|
return { name: name.trim(), selectedPlugins };
|
|
@@ -180,35 +159,47 @@ function writeFile(projectDir, relativePath, content) {
|
|
|
180
159
|
fs.writeFileSync(fullPath, content, "utf-8");
|
|
181
160
|
}
|
|
182
161
|
function generatePackageJson(name, selectedPlugins) {
|
|
183
|
-
const deps = {};
|
|
184
|
-
for (const dep of CORE_DEPS) {
|
|
185
|
-
deps[dep] = "latest";
|
|
186
|
-
}
|
|
162
|
+
const deps = { ...CORE_DEPS };
|
|
187
163
|
for (const plugin of selectedPlugins) {
|
|
188
164
|
if (plugin.isDep)
|
|
189
165
|
deps[plugin.name] = "latest";
|
|
190
166
|
}
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
167
|
+
const hasWixPlugins = selectedPlugins.some((p) => p.name.startsWith("@jay-framework/wix-"));
|
|
168
|
+
const hasWixStores = selectedPlugins.some((p) => p.name === "@jay-framework/wix-stores");
|
|
169
|
+
if (hasWixPlugins)
|
|
170
|
+
deps["@jay-framework/wix-server-client"] = "latest";
|
|
171
|
+
if (hasWixStores)
|
|
172
|
+
deps["@jay-framework/wix-cart"] = "latest";
|
|
173
|
+
const devDeps = { ...CORE_DEV_DEPS };
|
|
195
174
|
for (const plugin of selectedPlugins) {
|
|
196
175
|
if (!plugin.isDep)
|
|
197
176
|
devDeps[plugin.name] = "latest";
|
|
198
177
|
}
|
|
178
|
+
const hasWixDeploy = selectedPlugins.some((p) => p.name === "@jay-framework/wix-deploy");
|
|
179
|
+
const hasAiditor = true;
|
|
199
180
|
const pkg = {
|
|
200
181
|
name,
|
|
201
182
|
version: "0.1.0",
|
|
202
183
|
type: "module",
|
|
203
184
|
private: true,
|
|
204
185
|
scripts: {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
validate: "jay-stack validate",
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
186
|
+
setup: "jay-stack-cli setup",
|
|
187
|
+
dev: "jay-stack-cli dev",
|
|
188
|
+
"agent-kit": "jay-stack-cli agent-kit",
|
|
189
|
+
validate: "jay-stack-cli validate",
|
|
190
|
+
clean: "rimraf dist && rimraf build && rimraf -g 'src/**/*.d.ts'",
|
|
191
|
+
definitions: "jay-cli definitions src",
|
|
192
|
+
build: "npm run agent-kit && npm run definitions",
|
|
193
|
+
"build:production": "npm run build && jay-stack-cli build",
|
|
194
|
+
"build:check-types": "tsc",
|
|
195
|
+
serve: "jay-stack-cli serve",
|
|
196
|
+
...hasWixDeploy && {
|
|
197
|
+
"wix:deploy": "jay-stack-cli run wix-deploy/deploy --exclude-plugins aiditor",
|
|
198
|
+
"wix:serve": "node serve.mjs"
|
|
199
|
+
},
|
|
200
|
+
...hasAiditor && {
|
|
201
|
+
"aiditor:publish": hasWixDeploy ? "npm run build:production && npm run wix:deploy" : "npm run build:production && echo 'add your deploy command here'"
|
|
202
|
+
}
|
|
212
203
|
},
|
|
213
204
|
dependencies: sortKeys(deps),
|
|
214
205
|
devDependencies: sortKeys(devDeps)
|
|
@@ -225,13 +216,18 @@ function sortKeys(obj) {
|
|
|
225
216
|
function scaffoldProject(projectDir, name, selectedPlugins) {
|
|
226
217
|
fs.mkdirSync(projectDir, { recursive: true });
|
|
227
218
|
writeFile(projectDir, "package.json", generatePackageJson(name, selectedPlugins));
|
|
228
|
-
writeFile(
|
|
219
|
+
writeFile(
|
|
220
|
+
projectDir,
|
|
221
|
+
"src/pages/page.jay-html",
|
|
222
|
+
readTemplate("page.jay-html").replace(/\{\{name\}\}/g, name)
|
|
223
|
+
);
|
|
229
224
|
writeFile(projectDir, "src/pages/page.ts", readTemplate("page.ts"));
|
|
230
225
|
writeFile(projectDir, "src/pages/page.jay-contract", readTemplate("page.jay-contract"));
|
|
231
226
|
writeFile(projectDir, "src/styles/theme.css", readTemplate("theme.css"));
|
|
232
227
|
writeFile(projectDir, ".jay", readTemplate("jay-config.yaml"));
|
|
233
228
|
writeFile(projectDir, "vite.config.ts", readTemplate("vite.config.ts"));
|
|
234
229
|
writeFile(projectDir, "tsconfig.json", readTemplate("tsconfig.json"));
|
|
230
|
+
writeFile(projectDir, "CLAUDE.md", readTemplate("CLAUDE.md"));
|
|
235
231
|
const jaySkillPath = path.join(templatesDir(), "jay-skill.md");
|
|
236
232
|
if (fs.existsSync(jaySkillPath)) {
|
|
237
233
|
writeFile(projectDir, "jay-skill.md", fs.readFileSync(jaySkillPath, "utf-8"));
|
|
@@ -242,6 +238,14 @@ function scaffoldProject(projectDir, name, selectedPlugins) {
|
|
|
242
238
|
if (hasDesignValidator) {
|
|
243
239
|
writeFile(projectDir, "DESIGN.md", readTemplate("DESIGN.md"));
|
|
244
240
|
}
|
|
241
|
+
const hasWixMembers = selectedPlugins.some((p) => p.name === "@jay-framework/wix-members");
|
|
242
|
+
if (hasWixMembers) {
|
|
243
|
+
writeFile(
|
|
244
|
+
projectDir,
|
|
245
|
+
"src/pages/auth/callback/page.jay-html",
|
|
246
|
+
readTemplate("auth-callback.jay-html")
|
|
247
|
+
);
|
|
248
|
+
}
|
|
245
249
|
}
|
|
246
250
|
|
|
247
251
|
// lib/index.ts
|
|
@@ -254,39 +258,84 @@ function detectPackageManager() {
|
|
|
254
258
|
function run(cmd, cwd) {
|
|
255
259
|
execSync(cmd, { cwd, stdio: "inherit" });
|
|
256
260
|
}
|
|
261
|
+
function parseArgs() {
|
|
262
|
+
const args = process.argv.slice(2);
|
|
263
|
+
const result = {};
|
|
264
|
+
for (let i = 0; i < args.length; i++) {
|
|
265
|
+
if (args[i] === "--name" && args[i + 1]) {
|
|
266
|
+
result.name = args[++i];
|
|
267
|
+
} else if (args[i] === "--plugins" && args[i + 1]) {
|
|
268
|
+
result.plugins = args[++i];
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return result;
|
|
272
|
+
}
|
|
257
273
|
async function main() {
|
|
258
274
|
const pm = detectPackageManager();
|
|
275
|
+
const cliArgs = parseArgs();
|
|
276
|
+
const isNonInteractive = !!(cliArgs.name && cliArgs.plugins !== void 0);
|
|
259
277
|
console.log("");
|
|
260
278
|
console.log(chalk.bold(" Create Jay Stack Project"));
|
|
261
279
|
console.log("");
|
|
262
|
-
|
|
263
|
-
|
|
280
|
+
let name;
|
|
281
|
+
let selectedPlugins;
|
|
282
|
+
if (isNonInteractive) {
|
|
283
|
+
name = cliArgs.name;
|
|
284
|
+
const nameError = validateProjectName(name);
|
|
285
|
+
if (nameError !== true) {
|
|
286
|
+
console.error(chalk.red(` Error: ${nameError}`));
|
|
287
|
+
process.exit(1);
|
|
288
|
+
}
|
|
289
|
+
const requested = cliArgs.plugins ? cliArgs.plugins.split(",").map((s) => s.trim()) : [];
|
|
290
|
+
selectedPlugins = PLUGINS.filter(
|
|
291
|
+
(p) => requested.includes(p.name) || requested.includes(p.label.toLowerCase())
|
|
292
|
+
);
|
|
293
|
+
} else {
|
|
294
|
+
const config = await runPrompts();
|
|
295
|
+
name = config.name;
|
|
296
|
+
selectedPlugins = config.selectedPlugins;
|
|
297
|
+
}
|
|
298
|
+
const projectDir = path2.resolve(process.cwd(), name);
|
|
264
299
|
console.log("");
|
|
265
|
-
console.log(`Creating project in ${chalk.cyan(`./${
|
|
266
|
-
scaffoldProject(projectDir,
|
|
300
|
+
console.log(`Creating project in ${chalk.cyan(`./${name}`)}...`);
|
|
301
|
+
scaffoldProject(projectDir, name, selectedPlugins);
|
|
267
302
|
console.log(chalk.green(" \u2713 Created project structure"));
|
|
268
303
|
console.log(chalk.dim(" Installing dependencies..."));
|
|
269
304
|
run(pm === "yarn" ? "yarn install" : "npm install", projectDir);
|
|
270
305
|
console.log(chalk.green(" \u2713 Installed dependencies"));
|
|
271
306
|
console.log(chalk.dim(" Generating agent-kit..."));
|
|
272
307
|
try {
|
|
273
|
-
run("npx jay-stack agent-kit", projectDir);
|
|
308
|
+
run("npx jay-stack-cli agent-kit", projectDir);
|
|
274
309
|
console.log(chalk.green(" \u2713 Generated agent-kit"));
|
|
275
310
|
} catch {
|
|
276
|
-
console.log(
|
|
311
|
+
console.log(
|
|
312
|
+
chalk.yellow(
|
|
313
|
+
" \u26A0 Agent-kit generation skipped (can run later with: npm run agent-kit)"
|
|
314
|
+
)
|
|
315
|
+
);
|
|
277
316
|
}
|
|
278
317
|
console.log(chalk.dim(" Running plugin setup..."));
|
|
279
318
|
try {
|
|
280
|
-
|
|
319
|
+
const setupCmd = isNonInteractive ? "npx jay-stack-cli setup" : "npx jay-stack-cli setup --interactive";
|
|
320
|
+
run(setupCmd, projectDir);
|
|
281
321
|
console.log(chalk.green(" \u2713 Plugin setup complete"));
|
|
282
322
|
} catch {
|
|
283
|
-
|
|
323
|
+
if (!isNonInteractive) {
|
|
324
|
+
try {
|
|
325
|
+
run("npx jay-stack-cli setup", projectDir);
|
|
326
|
+
console.log(chalk.green(" \u2713 Plugin setup complete"));
|
|
327
|
+
} catch {
|
|
328
|
+
console.log(chalk.yellow(" \u26A0 Setup incomplete (can run later with: npm run setup)"));
|
|
329
|
+
}
|
|
330
|
+
} else {
|
|
331
|
+
console.log(chalk.yellow(" \u26A0 Setup incomplete (can run later with: npm run setup)"));
|
|
332
|
+
}
|
|
284
333
|
}
|
|
285
334
|
const runCmd = pm === "yarn" ? "yarn dev" : "npm run dev";
|
|
286
335
|
console.log("");
|
|
287
336
|
console.log(chalk.bold(" Ready!"));
|
|
288
337
|
console.log("");
|
|
289
|
-
console.log(` ${chalk.cyan(`cd ${
|
|
338
|
+
console.log(` ${chalk.cyan(`cd ${name}`)}`);
|
|
290
339
|
console.log(` ${chalk.cyan(runCmd)}`);
|
|
291
340
|
console.log("");
|
|
292
341
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This is a Jay Stack project.
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
Run `yarn setup` then `yarn agent-kit` to generate the agent kit.
|
|
8
|
+
|
|
9
|
+
Read `agent-kit/` for contracts, plugin references, and role guides. See the `/jay` skill for full details on the agent kit structure, CLI commands, and project organization.
|
|
10
|
+
|
|
11
|
+
Before making changes, read `agent-kit/plugins-index.yaml` and the relevant role guide (`agent-kit/designer/`, `agent-kit/developer/`, etc.).
|
|
12
|
+
|
|
13
|
+
Run `yarn validate` after changes.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<html>
|
|
2
|
+
<head>
|
|
3
|
+
<title>Signing in...</title>
|
|
4
|
+
<meta name="description" content="Authentication callback — please wait while we sign you in.">
|
|
5
|
+
<script type="application/jay-headless" plugin="@jay-framework/wix-members" contract="auth-callback"></script>
|
|
6
|
+
<script type="application/jay-data">
|
|
7
|
+
data:
|
|
8
|
+
</script>
|
|
9
|
+
<link rel="stylesheet" href="../../../styles/theme.css" />
|
|
10
|
+
<style>
|
|
11
|
+
.auth-callback {
|
|
12
|
+
display: flex;
|
|
13
|
+
align-items: center;
|
|
14
|
+
justify-content: center;
|
|
15
|
+
min-height: 100vh;
|
|
16
|
+
padding: 2rem;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.auth-callback-content {
|
|
20
|
+
text-align: center;
|
|
21
|
+
max-width: 400px;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.auth-callback-content h1 {
|
|
25
|
+
font-size: 1.5rem;
|
|
26
|
+
font-weight: 600;
|
|
27
|
+
margin-bottom: 0.75rem;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.auth-callback-content p {
|
|
31
|
+
color: var(--color-text-muted);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.auth-error {
|
|
35
|
+
color: #dc2626;
|
|
36
|
+
}
|
|
37
|
+
</style>
|
|
38
|
+
</head>
|
|
39
|
+
<body>
|
|
40
|
+
<jay:auth-callback>
|
|
41
|
+
<main class="auth-callback">
|
|
42
|
+
<div class="auth-callback-content">
|
|
43
|
+
<div if="isProcessing">
|
|
44
|
+
<h1>Signing you in...</h1>
|
|
45
|
+
<p>Please wait while we complete your login.</p>
|
|
46
|
+
</div>
|
|
47
|
+
<div if="hasError">
|
|
48
|
+
<h1>Something went wrong</h1>
|
|
49
|
+
<p class="auth-error">{errorMessage}</p>
|
|
50
|
+
<p><a href="/">Return to homepage</a></p>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
</main>
|
|
54
|
+
</jay:auth-callback>
|
|
55
|
+
</body>
|
|
56
|
+
</html>
|
package/templates/jay-skill.md
CHANGED
|
@@ -15,7 +15,7 @@ Jay Stack is a full-stack framework. Plugins provide headless components (data +
|
|
|
15
15
|
yarn jay-stack-cli setup
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
This configures plugins —
|
|
18
|
+
This configures plugins interactively — prompts for API keys and credentials, creates config files, validates services. Run this once when starting a new project or after adding a plugin. Use `--no-interactive` in CI/scripts to create config templates without prompting.
|
|
19
19
|
|
|
20
20
|
### Step 2: Generate the agent kit
|
|
21
21
|
|
package/templates/page.jay-html
CHANGED
|
@@ -1,35 +1,183 @@
|
|
|
1
1
|
<html lang="en">
|
|
2
2
|
<head>
|
|
3
|
-
<title>{{name}}</title>
|
|
4
|
-
<meta name="description" content="
|
|
3
|
+
<title>Welcome to {{name}}</title>
|
|
4
|
+
<meta name="description" content="Your Jay Stack project is ready — edit pages with the AIditor, a coding agent, or by hand.">
|
|
5
5
|
<script type="application/jay-data" contract="./page.jay-contract"></script>
|
|
6
|
+
<script
|
|
7
|
+
type="application/jay-headless"
|
|
8
|
+
plugin="@jay-framework/ui-kit"
|
|
9
|
+
contract="letter-split"
|
|
10
|
+
></script>
|
|
6
11
|
<link rel="stylesheet" href="../styles/theme.css" />
|
|
7
12
|
<style>
|
|
13
|
+
/* ── Hero ── */
|
|
8
14
|
.hero {
|
|
9
15
|
display: flex;
|
|
10
16
|
flex-direction: column;
|
|
11
17
|
align-items: center;
|
|
12
18
|
justify-content: center;
|
|
13
|
-
min-height:
|
|
19
|
+
min-height: 50vh;
|
|
14
20
|
text-align: center;
|
|
15
|
-
padding: 2rem;
|
|
21
|
+
padding: 3rem 2rem 2rem;
|
|
16
22
|
}
|
|
17
|
-
|
|
18
|
-
|
|
23
|
+
|
|
24
|
+
.hero-title {
|
|
25
|
+
font-size: clamp(2.2rem, 5vw, 3.5rem);
|
|
26
|
+
font-weight: 800;
|
|
27
|
+
margin-bottom: 1.5rem;
|
|
28
|
+
line-height: 1.15;
|
|
29
|
+
white-space: pre;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* Letter-split wave animation */
|
|
33
|
+
.letter {
|
|
34
|
+
display: inline-block;
|
|
35
|
+
animation: wave 2.2s ease-in-out infinite;
|
|
36
|
+
animation-delay: calc(var(--i) * 0.07s);
|
|
37
|
+
}
|
|
38
|
+
@keyframes wave {
|
|
39
|
+
0%, 100% { transform: translateY(0); }
|
|
40
|
+
30% { transform: translateY(-0.25em); }
|
|
41
|
+
50% { transform: translateY(0); }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.hero-subtitle {
|
|
45
|
+
font-size: 1.2rem;
|
|
46
|
+
color: var(--color-text-muted);
|
|
47
|
+
max-width: 520px;
|
|
48
|
+
margin-bottom: 2rem;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/* ── CTA button ── */
|
|
52
|
+
.cta-btn {
|
|
53
|
+
display: inline-flex;
|
|
54
|
+
align-items: center;
|
|
55
|
+
gap: 0.5rem;
|
|
56
|
+
padding: 0.85rem 2rem;
|
|
57
|
+
font-size: 1.1rem;
|
|
58
|
+
font-weight: 600;
|
|
59
|
+
color: #fff;
|
|
60
|
+
background: var(--color-primary);
|
|
61
|
+
border: none;
|
|
62
|
+
border-radius: 0.6rem;
|
|
63
|
+
text-decoration: none;
|
|
64
|
+
cursor: pointer;
|
|
65
|
+
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
|
66
|
+
}
|
|
67
|
+
.cta-btn:hover {
|
|
68
|
+
transform: translateY(-2px);
|
|
69
|
+
box-shadow: 0 6px 20px rgba(37, 99, 235, 0.35);
|
|
70
|
+
text-decoration: none;
|
|
71
|
+
}
|
|
72
|
+
.cta-btn:active {
|
|
73
|
+
transform: translateY(0);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* ── Steps section ── */
|
|
77
|
+
.steps {
|
|
78
|
+
display: flex;
|
|
79
|
+
flex-direction: column;
|
|
80
|
+
gap: 1.5rem;
|
|
81
|
+
max-width: 640px;
|
|
82
|
+
margin: 0 auto;
|
|
83
|
+
padding: 2rem 2rem 4rem;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.step {
|
|
87
|
+
display: flex;
|
|
88
|
+
align-items: flex-start;
|
|
89
|
+
gap: 1rem;
|
|
90
|
+
padding: 1.25rem 1.5rem;
|
|
91
|
+
background: var(--color-surface);
|
|
92
|
+
border: 1px solid var(--color-border);
|
|
93
|
+
border-radius: 0.75rem;
|
|
94
|
+
opacity: 0;
|
|
95
|
+
transform: translateY(12px);
|
|
96
|
+
animation: fadeUp 0.5s ease forwards;
|
|
97
|
+
}
|
|
98
|
+
.step:nth-child(1) { animation-delay: 0.2s; }
|
|
99
|
+
.step:nth-child(2) { animation-delay: 0.4s; }
|
|
100
|
+
.step:nth-child(3) { animation-delay: 0.6s; }
|
|
101
|
+
|
|
102
|
+
@keyframes fadeUp {
|
|
103
|
+
to {
|
|
104
|
+
opacity: 1;
|
|
105
|
+
transform: translateY(0);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.step-number {
|
|
110
|
+
flex-shrink: 0;
|
|
111
|
+
width: 2rem;
|
|
112
|
+
height: 2rem;
|
|
113
|
+
display: flex;
|
|
114
|
+
align-items: center;
|
|
115
|
+
justify-content: center;
|
|
19
116
|
font-weight: 700;
|
|
20
|
-
|
|
117
|
+
font-size: 0.95rem;
|
|
118
|
+
color: var(--color-primary);
|
|
119
|
+
background: rgba(37, 99, 235, 0.1);
|
|
120
|
+
border-radius: 50%;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.step-body h2 {
|
|
124
|
+
font-size: 1rem;
|
|
125
|
+
font-weight: 600;
|
|
126
|
+
margin-bottom: 0.2rem;
|
|
127
|
+
}
|
|
128
|
+
.step-body p {
|
|
129
|
+
font-size: 0.9rem;
|
|
130
|
+
color: var(--color-text-muted);
|
|
131
|
+
line-height: 1.5;
|
|
21
132
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
133
|
+
|
|
134
|
+
.step-body code {
|
|
135
|
+
font-size: 0.85rem;
|
|
136
|
+
background: var(--color-border);
|
|
137
|
+
padding: 0.1em 0.4em;
|
|
138
|
+
border-radius: 0.3rem;
|
|
26
139
|
}
|
|
27
140
|
</style>
|
|
28
141
|
</head>
|
|
29
142
|
<body>
|
|
30
|
-
<main
|
|
31
|
-
<
|
|
32
|
-
|
|
143
|
+
<main>
|
|
144
|
+
<section class="hero">
|
|
145
|
+
<jay:letter-split text="{title}">
|
|
146
|
+
<h1 class="hero-title" aria-label="Welcome to {{name}}">
|
|
147
|
+
<span forEach="letters" trackBy="index" class="letter" aria-hidden="true" style="--i: {index}">{text}</span>
|
|
148
|
+
</h1>
|
|
149
|
+
</jay:letter-split>
|
|
150
|
+
|
|
151
|
+
<p class="hero-subtitle">{description}</p>
|
|
152
|
+
|
|
153
|
+
<a class="cta-btn" href="/aiditor">Open the AIditor ➔</a>
|
|
154
|
+
</section>
|
|
155
|
+
|
|
156
|
+
<section class="steps">
|
|
157
|
+
<div class="step">
|
|
158
|
+
<span class="step-number">1</span>
|
|
159
|
+
<div class="step-body">
|
|
160
|
+
<h2>Use the AIditor</h2>
|
|
161
|
+
<p>Open the visual editor at <a href="/aiditor">/aiditor</a> to design and tweak pages with AI assistance.</p>
|
|
162
|
+
</div>
|
|
163
|
+
</div>
|
|
164
|
+
|
|
165
|
+
<div class="step">
|
|
166
|
+
<span class="step-number">2</span>
|
|
167
|
+
<div class="step-body">
|
|
168
|
+
<h2>Use any coding agent</h2>
|
|
169
|
+
<p>Work with your favorite AI coding tool — Cursor, Claude Code, or any agent that can edit files.</p>
|
|
170
|
+
</div>
|
|
171
|
+
</div>
|
|
172
|
+
|
|
173
|
+
<div class="step">
|
|
174
|
+
<span class="step-number">3</span>
|
|
175
|
+
<div class="step-body">
|
|
176
|
+
<h2>Edit the source directly</h2>
|
|
177
|
+
<p>Pages live in <code>src/pages/</code> — open the jay-html files in any editor and start building.</p>
|
|
178
|
+
</div>
|
|
179
|
+
</div>
|
|
180
|
+
</section>
|
|
33
181
|
</main>
|
|
34
182
|
</body>
|
|
35
183
|
</html>
|
package/templates/page.ts
CHANGED
|
@@ -5,7 +5,7 @@ export const page = makeJayStackComponent<PageContract>().withSlowlyRender(async
|
|
|
5
5
|
return phaseOutput(
|
|
6
6
|
{
|
|
7
7
|
title: 'Welcome to Jay',
|
|
8
|
-
description: 'Your project is ready
|
|
8
|
+
description: 'Your project is ready — here are three ways to start building.',
|
|
9
9
|
},
|
|
10
10
|
{},
|
|
11
11
|
);
|
package/templates/tsconfig.json
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
{
|
|
2
|
-
"extends": "@jay-framework/dev-environment/examples/tsconfig.json",
|
|
3
2
|
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ES2022",
|
|
5
|
+
"lib": ["ES2022", "DOM"],
|
|
6
|
+
"moduleResolution": "node",
|
|
7
|
+
"allowSyntheticDefaultImports": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"useDefineForClassFields": true,
|
|
11
|
+
"resolveJsonModule": true,
|
|
12
|
+
"isolatedModules": true,
|
|
13
|
+
"noEmit": true,
|
|
4
14
|
"outDir": "dist",
|
|
15
|
+
"types": [],
|
|
5
16
|
},
|
|
6
17
|
"include": ["src"],
|
|
7
18
|
}
|