void 0.7.12 → 0.7.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/AGENT_PROMPT.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ## Void
2
2
 
3
- This project uses [Void](https://void.cloud) — a fullstack Vite plugin + deployment platform for Cloudflare. `voidPlugin()` in `vite.config.ts` gives you file-based API routing on Hono (`routes/`), Inertia-inspired server-rendered pages with co-located loaders/actions (`pages/` + `@void/vue` or `@void/react`), auto-provisioned D1/KV/R2 bindings, first-class Drizzle ORM integration (schema in `db/schema.ts` -> `void/db` Drizzle instance -> typed routes -> typed fetch client), built-in auth, queues, cron jobs, edge caching (ISR), and one-command deploys via `npx void deploy`. For first-time setup, prefer `npx void init`; in an empty directory, install `void` first and let the interactive flow scaffold the starter, add the matching framework adapter, configure project files, handle auth, and link or create the deploy project before the first deploy. In an existing app, `void init` configures Void in place by adding missing Vite scripts and creating or patching `vite.config.*` with `voidPlugin()`. Use `void` and `@void/*` package names in source code and package manifests.
3
+ This project uses [Void](https://void.cloud) — a fullstack Vite plugin + deployment platform for Cloudflare. `voidPlugin()` in `vite.config.ts` gives you file-based API routing on Hono (`routes/`), Inertia-inspired server-rendered pages with co-located loaders/actions (`pages/` + `@void/vue` or `@void/react`), auto-provisioned D1/KV/R2 bindings, first-class Drizzle ORM integration (schema in `db/schema.ts` -> `void/db` Drizzle instance -> typed routes -> typed fetch client), built-in auth, queues, cron jobs, edge caching (ISR), and one-command deploys via `npx void deploy`. For first-time setup, prefer `npx void init`; in an empty directory, install `void` first and let the interactive flow scaffold the starter with Vite+ by default, add the matching framework adapter, configure project files, handle auth, and link or create the deploy project before the first deploy. In an existing app, `void init` configures Void in place by adding missing Vite scripts and creating or patching `vite.config.*` with `voidPlugin()`. Use `void` and `@void/*` package names in source code and package manifests.
4
4
 
5
5
  Database: define Drizzle tables in `db/schema.ts`, import `db` from `void/db` and tables from `@schema`. Use `void db push` for prototyping, `void db generate` for production migrations. `drizzle-orm` and `drizzle-kit` ship with void (no extra install). Migrations live in `db/migrations/`.
6
6
 
package/README.md CHANGED
@@ -21,7 +21,7 @@ Install the Void CLI:
21
21
  npm install -D void
22
22
  ```
23
23
 
24
- If you run `void init` in an empty directory, the scaffold flow adds the matching Pages adapter and Vite dependencies for you.
24
+ If you run `void init` in an empty directory, the scaffold flow adds the matching Pages adapter and Vite+ by default.
25
25
 
26
26
  Then run `npx void init`. In an empty directory, the full interactive flow can scaffold a starter, configure local project files, log you in, and link or create your Void project so the next step is just `npx void deploy`. In an existing app, it configures Void in place by adding missing Vite scripts and creating or patching `vite.config.*` with `voidPlugin()`.
27
27
 
@@ -82,7 +82,7 @@ There is Vinext-specific source in the repo, but it is intentionally on hold and
82
82
 
83
83
  ## Documentation
84
84
 
85
- Full docs live at [void.cloud/docs](https://void.cloud/docs).
85
+ Full docs live at [void.cloud/guide](https://void.cloud/guide).
86
86
 
87
87
  ## License
88
88
 
package/dist/cli/cli.mjs CHANGED
@@ -1539,7 +1539,7 @@ else if (command === "prepare") {
1539
1539
  });
1540
1540
  } else if (command === "init") {
1541
1541
  const root = process.cwd();
1542
- import("../init-iIiQWzyB.mjs").then(({ runInitCommand, parseInitArgs }) => {
1542
+ import("../init-Br5DTaG7.mjs").then(({ runInitCommand, parseInitArgs }) => {
1543
1543
  let initArgs;
1544
1544
  try {
1545
1545
  initArgs = parseInitArgs(args.slice(1));
@@ -1628,7 +1628,7 @@ else if (command === "-v" || command === "--version") {
1628
1628
  const root = process.cwd();
1629
1629
  switch (cmd) {
1630
1630
  case "init": {
1631
- const { runInitCommand, parseInitArgs } = await import("../init-iIiQWzyB.mjs");
1631
+ const { runInitCommand, parseInitArgs } = await import("../init-Br5DTaG7.mjs");
1632
1632
  await runInitCommand(root, parseInitArgs([]));
1633
1633
  return;
1634
1634
  }
@@ -1,7 +1,7 @@
1
1
  import { a as join, i as isAbsolute, n as dirname, o as relative, s as resolve, t as basename } from "./pathe.M-eThtNZ-D-kmWkCS.mjs";
2
2
  import { n as cliTitle } from "./output-D3g5otMC.mjs";
3
3
  import { c as getToken, n as PlatformClient, u as isStagingMode } from "./client-C_DYiXeu.mjs";
4
- import { _ as me, c as R, g as ge, i as Ee, u as Se, v as ue, x as q, y as ye } from "./dist-D2L3_KTK.mjs";
4
+ import { _ as me, c as R, g as ge, i as Ee, l as Re, u as Se, v as ue, x as q, y as ye } from "./dist-D2L3_KTK.mjs";
5
5
  import { a as writeProjectConfig, r as readProjectConfig } from "./project-DhB4A8_g.mjs";
6
6
  import { c as getDatabaseDialect, f as readConfig } from "./config-CeRQg3Lz.mjs";
7
7
  import { r as detectFramework } from "./plugin-inference-BexV6LL3.mjs";
@@ -208,6 +208,16 @@ const SCAFFOLD_BASE_DEV_DEPENDENCIES = {
208
208
  vite: "^8.0.10",
209
209
  typescript: "^5.9.3"
210
210
  };
211
+ const SCAFFOLD_VITE_PLUS_DEV_DEPENDENCIES = { "vite-plus": "^0.1.21" };
212
+ const SCAFFOLD_TOOLCHAIN_OPTIONS = [{
213
+ value: "vite-plus",
214
+ label: "Vite+",
215
+ hint: "Uses the Vite+ toolchain and vp commands."
216
+ }, {
217
+ value: "vite",
218
+ label: "Vite",
219
+ hint: "Uses plain Vite commands without Vite+."
220
+ }];
211
221
  const REACT_SCAFFOLD_COMPILER_DEV_DEPENDENCIES = {
212
222
  "@rolldown/plugin-babel": "^0.2.3",
213
223
  "@vitejs/plugin-react": "^6.0.1",
@@ -294,7 +304,7 @@ function getScaffoldTsconfigCompilerOptions(framework) {
294
304
  return framework ? { ...SCAFFOLD_FRAMEWORKS[framework].tsconfigCompilerOptions } : {};
295
305
  }
296
306
  function createPagesStarterTemplate(options) {
297
- const { framework, starterMode, voidPackageSpec, adapterPackageSpec } = options;
307
+ const { framework, starterMode, toolchain = "vite", voidPackageSpec, adapterPackageSpec } = options;
298
308
  const config = SCAFFOLD_FRAMEWORKS[framework];
299
309
  const files = {
300
310
  "vite.config.ts": getViteConfig(framework, config),
@@ -308,9 +318,9 @@ function createPagesStarterTemplate(options) {
308
318
  }
309
319
  return {
310
320
  scripts: {
311
- dev: "vite",
312
- build: "vite build",
313
- preview: "vite preview"
321
+ dev: toolchain === "vite-plus" ? "vp dev" : "vite",
322
+ build: toolchain === "vite-plus" ? "vp build" : "vite build",
323
+ preview: toolchain === "vite-plus" ? "vp preview" : "vite preview"
314
324
  },
315
325
  dependencies: {
316
326
  ...SCAFFOLD_BASE_DEPENDENCIES,
@@ -319,6 +329,7 @@ function createPagesStarterTemplate(options) {
319
329
  devDependencies: {
320
330
  void: voidPackageSpec,
321
331
  ...SCAFFOLD_BASE_DEV_DEPENDENCIES,
332
+ ...toolchain === "vite-plus" ? SCAFFOLD_VITE_PLUS_DEV_DEPENDENCIES : {},
322
333
  [config.adapterPackage]: adapterPackageSpec,
323
334
  ...config.devDependencies
324
335
  },
@@ -823,6 +834,53 @@ function isScaffoldableEmptyProject(root) {
823
834
  if (Object.keys(scripts).some((name) => name !== "test")) return false;
824
835
  return true;
825
836
  }
837
+ function shouldPromptForInitLocation(root) {
838
+ if (isScaffoldableEmptyProject(root)) return false;
839
+ if (existsSync(join(root, "package.json"))) return false;
840
+ if (existsSync(join(root, VOID_CONFIG_FILE))) return false;
841
+ return findViteConfig(root) === void 0;
842
+ }
843
+ function validateSubfolderName(root, value) {
844
+ const name = value?.trim() ?? "";
845
+ if (!name) return "Enter a folder name.";
846
+ if (name === "." || name === ".." || name.includes("/") || name.includes("\\")) return "Enter a single folder name, not a path.";
847
+ if (existsSync(join(root, name))) return "That folder already exists.";
848
+ }
849
+ async function resolveInitRoot(root) {
850
+ if (!shouldPromptForInitLocation(root)) return root;
851
+ const choice = await Ee({
852
+ message: "This folder is not empty. Where should Void initialize?",
853
+ initialValue: "subfolder",
854
+ options: [{
855
+ value: "subfolder",
856
+ label: "Create a new subfolder",
857
+ hint: "Scaffold a new app inside this directory."
858
+ }, {
859
+ value: "current",
860
+ label: "Continue here",
861
+ hint: "Add package.json, vite.config.ts, and Void files to this directory."
862
+ }]
863
+ });
864
+ if (q(choice)) {
865
+ me("Setup cancelled.");
866
+ process.exit(0);
867
+ }
868
+ if (choice === "current") return root;
869
+ const folder = await Re({
870
+ message: "New project folder name:",
871
+ placeholder: "my-void-app",
872
+ initialValue: "my-void-app",
873
+ validate: (value) => validateSubfolderName(root, value)
874
+ });
875
+ if (q(folder)) {
876
+ me("Setup cancelled.");
877
+ process.exit(0);
878
+ }
879
+ const nextRoot = join(root, folder.trim());
880
+ mkdirSync(nextRoot, { recursive: true });
881
+ R.info(`Scaffolding in ${nextRoot}`);
882
+ return nextRoot;
883
+ }
826
884
  function parsePackageManagerField(pkg) {
827
885
  if (!pkg || typeof pkg !== "object") return;
828
886
  const raw = pkg.packageManager;
@@ -1566,6 +1624,18 @@ async function promptStarterMode() {
1566
1624
  }
1567
1625
  return choice;
1568
1626
  }
1627
+ async function promptScaffoldToolchain() {
1628
+ const choice = await Ee({
1629
+ message: "Choose a Pages scaffold toolchain:",
1630
+ initialValue: "vite-plus",
1631
+ options: [...SCAFFOLD_TOOLCHAIN_OPTIONS]
1632
+ });
1633
+ if (q(choice)) {
1634
+ me("Setup cancelled.");
1635
+ process.exit(0);
1636
+ }
1637
+ return choice;
1638
+ }
1569
1639
  async function promptScaffoldFramework() {
1570
1640
  const choice = await Ee({
1571
1641
  message: "Choose a Pages framework to scaffold:",
@@ -1850,11 +1920,12 @@ function generateStarterMigration(root, starterMode) {
1850
1920
  }
1851
1921
  R.success("Generated initial Drizzle migration");
1852
1922
  }
1853
- function scaffoldPagesApp(root, packageManager, framework, starterMode) {
1923
+ function scaffoldPagesApp(root, packageManager, framework, starterMode, toolchain) {
1854
1924
  const packageJsonPath = join(root, "package.json");
1855
1925
  const template = createPagesStarterTemplate({
1856
1926
  framework,
1857
1927
  starterMode,
1928
+ toolchain,
1858
1929
  voidPackageSpec: resolveScaffoldDependencySpec(root, "void", getOwnVersion()),
1859
1930
  adapterPackageSpec: resolveScaffoldDependencySpec(root, SCAFFOLD_FRAMEWORKS[framework].adapterPackage, getOwnVersion())
1860
1931
  });
@@ -1893,7 +1964,7 @@ function scaffoldPagesApp(root, packageManager, framework, starterMode) {
1893
1964
  for (const [name, version] of Object.entries(template.dependencies)) ensureDependency("dependencies", name, version);
1894
1965
  for (const [name, version] of Object.entries(template.devDependencies)) ensureDependency("devDependencies", name, version);
1895
1966
  if (isPnpmProject(root, pkg)) ensurePnpmAllowBuilds(root, pkg);
1896
- if (packageManager === "pnpm" && (!pkg.packageManager || typeof pkg.packageManager !== "string")) pkg.packageManager = "pnpm@11.0.9";
1967
+ if (packageManager === "pnpm" && resolveWorkspaceDeferral(root, pkg) === void 0 && (!pkg.packageManager || typeof pkg.packageManager !== "string")) pkg.packageManager = "pnpm@11.0.9";
1897
1968
  writeFileSync(packageJsonPath, JSON.stringify(pkg, null, 2) + "\n");
1898
1969
  R.success("Updated package.json with starter scripts and dependencies");
1899
1970
  for (const [filePath, content] of Object.entries(template.files)) writeFileIfMissing(root, filePath, content);
@@ -2547,6 +2618,7 @@ async function runInitCommand(root, initArgs) {
2547
2618
  console.log();
2548
2619
  ge(cliTitle("init"));
2549
2620
  const targeted = Boolean(initArgs && (initArgs.tsconfig || initArgs.github || initArgs.agents));
2621
+ if (!targeted) root = await resolveInitRoot(root);
2550
2622
  const framework = detectFramework(root);
2551
2623
  const preScaffoldState = detectProjectState(root);
2552
2624
  const detectedPagesFramework = detectPagesFramework(root);
@@ -2558,12 +2630,14 @@ async function runInitCommand(root, initArgs) {
2558
2630
  if (framework) R.info(`Detected ${framework.name} framework`);
2559
2631
  if (!targeted && !framework && isScaffoldableEmptyProject(root)) {
2560
2632
  R.info("Empty project detected. Scaffolding a Pages starter...");
2633
+ const scaffoldToolchain = await promptScaffoldToolchain();
2561
2634
  if (detectedPagesFramework) {
2562
2635
  scaffoldedPagesFramework = detectedPagesFramework;
2563
2636
  R.info(`Detected ${SCAFFOLD_FRAMEWORKS[detectedPagesFramework].label} adapter in package.json`);
2564
2637
  } else scaffoldedPagesFramework = await promptScaffoldFramework();
2565
2638
  const starterMode = await promptStarterMode();
2566
- const scaffoldWroteDeps = scaffoldPagesApp(root, preScaffoldState.packageManager, scaffoldedPagesFramework, starterMode);
2639
+ const scaffoldPackageManager = scaffoldToolchain === "vite-plus" ? "pnpm" : preScaffoldState.packageManager;
2640
+ const scaffoldWroteDeps = scaffoldPagesApp(root, scaffoldPackageManager, scaffoldedPagesFramework, starterMode, scaffoldToolchain);
2567
2641
  const deferral = resolveWorkspaceDeferral(root, readPackageJson(root));
2568
2642
  const voidResolvable = isVoidResolvableFrom(root);
2569
2643
  if (deferral && (!voidResolvable || scaffoldWroteDeps)) {
@@ -5,6 +5,11 @@ import { normalizePath } from "vite";
5
5
  //#region src/pages/islands-plugin.ts
6
6
  const ISLANDS_RENDERER_ID = "virtual:void-islands-renderer";
7
7
  const ISLANDS_CLIENT_ENTRY_ID = "virtual:void-islands-client";
8
+ const ISLAND_IMPORT_RE = /import\s+([$_A-Za-z][$_\w]*)\s+from\s+("[^"]+"|'[^']+')\s+with\s*\{\s*island\s*:\s*("[^"]+"|'[^']+')\s*,?\s*\}/g;
9
+ function hasIslandImports(code) {
10
+ ISLAND_IMPORT_RE.lastIndex = 0;
11
+ return ISLAND_IMPORT_RE.test(code);
12
+ }
8
13
  /** Resolve a relative import specifier to an absolute path by checking extensions. */
9
14
  function resolveSpecifier(specifier, importerDir, extensions) {
10
15
  const base = normalizePath(resolve(importerDir, specifier));
@@ -18,7 +23,6 @@ function resolveSpecifier(specifier, importerDir, extensions) {
18
23
  * or any .md file has a `<script>` block.
19
24
  */
20
25
  function needsIslandClientBundle(dir, islandFilePattern, checkStyleBlocks) {
21
- const importAttrRe = /import\s+\w+\s+from\s+("[^"]+"|'[^']+')\s+with\s*\{\s*island\s*:/;
22
26
  const cssImportRe = /import\b[^"']*["'][^"']+\.(?:css|scss|sass|less|styl|stylus|pcss|postcss)["']/;
23
27
  const mdScriptRe = /^<script\b/m;
24
28
  const styleRe = checkStyleBlocks ? /<style\b/ : null;
@@ -31,7 +35,7 @@ function needsIslandClientBundle(dir, islandFilePattern, checkStyleBlocks) {
31
35
  const name = entry.name;
32
36
  if (islandFilePattern.test(name) || name.startsWith("layout.") || name.startsWith("_")) {
33
37
  const content = readFileSync(resolve(entry.parentPath, name), "utf-8");
34
- if (importAttrRe.test(content)) return true;
38
+ if (hasIslandImports(content)) return true;
35
39
  if (styleRe && styleRe.test(content)) return true;
36
40
  if (cssImportRe.test(content)) return true;
37
41
  }
@@ -67,13 +71,10 @@ function extractCssImports(filePath) {
67
71
  function computePagesNeedingClientJS(pageScan, pagesDir, resolvedConfig) {
68
72
  const mdPlugin = resolvedConfig?.plugins?.find((plugin) => plugin.name === "void-md");
69
73
  const mdScriptIds = new Set(mdPlugin?.api?.getClientScripts?.()?.keys() ?? []);
70
- const importAttrRe = /import\s+\w+\s+from\s+("[^"]+"|'[^']+')\s+with\s*\{\s*island\s*:\s*("[^"]+"|'[^']+')\s*\}/g;
71
74
  const layoutDirsWithIslands = /* @__PURE__ */ new Set();
72
75
  for (const layout of pageScan.layouts) {
73
76
  if (!layout.island) continue;
74
- const code = readFileSync(resolve(pagesDir, layout.filePath), "utf-8");
75
- importAttrRe.lastIndex = 0;
76
- if (importAttrRe.test(code)) layoutDirsWithIslands.add(layout.directory);
77
+ if (hasIslandImports(readFileSync(resolve(pagesDir, layout.filePath), "utf-8"))) layoutDirsWithIslands.add(layout.directory);
77
78
  }
78
79
  const result = /* @__PURE__ */ new Set();
79
80
  for (const page of pageScan.pages) {
@@ -82,9 +83,7 @@ function computePagesNeedingClientJS(pageScan, pagesDir, resolvedConfig) {
82
83
  result.add(page.componentId);
83
84
  continue;
84
85
  }
85
- const code = readFileSync(resolve(pagesDir, page.componentPath), "utf-8");
86
- importAttrRe.lastIndex = 0;
87
- if (importAttrRe.test(code)) {
86
+ if (hasIslandImports(readFileSync(resolve(pagesDir, page.componentPath), "utf-8"))) {
88
87
  result.add(page.componentId);
89
88
  continue;
90
89
  }
@@ -63,7 +63,8 @@ async function runD1Migrations(db, migrations) {
63
63
  const start = Date.now();
64
64
  try {
65
65
  const statements = splitMigrationSql(m.sql);
66
- if (statements.length === 1 && statements[0] === m.sql) await db.exec(m.sql);
66
+ if (statements.length === 1) if (isSingleSqlStatement(statements[0])) await db.prepare(statements[0]).run();
67
+ else await db.exec(m.sql);
67
68
  else for (const statement of statements) await db.prepare(statement).run();
68
69
  await db.prepare("INSERT OR IGNORE INTO _void_migrations (name, applied_at) VALUES (?, ?)").bind(m.name, (/* @__PURE__ */ new Date()).toISOString()).run();
69
70
  migrationResults.push({
@@ -121,5 +122,71 @@ function isStatementBreakpointLine(line) {
121
122
  function hasInlineStatementBreakpoint(line) {
122
123
  return /;\s*-->\s*statement-breakpoint\s*$/.test(line.trim());
123
124
  }
125
+ function isSingleSqlStatement(sql) {
126
+ let statements = 0;
127
+ let inStatement = false;
128
+ let index = 0;
129
+ while (index < sql.length) {
130
+ const character = sql[index];
131
+ const next = index + 1 < sql.length ? sql[index + 1] : "";
132
+ if (character === "-" && next === "-") {
133
+ index += 2;
134
+ while (index < sql.length && sql[index] !== "\n") index++;
135
+ continue;
136
+ }
137
+ if (character === "/" && next === "*") {
138
+ index += 2;
139
+ while (index < sql.length - 1 && !(sql[index] === "*" && sql[index + 1] === "/")) index++;
140
+ index = Math.min(index + 2, sql.length);
141
+ continue;
142
+ }
143
+ if (character === "'") {
144
+ inStatement = true;
145
+ index++;
146
+ while (index < sql.length) {
147
+ if (sql[index] === "'" && sql[index + 1] === "'") {
148
+ index += 2;
149
+ continue;
150
+ }
151
+ if (sql[index] === "'") {
152
+ index++;
153
+ break;
154
+ }
155
+ index++;
156
+ }
157
+ continue;
158
+ }
159
+ if (character === "\"" || character === "`" || character === "[") {
160
+ inStatement = true;
161
+ const close = character === "[" ? "]" : character;
162
+ index++;
163
+ while (index < sql.length) {
164
+ if (close !== "]" && sql[index] === close && sql[index + 1] === close) {
165
+ index += 2;
166
+ continue;
167
+ }
168
+ if (sql[index] === close) {
169
+ index++;
170
+ break;
171
+ }
172
+ index++;
173
+ }
174
+ continue;
175
+ }
176
+ if (character === ";") {
177
+ if (inStatement) {
178
+ statements++;
179
+ if (statements > 1) return false;
180
+ inStatement = false;
181
+ }
182
+ index++;
183
+ continue;
184
+ }
185
+ if (character !== " " && character !== " " && character !== "\n" && character !== "\r") inStatement = true;
186
+ index++;
187
+ }
188
+ if (inStatement) statements++;
189
+ return statements === 1;
190
+ }
124
191
  //#endregion
