create-vista-app 0.2.10 → 0.2.13

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
@@ -6,37 +6,95 @@ const { execSync } = require('child_process');
6
6
  const prompts = require('prompts');
7
7
 
8
8
  const usageCommand = 'npx create-vista-app@latest <project-name>';
9
-
10
- // Detect which package manager invoked us (npm, pnpm, yarn, bun)
11
- function detectPackageManager() {
12
- const ua = process.env.npm_config_user_agent || '';
13
- if (ua.startsWith('pnpm')) return 'pnpm';
14
- if (ua.startsWith('yarn')) return 'yarn';
15
- if (ua.startsWith('bun')) return 'bun';
16
- return 'npm';
17
- }
18
-
19
- const pkgManager = detectPackageManager();
9
+ const SUPPORTED_PACKAGE_MANAGERS = ['npm', 'pnpm', 'yarn', 'bun'];
10
+
11
+ // Detect which package manager invoked us (npm, pnpm, yarn, bun)
12
+ function normalizePackageManager(value) {
13
+ const normalized = String(value || '').trim().toLowerCase();
14
+ return SUPPORTED_PACKAGE_MANAGERS.includes(normalized) ? normalized : undefined;
15
+ }
16
+
17
+ function detectPackageManager(userAgent = process.env.npm_config_user_agent || '') {
18
+ const ua = String(userAgent || '');
19
+ if (ua.startsWith('pnpm')) return 'pnpm';
20
+ if (ua.startsWith('yarn')) return 'yarn';
21
+ if (ua.startsWith('bun')) return 'bun';
22
+ return 'npm';
23
+ }
24
+
25
+ function getExplicitPackageManagerFromArgs(args) {
26
+ const explicitValue = normalizePackageManager(getFlagValue('--package-manager'));
27
+ const explicitFlags = SUPPORTED_PACKAGE_MANAGERS.filter((manager) => args.includes(`--${manager}`));
28
+
29
+ if (explicitFlags.length > 1) {
30
+ console.error('Error: use only one package manager flag: --npm, --pnpm, --yarn, or --bun.');
31
+ process.exit(1);
32
+ }
33
+
34
+ if (getFlagValue('--package-manager') && !explicitValue) {
35
+ console.error(
36
+ `Error: unsupported package manager "${getFlagValue('--package-manager')}". Use npm, pnpm, yarn, or bun.`
37
+ );
38
+ process.exit(1);
39
+ }
40
+
41
+ if (explicitValue && explicitFlags.length > 0 && explicitFlags[0] !== explicitValue) {
42
+ console.error('Error: package manager flags conflict. Use only one package manager selector.');
43
+ process.exit(1);
44
+ }
45
+
46
+ return explicitValue || explicitFlags[0];
47
+ }
48
+
20
49
  const rawArgs = process.argv.slice(2);
21
50
  const useTypedApiStarter = rawArgs.includes('--typed-api') || rawArgs.includes('--typed');
22
51
  const skipInstall = rawArgs.includes('--skip-install');
23
52
  const skipGit = rawArgs.includes('--no-git');
24
53
  const assumeYes = rawArgs.includes('--yes') || rawArgs.includes('-y');
25
54
  const canPrompt = !!(process.stdin.isTTY && process.stdout.isTTY);
55
+ const detectedPackageManager = detectPackageManager();
56
+
57
+ function getFlagValue(flag) {
58
+ const index = rawArgs.indexOf(flag);
59
+ if (index !== -1) {
60
+ const next = rawArgs[index + 1];
61
+ if (next && !next.startsWith('-')) return next;
62
+ }
63
+ const inline = rawArgs.find((arg) => arg.startsWith(`${flag}=`));
64
+ if (inline) return inline.slice(flag.length + 1);
65
+ return undefined;
66
+ }
67
+
68
+ const explicitFlashpack = rawArgs.includes('--flashpack');
69
+ const explicitDefaultEngine = rawArgs.includes('--default-engine');
70
+ const explicitEngine = getFlagValue('--engine');
71
+ const explicitPackageManager = getExplicitPackageManagerFromArgs(rawArgs);
26
72
 
