create-vista-app 0.3.0 → 0.3.3

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/bin/cli.js CHANGED
@@ -70,17 +70,24 @@ const explicitFlashpack = rawArgs.includes('--flashpack');
70
70
  const explicitDefaultEngine = rawArgs.includes('--default-engine');
71
71
  const explicitEngine = getFlagValue('--engine');
72
72
  const explicitPackageManager = getExplicitPackageManagerFromArgs(rawArgs);
73
+ const explicitSrcDir =
74
+ rawArgs.includes('--src-dir') || rawArgs.includes('--src')
75
+ ? true
76
+ : rawArgs.includes('--no-src-dir')
77
+ ? false
78
+ : undefined;
73
79
 
74
80
  if (process.argv.includes('--help') || process.argv.includes('-h')) {
75
81
  console.log(`
76
82
  Usage:
77
- ${usageCommand} [--typed-api] [--skip-install] [--no-git] [--yes] [--no-deploy-templates] [--engine <default|flashpack>] [--flashpack] [--default-engine] [--package-manager <npm|pnpm|yarn|bun>] [--npm|--pnpm|--yarn|--bun]
83
+ ${usageCommand} [--typed-api] [--skip-install] [--no-git] [--yes] [--no-deploy-templates] [--engine <default|flashpack>] [--flashpack] [--default-engine] [--src-dir|--no-src-dir] [--package-manager <npm|pnpm|yarn|bun>] [--npm|--pnpm|--yarn|--bun]
78
84
 
79
85
  Example:
80
86
  npx create-vista-app@latest my-vista-app
81
87
  npx create-vista-app@latest
82
88
  npx create-vista-app@latest my-vista-app --typed-api
83
89
  npx create-vista-app@latest my-vista-app --flashpack
90
+ npx create-vista-app@latest my-vista-app --src-dir
84
91
  npx create-vista-app@latest my-vista-app --package-manager pnpm
85
92
  `);
86
93
  process.exit(0);
@@ -91,6 +98,16 @@ if (explicitFlashpack && explicitDefaultEngine) {
91
98
  process.exit(1);
92
99
  }
93
100
 
101
+ if (rawArgs.includes('--src-dir') && rawArgs.includes('--no-src-dir')) {
102
+ console.error('Error: use only one of --src-dir or --no-src-dir.');
103
+ process.exit(1);
104
+ }
105
+
106
+ if (rawArgs.includes('--src') && rawArgs.includes('--no-src-dir')) {
107
+ console.error('Error: use only one of --src / --src-dir or --no-src-dir.');
108
+ process.exit(1);
109
+ }
110
+
94
111
  if (explicitEngine && !['default', 'flashpack'].includes(explicitEngine)) {
95
112
  console.error(`Error: unsupported engine "${explicitEngine}". Use "default" or "flashpack".`);
96
113
  process.exit(1);
@@ -124,12 +141,13 @@ async function resolveProjectName() {
124
141
  }
125
142
  return value;
126
143
  }
127
- async function confirmProceed(projectName, projectDir, engine, packageManager) {
144
+ async function confirmProceed(projectName, projectDir, engine, packageManager, useSrcDir) {
128
145
  if (assumeYes || !canPrompt) return true;
146
+ const layout = useSrcDir ? 'src/app' : 'app';
129
147
  const response = await prompts({
130
148
  type: 'confirm',
131
149
  name: 'proceed',
132
- message: `Create Vista app "${projectName}" in ${projectDir} (engine: ${engine}, package manager: ${packageManager})?`,
150
+ message: `Create Vista app "${projectName}" in ${projectDir} (engine: ${engine}, layout: ${layout}, package manager: ${packageManager})?`,
133
151
  initial: true,
134
152
  });
135
153
  return response.proceed !== false;
@@ -168,6 +186,25 @@ async function resolveEngineChoice() {
168
186
  return value;
169
187
  }
170
188
 
189
+ async function resolveSrcDirChoice() {
190
+ if (typeof explicitSrcDir === 'boolean') return explicitSrcDir;
191
+ if (assumeYes || !canPrompt) return false;
192
+
193
+ const response = await prompts({
194
+ type: 'confirm',
195
+ name: 'useSrcDir',
196
+ message: 'Would you like to use a `src/` directory?',
197
+ initial: false,
198
+ });
199
+
200
+ if (typeof response.useSrcDir !== 'boolean') {
201
+ console.log('Aborted.');
202
+ process.exit(0);
203
+ }
204
+
205
+ return response.useSrcDir;
206
+ }
207
+
171
208
  async function resolvePackageManagerChoice() {
172
209
  if (explicitPackageManager) return explicitPackageManager;
173
210
  if (assumeYes || !canPrompt) return detectedPackageManager;
@@ -277,15 +314,27 @@ function applyEngineToVistaConfig(projectDir, selectedEngine) {
277
314
  fs.writeFileSync(configPath, patched);
278
315
  }
279
316
 
280
- function applyReadmeSelections(projectDir, selectedEngine, useTypedApi) {
317
+ function applyReadmeSelections(projectDir, selectedEngine, useTypedApi, useSrcDir = false) {
281
318
  const readmePath = path.join(projectDir, 'README.md');
282
319
  if (!fs.existsSync(readmePath)) return;
283
320
 
284
- const source = fs.readFileSync(readmePath, 'utf8');
285
- const patched = source
321
+ let source = fs.readFileSync(readmePath, 'utf8');
322
+ source = source
286
323
  .replace(/__VISTA_ENGINE__/g, selectedEngine)
287
324
  .replace(/__VISTA_TYPED_API__/g, useTypedApi ? 'enabled' : 'disabled');
288
- fs.writeFileSync(readmePath, patched);
325
+
326
+ if (useSrcDir) {
327
+ source = source
328
+ .replace(/Add pages under `app`\./g, 'Add pages under `src/app`.')
329
+ .replace(/`app\/api\/\*\*\/route\.ts`/g, '`src/app/api/**/route.ts`')
330
+ .replace(/`app\/agents\//g, '`src/app/agents/')
331
+ .replace(
332
+ /```\napp\/\n├── root\.tsx[\s\S]*?vista\.config\.ts\n```/,
333
+ '```\nsrc/\n├── app/\n│ ├── root.tsx # Root layout\n│ ├── index.tsx # Home → /\n│ ├── globals.css\n│ └── about/page.tsx # → /about\n└── components/\npublic/\nvista.config.ts\n```'
334
+ );
335
+ }
336
+
337
+ fs.writeFileSync(readmePath, source);
289
338
  }
290
339
 
291
340
  function applyFlashpackStarterTheme(projectDir) {
@@ -295,6 +344,56 @@ function applyFlashpackStarterTheme(projectDir) {
295
344
  }
296
345
  }
297
346
 
347
+ /**
348
+ * Move app/ + components/ under src/ (Next-style layout).
349
+ * Call after all template overlays so flashpack/typed files move too.
350
+ */
351
+ function applySrcDirectoryLayout(projectDir) {
352
+ const srcDir = path.join(projectDir, 'src');
353
+ fs.mkdirSync(srcDir, { recursive: true });
354
+
355
+ const moves = [
356
+ ['app', path.join('src', 'app')],
357
+ ['components', path.join('src', 'components')],
358
+ ];
359
+
360
+ for (const [fromRel, toRel] of moves) {
361
+ const from = path.join(projectDir, fromRel);
362
+ const to = path.join(projectDir, toRel);
363
+ if (!fs.existsSync(from)) continue;
364
+ if (fs.existsSync(to)) {
365
+ // Merge: move children into existing target
366
+ for (const entry of fs.readdirSync(from)) {
367
+ const srcPath = path.join(from, entry);
368
+ const destPath = path.join(to, entry);
369
+ if (fs.existsSync(destPath)) {
370
+ fs.rmSync(destPath, { recursive: true, force: true });
371
+ }
372
+ fs.renameSync(srcPath, destPath);
373
+ }
374
+ fs.rmSync(from, { recursive: true, force: true });
375
+ } else {
376
+ fs.renameSync(from, to);
377
+ }
378
+ }
379
+
380
+ // Point @/* at src/* for the common import alias.
381
+ const tsconfigPath = path.join(projectDir, 'tsconfig.json');
382
+ if (fs.existsSync(tsconfigPath)) {
383
+ try {
384
+ const tsconfig = JSON.parse(fs.readFileSync(tsconfigPath, 'utf8'));
385
+ tsconfig.compilerOptions = tsconfig.compilerOptions || {};
386
+ tsconfig.compilerOptions.paths = {
387
+ ...(tsconfig.compilerOptions.paths || {}),
388
+ '@/*': ['./src/*'],
389
+ };
390
+ fs.writeFileSync(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}\n`);
391
+ } catch {
392
+ // Keep scaffold resilient if tsconfig is unexpected.
393
+ }
394
+ }
395
+ }
396
+
298
397
  function applyDeployTemplates(projectDir, options = {}) {
299
398
  const deployTemplateDir = path.join(__dirname, '../template/deploy');
300
399
  if (!fs.existsSync(deployTemplateDir)) return;
@@ -318,6 +417,7 @@ async function main() {
318
417
  const currentDir = process.cwd();
319
418
  const projectName = await resolveProjectName();
320
419
  const selectedEngine = await resolveEngineChoice();
420
+ const useSrcDir = await resolveSrcDirChoice();
321
421
  const selectedPackageManager = await resolvePackageManagerChoice();
322
422
  const projectDir = path.join(currentDir, projectName);
323
423
 
@@ -325,7 +425,8 @@ async function main() {
325
425
  projectName,
326
426
  projectDir,
327
427
  selectedEngine,
328
- selectedPackageManager
428
+ selectedPackageManager,
429
+ useSrcDir
329
430
  );
330
431
  if (!proceed) {
331
432
  console.log('Aborted.');
@@ -352,7 +453,7 @@ async function main() {
352
453
  }
353
454
 
354
455
  applyEngineToVistaConfig(projectDir, selectedEngine);
355
- applyReadmeSelections(projectDir, selectedEngine, useTypedApiStarter);
456
+ applyReadmeSelections(projectDir, selectedEngine, useTypedApiStarter, useSrcDir);
356
457
  if (selectedEngine === 'flashpack') {
357
458
  applyFlashpackStarterTheme(projectDir);
358
459
  }
@@ -361,6 +462,11 @@ async function main() {
361
462
  console.log('Added deployment templates (render.yaml, Dockerfile).');
362
463
  }
363
464
 
465
+ if (useSrcDir) {
466
+ applySrcDirectoryLayout(projectDir);
467
+ console.log('Using src/ directory layout (src/app, src/components).');
468
+ }
469
+
364
470
  console.log('Scaffolding complete.');
365
471
 
366
472
  // 3. Setup Dependencies (production-ready)
@@ -378,7 +484,7 @@ async function main() {
378
484
  react: '^19.0.0',
379
485
  'react-dom': '^19.0.0',
380
486
  'react-server-dom-webpack': '^19.0.0',
381
- vista: useLocal ? 'file:../packages/vista' : 'npm:@vistagenic/vista@latest',
487
+ vista: useLocal ? 'file:../packages/vista' : 'npm:@vistagenic/vista@0.3.3',
382
488
  'lucide-react': '^0.468.0',
383
489
  // CSS build (needed in production for vista build)
384
490
  postcss: '^8.0.0',
@@ -500,6 +606,7 @@ coverage/
500
606
  console.log(`
501
607
  ✨ Success! Created ${projectName} at ${projectDir}
502
608
  Engine: ${selectedEngine}
609
+ Layout: ${useSrcDir ? 'src/app' : 'app'}
503
610
  Package manager: ${selectedPackageManager}
504
611
 
505
612
  Get started by running:
@@ -525,6 +632,7 @@ module.exports = {
525
632
  applyEngineToVistaConfig,
526
633
  applyReadmeSelections,
527
634
  applyFlashpackStarterTheme,
635
+ applySrcDirectoryLayout,
528
636
  };
529
637
 
530
638
  if (require.main === module) {
package/package.json CHANGED
@@ -1,39 +1,39 @@
1
- {
2
- "name": "create-vista-app",
3
- "version": "0.3.0",
4
- "description": "Create Vista applications with one command",
5
- "bin": {
6
- "create-vista-app": "./bin/cli.js"
7
- },
8
- "repository": {
9
- "type": "git",
10
- "url": "https://github.com/Mantitup-Org/vista.git",
11
- "directory": "packages/create-vista-app"
12
- },
13
- "author": "Vista Team",
14
- "license": "MIT",
15
- "keywords": [
16
- "create",
17
- "vista",
18
- "react",
19
- "scaffold",
20
- "cli"
21
- ],
22
- "files": [
23
- "bin",
24
- "template",
25
- "template-typed"
26
- ],
27
- "dependencies": {
28
- "fs-extra": "^11.1.1",
29
- "picocolors": "^1.0.0",
30
- "prompts": "^2.4.2"
31
- },
32
- "devDependencies": {
33
- "@types/react": "^19.0.0",
34
- "@types/react-dom": "^19.0.0",
35
- "react": "^19.0.0",
36
- "react-dom": "^19.0.0"
37
- },
38
- "gitHead": "d1b9f715d6365d8e1f553e96b752fbce8d98df7c"
39
- }
1
+ {
2
+ "name": "create-vista-app",
3
+ "version": "0.3.3",
4
+ "description": "Create Vista applications with one command",
5
+ "bin": {
6
+ "create-vista-app": "./bin/cli.js"
7
+ },
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/Mantitup-Org/vista.git",
11
+ "directory": "packages/create-vista-app"
12
+ },
13
+ "author": "Vista Team",
14
+ "license": "MIT",
15
+ "keywords": [
16
+ "create",
17
+ "vista",
18
+ "react",
19
+ "scaffold",
20
+ "cli"
21
+ ],
22
+ "files": [
23
+ "bin",
24
+ "template",
25
+ "template-typed"
26
+ ],
27
+ "dependencies": {
28
+ "fs-extra": "^11.1.1",
29
+ "picocolors": "^1.0.0",
30
+ "prompts": "^2.4.2"
31
+ },
32
+ "devDependencies": {
33
+ "@types/react": "^19.0.0",
34
+ "@types/react-dom": "^19.0.0",
35
+ "react": "^19.0.0",
36
+ "react-dom": "^19.0.0"
37
+ },
38
+ "gitHead": "d1b9f715d6365d8e1f553e96b752fbce8d98df7c"
39
+ }
@@ -11,7 +11,8 @@ FROM node:20-alpine AS runner
11
11
  WORKDIR /app
12
12
  ENV NODE_ENV=production
13
13
  ENV PORT=3003
14
- COPY --from=builder /app/.vista ./.vista
15
14
  COPY --from=builder /app/package.json ./package.json
15
+ COPY --from=builder /app/node_modules ./node_modules
16
+ COPY --from=builder /app/.vista ./.vista
16
17
  EXPOSE 3003
17
18
  CMD ["node", ".vista/standalone/server.js"]
@@ -1,7 +1,22 @@
1
1
  [build]
2
2
  command = "npm run build"
3
3
  publish = ".vista/deploy/netlify"
4
+ functions = "netlify/functions"
5
+
6
+ [functions]
7
+ node_bundler = "none"
8
+ included_files = ["netlify/functions/.vista/**", "netlify/functions/node_modules/**"]
4
9
 
5
10
  [dev]
6
11
  command = "npm run dev"
7
12
  port = 3003
13
+
14
+ [[redirects]]
15
+ from = "/_vista/*"
16
+ to = "/_vista/:splat"
17
+ status = 200
18
+
19
+ [[redirects]]
20
+ from = "/*"
21
+ to = "/.netlify/functions/ssr"
22
+ status = 200
@@ -1,16 +1,7 @@
1
1
  {
2
2
  "version": 2,
3
3
  "buildCommand": "npm run build",
4
- "outputDirectory": ".vista",
5
- "framework": null,
6
4
  "installCommand": "npm install --legacy-peer-deps --no-audit --no-fund",
7
- "devCommand": "npm run dev",
8
- "routes": [
9
- { "handle": "filesystem" },
10
- { "src": "^/_vista/(.*)$", "dest": "/$1" },
11
- { "src": "^/(?:rsc|_rsc)/?$", "dest": "/static/pages/index.rsc" },
12
- { "src": "^/(?:rsc|_rsc)/(.+)$", "dest": "/static/pages/$1.rsc" },
13
- { "src": "^/$", "dest": "/static/pages/index.html" },
14
- { "src": "^/(.+)$", "dest": "/static/pages/$1.html" }
15
- ]
5
+ "framework": null,
6
+ "devCommand": "npm run dev"
16
7
  }
@@ -1,3 +1,19 @@
1
1
  name = "my-vista-app"
2
- compatibility_date = "2024-09-01"
3
- pages_build_output_dir = ".vista/deploy/cloudflare"
2
+ compatibility_date = "2026-09-20"
3
+ main = ".vista/deploy/cloudflare/worker.js"
4
+
5
+ [vars]
6
+ VISTA_RUNTIME = "standalone"
7
+
8
+ [[containers]]
9
+ class_name = "VistaSSR"
10
+ image = "./Dockerfile"
11
+ max_instances = 4
12
+
13
+ [[durable_objects.bindings]]
14
+ name = "VISTA_SSR"
15
+ class_name = "VistaSSR"
16
+
17
+ [[migrations]]
18
+ tag = "v1"
19
+ new_sqlite_classes = ["VistaSSR"]