125
192
  export { createMigrationHandler };
@@ -7,9 +7,9 @@ Then run:
7
7
 
8
8
  npx void init
9
9
 
10
- In an empty directory, `void init` will add the matching Pages adapter and starter dependencies after you choose a framework. In an existing app, it configures Void in place by adding missing Vite scripts and creating or patching `vite.config.*` with `voidPlugin()`.
10
+ In an empty directory, `void init` will add the matching Pages adapter and starter dependencies after you choose a scaffold toolchain and framework. Vite+ is the default toolchain. In an existing app, it configures Void in place by adding missing Vite scripts and creating or patching `vite.config.*` with `voidPlugin()`.
11
11
 
12
- During `void init`, first choose a Pages framework (React, Vue, Svelte, or Solid), then choose D1 for a zero-config, fully managed default or PostgreSQL if you already have Postgres infrastructure or expect heavier writes and more complex queries.
12
+ During `void init`, choose Vite+ unless you specifically want plain Vite scripts, then choose a Pages framework (React, Vue, Svelte, or Solid). Choose D1 for a zero-config, fully managed default or PostgreSQL if you already have Postgres infrastructure or expect heavier writes and more complex queries.
13
13
 
14
14
  At the end of the interactive flow, `void init` can also log you in and link or create your Void project so your first deploy is just:
15
15
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "void",
3
- "version": "0.7.12",
3
+ "version": "0.7.13",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/voidzero-dev/void.git",
@@ -332,7 +332,7 @@
332
332
  "valibot": ">=1.0.0-beta.7",
333
333
  "vite": "^8.0.0",
334
334
  "zod": "^3.25.0 || ^4.0.0",
335
- "@void/md": "0.7.12"
335
+ "@void/md": "0.7.13"
336
336
  },
337
337
  "peerDependenciesMeta": {
338
338
  "@void/md": {
@@ -13,7 +13,7 @@ Docs in this skill are bundled from `docs/` during `void` package build and live
13
13
 
14
14
  ## Command Naming
15
15
 
16
- Use `void` in examples and commands in this skill. For first-time setup, prefer `void init` followed by `void deploy`; in an empty directory, install `void` first and let `void init` add the matching Pages adapter and starter dependencies. In an existing app, `void init` configures Void in place by adding missing Vite scripts and creating or patching `vite.config.*` with `voidPlugin()`. `void init` can also handle auth and project linking interactively.
16
+ Use `void` in examples and commands in this skill. For first-time setup, prefer `void init` followed by `void deploy`; in an empty directory, install `void` first and let `void init` add the matching Pages adapter and starter dependencies with Vite+ as the default scaffold toolchain. In an existing app, `void init` configures Void in place by adding missing Vite scripts and creating or patching `vite.config.*` with `voidPlugin()`. `void init` can also handle auth and project linking interactively.
17
17
 
18
18
  Use `void` and `@void/*` in code examples and package manifests.
19
19
 
@@ -12,7 +12,7 @@ Pages mode is also entirely optional - you can use any client-side router to bui
12
12
 
13
13
  ## Setup
14
14
 
15
- If you start in a scaffoldable empty directory, `void init` can generate this setup for you: it asks whether you want React, Vue, Svelte, or Solid Pages mode, then lets you pick a D1 starter, a PostgreSQL starter, or Static Pages. The database-backed starters write the adapter-aware `vite.config.ts`, `pages/`, and `db/` starter files; Static Pages writes just the basic `pages/` setup so you can grow into server features later.
15
+ If you start in a scaffoldable empty directory, `void init` can generate this setup for you: it asks whether to scaffold with Vite+ (the default) or plain Vite, asks whether you want React, Vue, Svelte, or Solid Pages mode, then lets you pick a D1 starter, a PostgreSQL starter, or Static Pages. The database-backed starters write the adapter-aware `vite.config.ts`, `pages/`, and `db/` starter files; Static Pages writes just the basic `pages/` setup so you can grow into server features later.
16
16
 
17
17
  If you're adding Pages mode manually, install a framework adapter alongside `void`:
18
18
 
@@ -32,9 +32,9 @@ yarn add -D void
32
32
  bun add -D void
33
33
  ```
34
34
 
35
- In an empty directory, `void init` adds the matching Pages adapter and starter dependencies after you choose a framework.
35
+ In an empty directory, `void init` adds the matching Pages adapter and starter dependencies after you choose a scaffold toolchain and framework. Vite+ is the default toolchain and uses `vp` scripts.
36
36
 
37
- As part of `void init`, you'll choose a Pages framework (React, Vue, Svelte, or Solid) and a starter type. D1 is the default top option and scaffolds a DB-backed page loader, schema, generated migration, `db/seed.ts`, and API route. PostgreSQL scaffolds the same starter and writes `"database": "pg"` to `void.json`. Static Pages skips the database and server starter files so you can start with static content and add Void features later.
37
+ As part of `void init`, you'll choose Vite+ or plain Vite, then a Pages framework (React, Vue, Svelte, or Solid) and a starter type. D1 is the default top option and scaffolds a DB-backed page loader, schema, generated migration, `db/seed.ts`, and API route. PostgreSQL scaffolds the same starter and writes `"database": "pg"` to `void.json`. Static Pages skips the database and server starter files so you can start with static content and add Void features later.
38
38
 
39
39
  After installation, run the setup flow:
40
40
 
@@ -1,6 +1,6 @@
1
1
  ## Void
2
2
 
3
- This project uses [Void](https://void.cloud) — a fullstack Vite plugin + deployment platform for Cloudflare. `voidPlugin()` in `vite.config.ts` gives you file-based API routing on Hono (`routes/`), Inertia-inspired server-rendered pages with co-located loaders/actions (`pages/` + `@void/vue` or `@void/react`), auto-provisioned D1/KV/R2 bindings, first-class Drizzle ORM integration (schema in `db/schema.ts` -> `void/db` Drizzle instance -> typed routes -> typed fetch client), built-in auth, queues, cron jobs, edge caching (ISR), and one-command deploys via `npx void deploy`. For first-time setup, prefer `npx void init`; in an empty directory, install `void` first and let the interactive flow scaffold the starter, add the matching framework adapter, configure project files, handle auth, and link or create the deploy project before the first deploy. In an existing app, `void init` configures Void in place by adding missing Vite scripts and creating or patching `vite.config.*` with `voidPlugin()`. Use `void` and `@void/*` package names in source code and package manifests.
3
+ This project uses [Void](https://void.cloud) — a fullstack Vite plugin + deployment platform for Cloudflare. `voidPlugin()` in `vite.config.ts` gives you file-based API routing on Hono (`routes/`), Inertia-inspired server-rendered pages with co-located loaders/actions (`pages/` + `@void/vue` or `@void/react`), auto-provisioned D1/KV/R2 bindings, first-class Drizzle ORM integration (schema in `db/schema.ts` -> `void/db` Drizzle instance -> typed routes -> typed fetch client), built-in auth, queues, cron jobs, edge caching (ISR), and one-command deploys via `npx void deploy`. For first-time setup, prefer `npx void init`; in an empty directory, install `void` first and let the interactive flow scaffold the starter with Vite+ by default, add the matching framework adapter, configure project files, handle auth, and link or create the deploy project before the first deploy. In an existing app, `void init` configures Void in place by adding missing Vite scripts and creating or patching `vite.config.*` with `voidPlugin()`. Use `void` and `@void/*` package names in source code and package manifests.
4
4
 
5
5
  Database: define Drizzle tables in `db/schema.ts`, import `db` from `void/db` and tables from `@schema`. Use `void db push` for prototyping, `void db generate` for production migrations. `drizzle-orm` and `drizzle-kit` ship with void (no extra install). Migrations live in `db/migrations/`.
6
6
 
@@ -21,7 +21,7 @@ Install the Void CLI:
21
21
  npm install -D void
22
22
  ```
23
23
 
24
- If you run `void init` in an empty directory, the scaffold flow adds the matching Pages adapter and Vite dependencies for you.
24
+ If you run `void init` in an empty directory, the scaffold flow adds the matching Pages adapter and Vite+ by default.
25
25
 
26
26
  Then run `npx void init`. In an empty directory, the full interactive flow can scaffold a starter, configure local project files, log you in, and link or create your Void project so the next step is just `npx void deploy`. In an existing app, it configures Void in place by adding missing Vite scripts and creating or patching `vite.config.*` with `voidPlugin()`.
27
27
 
@@ -82,7 +82,7 @@ There is Vinext-specific source in the repo, but it is intentionally on hold and
82
82
 
83
83
  ## Documentation
84
84
 
85
- Full docs live at [void.cloud/docs](https://void.cloud/docs).
85
+ Full docs live at [void.cloud/guide](https://void.cloud/guide).
86
86
 
87
87
  ## License
88
88
 
@@ -13,7 +13,7 @@ Docs in this skill are bundled from `docs/` during `void` package build and live
13
13
 
14
14
  ## Command Naming
15
15
 
16
- Use `void` in examples and commands in this skill. For first-time setup, prefer `void init` followed by `void deploy`; in an empty directory, install `void` first and let `void init` add the matching Pages adapter and starter dependencies. In an existing app, `void init` configures Void in place by adding missing Vite scripts and creating or patching `vite.config.*` with `voidPlugin()`. `void init` can also handle auth and project linking interactively.
16
+ Use `void` in examples and commands in this skill. For first-time setup, prefer `void init` followed by `void deploy`; in an empty directory, install `void` first and let `void init` add the matching Pages adapter and starter dependencies with Vite+ as the default scaffold toolchain. In an existing app, `void init` configures Void in place by adding missing Vite scripts and creating or patching `vite.config.*` with `voidPlugin()`. `void init` can also handle auth and project linking interactively.
17
17
 
18
18
  Use `void` and `@void/*` in code examples and package manifests.
19
19
 
@@ -66,7 +66,9 @@ void init [--tsconfig] [--github] [--agents]
66
66
 
67
67
  Setup wizard for Void projects (new or existing).
68
68
 
69
- If run in a scaffoldable empty directory, `void init` scaffolds a Pages starter. If a single Pages adapter is already installed, it reuses that framework; otherwise it asks which framework to scaffold (React, Vue, Svelte, or Solid). It then asks which starter you want: D1, PostgreSQL, or Static Pages. The D1 and PostgreSQL starters write a framework-specific `vite.config.ts`, a `pages/` home page plus `.server.ts` loader, `db/schema.ts`, `db/seed.ts`, a generated initial migration under `db/migrations/`, and `routes/api/hello.ts`. The Static Pages starter writes just the framework-specific `vite.config.ts` and a `pages/` home page so you can add server features later.
69
+ If run in a scaffoldable empty directory, `void init` scaffolds a Pages starter. It asks which scaffold toolchain to use, with Vite+ as the default top option and plain Vite as the alternative. If a single Pages adapter is already installed, it reuses that framework; otherwise it asks which framework to scaffold (React, Vue, Svelte, or Solid). It then asks which starter you want: D1, PostgreSQL, or Static Pages. The D1 and PostgreSQL starters write a framework-specific `vite.config.ts`, a `pages/` home page plus `.server.ts` loader, `db/schema.ts`, `db/seed.ts`, a generated initial migration under `db/migrations/`, and `routes/api/hello.ts`. The Static Pages starter writes just the framework-specific `vite.config.ts` and a `pages/` home page so you can add server features later. Vite+ starters add `vite-plus` and use `vp dev`, `vp build`, and `vp preview` scripts.
70
+
71
+ If run in a non-empty folder that does not look like an app yet, such as a parent `Projects/` folder with subdirectories but no `package.json`, `void init` asks whether to create a new subfolder or continue in the current folder. Creating a subfolder is the default selection.
70
72
 
71
73
  If run in an existing project, `void init` configures the project in place: it ensures `void` and `vite` are declared, adds missing `dev` (`vite`) and `build` (`vite build`) scripts without overwriting existing scripts, and creates or patches `vite.config.*` with `voidPlugin()` when the config shape is safe to edit. If the Vite config is too dynamic to patch confidently, it prints the manual snippet instead of rewriting it.
72
74