27
73
  if (process.argv.includes('--help') || process.argv.includes('-h')) {
28
74
  console.log(`
29
75
  Usage:
30
- ${usageCommand} [--typed-api] [--skip-install] [--no-git] [--yes]
76
+ ${usageCommand} [--typed-api] [--skip-install] [--no-git] [--yes] [--engine <default|flashpack>] [--flashpack] [--default-engine] [--package-manager <npm|pnpm|yarn|bun>] [--npm|--pnpm|--yarn|--bun]
31
77
 
32
78
  Example:
33
79
  npx create-vista-app@latest my-vista-app
34
80
  npx create-vista-app@latest
35
81
  npx create-vista-app@latest my-vista-app --typed-api
82
+ npx create-vista-app@latest my-vista-app --flashpack
83
+ npx create-vista-app@latest my-vista-app --package-manager pnpm
36
84
  `);
37
85
  process.exit(0);
38
86
  }
39
87
 
88
+ if (explicitFlashpack && explicitDefaultEngine) {
89
+ console.error('Error: use only one of --flashpack or --default-engine.');
90
+ process.exit(1);
91
+ }
92
+
93
+ if (explicitEngine && !['default', 'flashpack'].includes(explicitEngine)) {
94
+ console.error(`Error: unsupported engine "${explicitEngine}". Use "default" or "flashpack".`);
95
+ process.exit(1);
96
+ }
97
+
40
98
  async function resolveProjectName() {
41
99
  const args = rawArgs.filter((arg) => !arg.startsWith('-'));
42
100
  if (args[0]) return args[0];
@@ -65,17 +123,109 @@ async function resolveProjectName() {
65
123
  }
66
124
  return value;
67
125
  }
68
- async function confirmProceed(projectName, projectDir) {
126
+ async function confirmProceed(projectName, projectDir, engine, packageManager) {
69
127
  if (assumeYes || !canPrompt) return true;
70
128
  const response = await prompts({
71
129
  type: 'confirm',
72
130
  name: 'proceed',
73
- message: `Create Vista app "${projectName}" in ${projectDir}?`,
131
+ message: `Create Vista app "${projectName}" in ${projectDir} (engine: ${engine}, package manager: ${packageManager})?`,
74
132
  initial: true,
75
133
  });
76
134
  return response.proceed !== false;
77
135
  }
78
136
 
137
+ async function resolveEngineChoice() {
138
+ if (explicitEngine) return explicitEngine;
139
+ if (explicitFlashpack) return 'flashpack';
140
+ if (explicitDefaultEngine) return 'default';
141
+ if (assumeYes || !canPrompt) return 'default';
142
+
143
+ const response = await prompts({
144
+ type: 'select',
145
+ name: 'engine',
146
+ message: 'Select engine',
147
+ choices: [
148
+ {
149
+ title: 'default (recommended)',
150
+ value: 'default',
151
+ description: 'Stable webpack-first path',
152
+ },
153
+ {
154
+ title: 'flashpack',
155
+ value: 'flashpack',
156
+ description: 'Rust-first engine path',
157
+ },
158
+ ],
159
+ initial: 0,
160
+ });
161
+
162
+ const value = String(response.engine || '').trim();
163
+ if (!value) {
164
+ console.log('Aborted.');
165
+ process.exit(0);
166
+ }
167
+ return value;
168
+ }
169
+
170
+ async function resolvePackageManagerChoice() {
171
+ if (explicitPackageManager) return explicitPackageManager;
172
+ if (assumeYes || !canPrompt) return detectedPackageManager;
173
+
174
+ const response = await prompts({
175
+ type: 'select',
176
+ name: 'packageManager',
177
+ message: 'Select package manager',
178
+ choices: [
179
+ {
180
+ title: 'npm',
181
+ value: 'npm',
182
+ description: 'Widely available default',
183
+ },
184
+ {
185
+ title: 'pnpm',
186
+ value: 'pnpm',
187
+ description: 'Fast installs with shared store',
188
+ },
189
+ {
190
+ title: 'yarn',
191
+ value: 'yarn',
192
+ description: 'Classic Yarn workflow',
193
+ },
194
+ {
195
+ title: 'bun',
196
+ value: 'bun',
197
+ description: 'Fast Bun-based install/runtime',
198
+ },
199
+ ],
200
+ initial: Math.max(SUPPORTED_PACKAGE_MANAGERS.indexOf(detectedPackageManager), 0),
201
+ });
202
+
203
+ const value = normalizePackageManager(response.packageManager);
204
+ if (!value) {
205
+ console.log('Aborted.');
206
+ process.exit(0);
207
+ }
208
+
209
+ return value;
210
+ }
211
+
212
+ function getInstallCommand(packageManager) {
213
+ if (packageManager === 'yarn') return 'yarn';
214
+ if (packageManager === 'bun') return 'bun install';
215
+ return `${packageManager} install`;
216
+ }
217
+
218
+ function getRunCommand(packageManager) {
219
+ return packageManager === 'npm' ? 'npm run' : packageManager;
220
+ }
221
+
222
+ function getCreateCommand(packageManager) {
223
+ if (packageManager === 'pnpm') return 'pnpm create vista-app';
224
+ if (packageManager === 'yarn') return 'yarn create vista-app';
225
+ if (packageManager === 'bun') return 'bun create vista-app';
226
+ return 'npx create-vista-app@latest';
227
+ }
228
+
79
229
  function copyRecursiveSync(src, dest) {
80
230
  const exists = fs.existsSync(src);
81
231
  const stats = exists && fs.statSync(src);
@@ -90,13 +240,74 @@ function copyRecursiveSync(src, dest) {
90
240
  }
91
241
  }
92
242
 
243
+ function injectEngineBlock(source, selectedEngine) {
244
+ // Prefer preserving existing formatting when an engine block already exists.
245
+ if (/\bengine\s*:\s*\{[\s\S]*?\bvariant\s*:\s*['"][^'"]+['"]/m.test(source)) {
246
+ return source.replace(
247
+ /(\bengine\s*:\s*\{[\s\S]*?\bvariant\s*:\s*['"])([^'"]+)(['"])/m,
248
+ `$1${selectedEngine}$3`
249
+ );
250
+ }
251
+
252
+ // Replace existing scalar engine config
253
+ if (/\bengine\s*:\s*['"][^'"]+['"],?/m.test(source)) {
254
+ return source.replace(/\bengine\s*:\s*['"][^'"]+['"],?/m, `engine: '${selectedEngine}',`);
255
+ }
256
+
257
+ // Insert right after "const config = {"
258
+ const engineBlock = ` engine: {\n variant: '${selectedEngine}',\n },`;
259
+ const marker = 'const config = {';
260
+ const markerIndex = source.indexOf(marker);
261
+ if (markerIndex !== -1) {
262
+ const insertAt = markerIndex + marker.length;
263
+ return `${source.slice(0, insertAt)}\n${engineBlock}${source.slice(insertAt)}`;
264
+ }
265
+
266
+ // Fallback to a minimal config when template structure is unexpected
267
+ return `const config = {\n${engineBlock}\n};\n\nexport default config;\n`;
268
+ }
269
+
270
+ function applyEngineToVistaConfig(projectDir, selectedEngine) {
271
+ const configPath = path.join(projectDir, 'vista.config.ts');
272
+ if (!fs.existsSync(configPath)) return;
273
+
274
+ const source = fs.readFileSync(configPath, 'utf8');
275
+ const patched = injectEngineBlock(source, selectedEngine);
276
+ fs.writeFileSync(configPath, patched);
277
+ }
278
+
279
+ function applyReadmeSelections(projectDir, selectedEngine, useTypedApi) {
280
+ const readmePath = path.join(projectDir, 'README.md');
281
+ if (!fs.existsSync(readmePath)) return;
282
+
283
+ const source = fs.readFileSync(readmePath, 'utf8');
284
+ const patched = source
285
+ .replace(/__VISTA_ENGINE__/g, selectedEngine)
286
+ .replace(/__VISTA_TYPED_API__/g, useTypedApi ? 'enabled' : 'disabled');
287
+ fs.writeFileSync(readmePath, patched);
288
+ }
289
+
290
+ function applyFlashpackStarterTheme(projectDir) {
291
+ const flashTemplateDir = path.join(__dirname, 'flash-template');
292
+ if (fs.existsSync(flashTemplateDir)) {
293
+ copyRecursiveSync(flashTemplateDir, projectDir);
294
+ }
295
+ }
296
+
93
297
  async function main() {
94
298
  const useLocal = rawArgs.includes('--local');
95
299
  const currentDir = process.cwd();
96
300
  const projectName = await resolveProjectName();
301
+ const selectedEngine = await resolveEngineChoice();
302
+ const selectedPackageManager = await resolvePackageManagerChoice();
97
303
  const projectDir = path.join(currentDir, projectName);
98
304
 
99
- const proceed = await confirmProceed(projectName, projectDir);
305
+ const proceed = await confirmProceed(
306
+ projectName,
307
+ projectDir,
308
+ selectedEngine,
309
+ selectedPackageManager
310
+ );
100
311
  if (!proceed) {
101
312
  console.log('Aborted.');
102
313
  process.exit(0);
@@ -121,6 +332,12 @@ async function main() {
121
332
  console.log('Added typed API starter files.');
122
333
  }
123
334
 
335
+ applyEngineToVistaConfig(projectDir, selectedEngine);
336
+ applyReadmeSelections(projectDir, selectedEngine, useTypedApiStarter);
337
+ if (selectedEngine === 'flashpack') {
338
+ applyFlashpackStarterTheme(projectDir);
339
+ }
340
+
124
341
  console.log('Scaffolding complete.');
125
342
 
126
343
  // 3. Setup Dependencies (production-ready)
@@ -143,6 +360,7 @@ async function main() {
143
360
  'postcss-cli': '^11.0.0',
144
361
  tailwindcss: '^4.0.0',
145
362
  '@tailwindcss/postcss': '^4.0.0',
363
+ webpack: '^5.90.0',
146
364
  // Node 20+ SSR compatibility
147
365
  '@swc-node/register': '^1.9.0',
148
366
  '@swc/core': '^1.4.0',
@@ -165,7 +383,7 @@ node_modules/
165
383
  # Build outputs
166
384
  dist/
167
385
  .vista/
168
- .next/
386
+ .flash/
169
387
  out/
170
388
 
171
389
  # Rust artifacts
@@ -235,9 +453,11 @@ coverage/
235
453
  }
236
454
 
237
455
  // 6. Install Dependencies
238
- const installCmd = pkgManager === 'yarn' ? 'yarn' : `${pkgManager} install`;
456
+ const installCmd = getInstallCommand(selectedPackageManager);
239
457
  if (!skipInstall) {
240
- console.log(`\nInstalling dependencies with ${pkgManager}... This may take a moment.\n`);
458
+ console.log(
459
+ `\nInstalling dependencies with ${selectedPackageManager}... This may take a moment.\n`
460
+ );
241
461
  try {
242
462
  execSync(installCmd, { cwd: projectDir, stdio: 'inherit' });
243
463
  console.log(`\n✓ Dependencies installed successfully!`);
@@ -250,18 +470,13 @@ coverage/
250
470
  console.log('\nSkipped dependency installation (--skip-install).');
251
471
  }
252
472
 
253
- const runCmd = pkgManager === 'npm' ? 'npm run' : pkgManager;
254
- const createCmd =
255
- pkgManager === 'pnpm'
256
- ? 'pnpm create vista-app'
257
- : pkgManager === 'yarn'
258
- ? 'yarn create vista-app'
259
- : pkgManager === 'bun'
260
- ? 'bun create vista-app'
261
- : 'npx create-vista-app@latest';
473
+ const runCmd = getRunCommand(selectedPackageManager);
474
+ const createCmd = getCreateCommand(selectedPackageManager);
262
475
 
263
476
  console.log(`
264
477
  ✨ Success! Created ${projectName} at ${projectDir}
478
+ Engine: ${selectedEngine}
479
+ Package manager: ${selectedPackageManager}
265
480
 
266
481
  Get started by running:
267
482
 
@@ -275,7 +490,22 @@ Happy Hacking! 🚀
275
490
  `);
276
491
  }
277
492
 
278
- main().catch((error) => {
279
- console.error('create-vista-app failed:', error);
280
- process.exit(1);
281
- });
493
+ module.exports = {
494
+ main,
495
+ detectPackageManager,
496
+ normalizePackageManager,
497
+ getInstallCommand,
498
+ getRunCommand,
499
+ getCreateCommand,
500
+ injectEngineBlock,
501
+ applyEngineToVistaConfig,
502
+ applyReadmeSelections,
503
+ applyFlashpackStarterTheme,
504
+ };
505
+
506
+ if (require.main === module) {
507
+ main().catch((error) => {
508
+ console.error('create-vista-app failed:', error);
509
+ process.exit(1);
510
+ });
511
+ }
@@ -0,0 +1,91 @@
1
+ import Image from 'vista/image';
2
+
3
+ export default function Index() {
4
+ return (
5
+ <main className="relative flex min-h-[100dvh] items-center overflow-hidden bg-black text-zinc-100 selection:bg-primary/20 selection:text-primary">
6
+ <div className="pointer-events-none absolute top-0 right-0 h-[380px] w-[380px] translate-x-1/4 -translate-y-1/4 rounded-full bg-primary opacity-20 blur-[110px]" />
7
+ <div className="pointer-events-none absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-primary/45 to-transparent" />
8
+
9
+ <section className="relative z-10 mx-auto w-full max-w-5xl px-6 py-10 md:px-10 lg:px-12">
10
+ <div className="grid items-center gap-10 lg:grid-cols-[minmax(0,1.05fr)_minmax(320px,0.95fr)]">
11
+ <div className="max-w-2xl">
12
+ <div className="inline-flex items-center gap-2 rounded-full border border-primary/30 bg-primary/10 px-4 py-2 text-[11px] font-medium uppercase tracking-[0.28em] text-primary">
13
+ Flashpack starter
14
+ </div>
15
+ <h1 className="mt-6 max-w-2xl text-balance text-[clamp(2.9rem,5.8vw,5rem)] font-semibold leading-[0.94] tracking-tight text-zinc-50">
16
+ Stay in flow while the app keeps moving.
17
+ </h1>
18
+ <p className="mt-5 max-w-xl text-pretty text-base leading-8 text-zinc-400 md:text-lg">
19
+ Flashpack keeps the Vista workflow familiar, but gives you a tighter edit loop, clearer runtime traces,
20
+ and a cleaner place to inspect what happened during dev, build, and start.
21
+ </p>
22
+
23
+ <div className="mt-6 flex flex-wrap items-center gap-3 text-sm text-zinc-300">
24
+ <span className="rounded-full border border-zinc-800 bg-zinc-950/80 px-4 py-2">
25
+ Same <code>vista dev</code> workflow
26
+ </span>
27
+ <span className="rounded-full border border-zinc-800 bg-zinc-950/80 px-4 py-2">
28
+ Traceable output in <code>.flash/</code>
29
+ </span>
30
+ </div>
31
+
32
+ <div className="mt-7 flex flex-wrap items-center gap-3 text-sm text-zinc-400">
33
+ <span>
34
+ Edit <code className="rounded bg-zinc-900 px-2 py-1 text-zinc-200">app/index.tsx</code> to shape this
35
+ screen.
36
+ </span>
37
+ <a
38
+ href="https://vista.xyz/docs/env"
39
+ className="rounded-full border border-zinc-800 bg-zinc-950/70 px-4 py-2 text-zinc-200 transition-colors hover:border-primary/50 hover:text-primary"
40
+ >
41
+ Read the env guide
42
+ </a>
43
+ </div>
44
+ </div>
45
+
46
+ <aside className="space-y-4">
47
+ <div className="rounded-[1.9rem] border border-zinc-800/80 bg-zinc-950/60 p-6 shadow-[0_28px_75px_rgba(0,0,0,0.45)] backdrop-blur-sm">
48
+ <div className="mb-6 flex items-center justify-between text-[11px] uppercase tracking-[0.24em] text-zinc-500">
49
+ <span>Vista</span>
50
+ <span>Flashpack</span>
51
+ </div>
52
+ <div className="flex justify-center">
53
+ <Image
54
+ src="/vista.svg"
55
+ alt="Vista Logo"
56
+ width={600}
57
+ height={600}
58
+ priority
59
+ unoptimized
60
+ className="h-auto w-[210px] invert opacity-95 sm:w-[250px] lg:w-[280px]"
61
+ />
62
+ </div>
63
+ </div>
64
+
65
+ <div className="grid gap-4 sm:grid-cols-2">
66
+ <article className="rounded-[1.6rem] border border-zinc-800/80 bg-zinc-950/45 p-5">
67
+ <p className="text-sm font-medium uppercase tracking-[0.22em] text-primary">Quicker feedback</p>
68
+ <p className="mt-3 text-sm leading-7 text-zinc-400">
69
+ Keep editing without feeling pushed into long restart cycles every time the route tree shifts.
70
+ </p>
71
+ </article>
72
+ <article className="rounded-[1.6rem] border border-zinc-800/80 bg-zinc-950/45 p-5">
73
+ <p className="text-sm font-medium uppercase tracking-[0.22em] text-primary">Readable artifacts</p>
74
+ <p className="mt-3 text-sm leading-7 text-zinc-400">
75
+ Open graph, runtime, and log output when you want to understand how the engine moved.
76
+ </p>
77
+ </article>
78
+ </div>
79
+
80
+ <div className="rounded-[1.6rem] border border-zinc-800/80 bg-zinc-950/45 p-5">
81
+ <p className="text-sm font-medium uppercase tracking-[0.22em] text-primary">Why teams pick it</p>
82
+ <p className="mt-3 text-sm leading-7 text-zinc-400">
83
+ Flashpack keeps the command surface stable while making build artifacts and dev behavior easier to read.
84
+ </p>
85
+ </div>
86
+ </aside>
87
+ </div>
88
+ </section>
89
+ </main>
90
+ );
91
+ }
@@ -0,0 +1,32 @@
1
+ import type { Metadata } from 'vista';
2
+ import { Geist, Geist_Mono } from 'vista/font/google';
3
+ import './globals.css';
4
+
5
+ const geistSans = Geist({
6
+ variable: '--font-geist-sans',
7
+ subsets: ['latin'],
8
+ });
9
+
10
+ const geistMono = Geist_Mono({
11
+ variable: '--font-geist-mono',
12
+ subsets: ['latin'],
13
+ });
14
+
15
+ export const metadata: Metadata = {
16
+ title: 'My Vista App',
17
+ description: 'Built with Vista Framework',
18
+ };
19
+
20
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
21
+ return (
22
+ <html lang="en" suppressHydrationWarning>
23
+ <head />
24
+ <body
25
+ className={`${geistSans.variable} ${geistMono.variable} min-h-screen overflow-x-hidden bg-black text-zinc-100 antialiased`}
26
+ suppressHydrationWarning
27
+ >
28
+ {children}
29
+ </body>
30
+ </html>
31
+ );
32
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-vista-app",
3
- "version": "0.2.10",
3
+ "version": "0.2.13",
4
4
  "description": "Create Vista applications with one command",
5
5
  "bin": {
6
6
  "create-vista-app": "./bin/cli.js"
@@ -1,6 +1,10 @@
1
- # My Vista App
2
-
3
- Built with [Vista.js](https://github.com/vistagen/Vista-Js) — the React framework powered by Rust.
1
+ # My Vista App
2
+
3
+ Built with [Vista.js](https://github.com/vistagen/Vista-Js) — the React framework powered by Rust.
4
+
5
+ Selected engine for this app: `__VISTA_ENGINE__`
6
+
7
+ Typed API starter: `__VISTA_TYPED_API__`
4
8
 
5
9
  ## Getting Started
6
10
 
@@ -41,17 +45,42 @@ vista.config.ts # Framework configuration
41
45
  - **`'use client'`** — Add this directive to make a component interactive (client-side).
42
46
  - **Server Components** — All components are server components by default (zero JS sent to browser).
43
47
 
44
- ## Available Commands
48
+ ## Available Commands
45
49
 
46
50
  | Command | Description |
47
51
  | ------------- | --------------------------------- |
48
- | `vista dev` | Start dev server with live-reload |
49
- | `vista build` | Create production build |
50
- | `vista start` | Start production server |
52
+ | `vista dev` | Start dev server with the engine selected in `vista.config.ts` |
53
+ | `vista build` | Create production build with the engine selected in `vista.config.ts` |
54
+ | `vista start` | Start production server with the engine selected in `vista.config.ts` |
51
55
  | `vista g api-init` | Generate typed API starter files |
52
56
  | `vista g router <name>` | Generate a typed router file |
53
57
  | `vista g procedure <name> [get\|post]` | Generate a typed procedure file |
54
58
 
59
+ ## Engine Selection
60
+
61
+ `create-vista-app` supports both engine variants:
62
+
63
+ - `default` (webpack path)
64
+ - `flashpack` (Rust-first path)
65
+
66
+ You can choose at scaffold time, but the generated app still uses the same `npm run dev`, `npm run build`, and `npm run start` scripts. Vista reads the selected engine from `vista.config.ts`.
67
+
68
+ Example:
69
+
70
+ ```bash
71
+ npx create-vista-app@latest my-vista-app --engine flashpack
72
+ ```
73
+
74
+ The generated config looks like:
75
+
76
+ ```ts
77
+ engine: {
78
+ variant: 'flashpack'
79
+ }
80
+ ```
81
+
82
+ Flashpack engine runtime/cache artifacts are stored in `.flash/`.
83
+
55
84
  ## Typed API Rollback
56
85
 
57
86
  Typed API is experimental and can be disabled anytime from `vista.config.ts`:
@@ -11,14 +11,16 @@
11
11
  }
12
12
 
13
13
  html {
14
- overflow-y: scroll;
14
+ min-height: 100%;
15
+ overflow-x: hidden;
16
+ scrollbar-gutter: stable;
15
17
  }
16
18
 
17
19
  :root {
18
- --background: #0a0a0a;
19
- --foreground: #ededed;
20
+ --background: #f3e8d8;
21
+ --foreground: #171717;
20
22
  --primary: #ff4c30;
21
- color-scheme: dark;
23
+ color-scheme: light;
22
24
  }
23
25
 
24
26
  :root.light {
@@ -36,7 +38,10 @@ html {
36
38
  }
37
39
 
38
40
  body {
41
+ min-height: 100vh;
42
+ margin: 0;
39
43
  background: var(--background);
40
44
  color: var(--foreground);
41
45
  font-family: var(--font-geist-sans), Arial, Helvetica, sans-serif;
46
+ overflow-x: hidden;
42
47
  }
@@ -2,23 +2,65 @@ import Image from 'vista/image';
2
2
 
3
3
  export default function Index() {
4
4
  return (
5
- <main className="flex min-h-screen flex-col items-center justify-center bg-white dark:bg-black transition-colors duration-200">
6
- <div className="-mt-20 mb-10 relative border border-dashed border-gray-300 dark:border-neutral-700 p-10">
7
- <div className="absolute -top-0 -left-0 -translate-x-1/2 -translate-y-1/2 w-24 h-24 border border-dashed border-gray-300 dark:border-neutral-700 rounded-full" />
8
- <div className="absolute -bottom-0 -right-0 translate-x-1/2 translate-y-1/2 w-24 h-24 border border-dashed border-gray-300 dark:border-neutral-700 rounded-full" />
9
- <Image
10
- src="/vista.svg"
11
- alt="Vista Logo"
12
- width={600}
13
- height={600}
14
- unoptimized
15
- className="dark:invert"
16
- />
17
- </div>
5
+ <main className="flex min-h-[100dvh] items-center justify-center bg-[#f7f4ee] px-6 py-10 text-zinc-950 selection:bg-primary/15 selection:text-primary md:px-10">
6
+ <section className="w-full max-w-4xl rounded-[2rem] border border-zinc-900/10 bg-white/85 p-7 shadow-[0_24px_80px_rgba(27,18,7,0.08)] backdrop-blur-sm md:p-10">
7
+ <div className="grid items-center gap-10 lg:grid-cols-[minmax(0,1.05fr)_minmax(300px,0.95fr)]">
8
+ <div className="max-w-xl">
9
+ <div className="inline-flex items-center gap-2 rounded-full border border-zinc-900/10 bg-[#fbf7f1] px-4 py-2 text-[11px] font-medium uppercase tracking-[0.28em] text-primary">
10
+ Vista starter
11
+ </div>
12
+ <h1 className="mt-6 max-w-xl text-balance text-[clamp(2.6rem,5vw,4.6rem)] font-semibold tracking-tight text-zinc-950">
13
+ Start by editing <code className="font-mono text-[0.82em]">app/index.tsx</code>.
14
+ </h1>
15
+ <p className="mt-5 max-w-lg text-pretty text-base leading-8 text-zinc-700 md:text-lg">
16
+ The default starter keeps the first screen calm: one route, a clean app shell, and the core Vista flow
17
+ already wired so you can start building instead of cleaning up scaffolding.
18
+ </p>
18
19
 
19
- <h1 className="max-w-xs sm:max-w-none text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50 text-center">
20
- To get started, edit the index.tsx file.
21
- </h1>
22
- </main>
23
- );
24
- }
20
+ <div className="mt-7 flex flex-wrap items-center gap-3">
21
+ <a
22
+ href="https://vista.xyz/docs/env"
23
+ className="inline-flex items-center justify-center rounded-full bg-zinc-950 px-5 py-3 text-sm font-medium text-white transition-colors hover:bg-zinc-800"
24
+ >
25
+ Open env guide
26
+ </a>
27
+ <span className="rounded-full border border-zinc-900/10 bg-[#fbf7f1] px-4 py-3 text-sm text-zinc-700">
28
+ Engine lives in <code>vista.config.ts</code>
29
+ </span>
30
+ </div>
31
+ </div>
32
+
33
+ <aside className="rounded-[1.7rem] border border-zinc-900/10 bg-[#fcfaf6] p-6">
34
+ <div className="flex items-center justify-between text-[11px] uppercase tracking-[0.24em] text-zinc-500">
35
+ <span>Default engine</span>
36
+ <span>Vista</span>
37
+ </div>
38
+
39
+ <div className="mt-6 flex justify-center">
40
+ <Image
41
+ src="/vista.svg"
42
+ alt="Vista Logo"
43
+ width={600}
44
+ height={600}
45
+ priority
46
+ unoptimized
47
+ className="h-auto w-[220px] opacity-95 sm:w-[250px]"
48
+ />
49
+ </div>
50
+
51
+ <div className="mt-7 space-y-3 text-sm text-zinc-700">
52
+ <div className="rounded-2xl border border-zinc-900/8 bg-white p-4">
53
+ <p className="font-medium text-zinc-950">Stable default path</p>
54
+ <p className="mt-2 leading-7">Use the familiar <code>vista dev</code>, <code>vista build</code>, and <code>vista start</code> flow from day one.</p>
55
+ </div>
56
+ <div className="rounded-2xl border border-zinc-900/8 bg-white p-4">
57
+ <p className="font-medium text-zinc-950">Config-first workflow</p>
58
+ <p className="mt-2 leading-7">Adjust engine and framework behavior in <code>vista.config.ts</code> instead of rewriting scripts.</p>
59
+ </div>
60
+ </div>
61
+ </aside>
62
+ </div>
63
+ </section>
64
+ </main>
65
+ );
66
+ }
@@ -19,9 +19,14 @@ export const metadata: Metadata = {
19
19
 
20
20
  export default function RootLayout({ children }: { children: React.ReactNode }) {
21
21
  return (
22
- <html lang="en">
22
+ <html lang="en" suppressHydrationWarning>
23
23
  <head />
24
- <body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>{children}</body>
24
+ <body
25
+ className={`${geistSans.variable} ${geistMono.variable} min-h-screen overflow-x-hidden antialiased bg-background text-foreground`}
26
+ suppressHydrationWarning
27
+ >
28
+ {children}
29
+ </body>
25
30
  </html>
26
31
  );
27
32
  }
@@ -2,7 +2,7 @@
2
2
  /// <reference types="vista/image/image-types/global" />
3
3
 
4
4
  // NOTE: This file should not be edited
5
- // see https://vista.dev/docs/env for more information.
5
+ // see https://vista.xyz/docs/env for more information.
6
6
 
7
7
  declare module '*.module.css' {
8
8
  const classes: { readonly [key: string]: string };
@@ -1,4 +1,8 @@
1
1
  const config = {
2
+ engine: {
3
+ // Engine options: 'default' or 'flashpack'
4
+ variant: 'default',
5
+ },
2
6
  images: {
3
7
  domains: ['example.com'],
4
8
  // For static hosts where the /_vista/image endpoint is not available:
@@ -1,4 +1,8 @@
1
1
  const config = {
2
+ engine: {
3
+ // Engine options: 'default' or 'flashpack'
4
+ variant: 'default',
5
+ },
2
6
  images: {
3
7
  domains: ['example.com'],
4
8
  },