create-pracht 0.5.0 → 0.6.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/src/index.js CHANGED
@@ -16,10 +16,11 @@ const FALLBACK_VERSION_RANGES = {
16
16
  "@pracht/adapter-cloudflare": "^0.5.8",
17
17
  "@pracht/adapter-netlify": "^0.1.0",
18
18
  "@pracht/adapter-node": "^0.3.8",
19
+ "@pracht/adapter-static": "^0.1.0",
19
20
  "@pracht/adapter-vercel": "^0.2.8",
20
- "@pracht/cli": "^1.9.0",
21
- "@pracht/core": "^0.12.0",
22
- "@pracht/vite-plugin": "^0.7.6",
21
+ "@pracht/cli": "^1.11.0",
22
+ "@pracht/core": "^0.14.0",
23
+ "@pracht/vite-plugin": "^0.9.0",
23
24
  "@tailwindcss/vite": "^4.1.0",
24
25
  "netlify-cli": "^21.6.0",
25
26
  tailwindcss: "^4.1.0",
@@ -87,6 +88,13 @@ const ADAPTERS = {
87
88
  packageName: "@pracht/adapter-vercel",
88
89
  short: "vercel",
89
90
  },
91
+ static: {
92
+ description: "Pure static export — deploy dist/client to any static host",
93
+ id: "static",
94
+ label: "Static export",
95
+ packageName: "@pracht/adapter-static",
96
+ short: "static",
97
+ },
90
98
  };
91
99
 
92
100
  const DEFAULT_DIRECTORY = "pracht-app";
@@ -407,7 +415,7 @@ export function parseArgs(argv) {
407
415
  const value = normalizeAdapter(arg.slice("--adapter=".length));
408
416
  if (!value) {
409
417
  throw new ValidationError(
410
- `Invalid adapter: ${arg.slice("--adapter=".length)}. Use node, cf, netlify, or vercel.`,
418
+ `Invalid adapter: ${arg.slice("--adapter=".length)}. Use node, cf, netlify, vercel, or static.`,
411
419
  );
412
420
  }
413
421
  options.adapter = value;
@@ -462,6 +470,7 @@ async function promptForAdapter(readline) {
462
470
  console.log(" 2. Cloudflare Workers");
463
471
  console.log(" 3. Vercel");
464
472
  console.log(" 4. Netlify");
473
+ console.log(" 5. Static export (no server)");
465
474
 
466
475
  while (true) {
467
476
  const answer = await readline.question("Adapter (1): ");
@@ -471,7 +480,7 @@ async function promptForAdapter(readline) {
471
480
  return normalized;
472
481
  }
473
482
 
474
- console.log("Choose 1/2/3/4 or node/cf/vercel/netlify.");
483
+ console.log("Choose 1/2/3/4/5 or node/cf/vercel/netlify/static.");
475
484
  }
476
485
  }
477
486
 
@@ -614,6 +623,10 @@ function normalizeAdapter(value) {
614
623
  return "netlify";
615
624
  }
616
625
 
626
+ if (normalized === "5" || normalized === "static" || normalized === "export") {
627
+ return "static";
628
+ }
629
+
617
630
  return null;
618
631
  }
619
632
 
@@ -690,11 +703,16 @@ async function buildProjectFiles({
690
703
  tailwind,
691
704
  versions,
692
705
  }),
693
- "src/api/health.ts": createHealthRoute(adapter),
694
706
  "vite.config.ts": createViteConfig(adapter, router, tailwind),
695
707
  "tsconfig.json": createBaseTSConfig(adapter),
696
708
  };
697
709
 
710
+ // A static export has no server, so an API route would be a hard build
711
+ // error — the starter must not scaffold one it cannot build.
712
+ if (adapter.id !== "static") {
713
+ files["src/api/health.ts"] = createHealthRoute(adapter);
714
+ }
715
+
698
716
  if (agentTools) {
699
717
  files["AGENTS.md"] = createAgentInstructions({
700
718
  adapter,
@@ -803,6 +821,10 @@ function createPackageJson({ adapter, projectName, tailwind, versions }) {
803
821
  scripts.start = "node dist/server/server.js";
804
822
  }
805
823
 
824
+ if (adapter.id === "static") {
825
+ scripts.preview = "pracht preview";
826
+ }
827
+
806
828
  const devDependencies = {
807
829
  "@pracht/cli": versions["@pracht/cli"],
808
830
  "@pracht/vite-plugin": versions["@pracht/vite-plugin"],
@@ -858,6 +880,7 @@ function createViteConfig(adapter, router, tailwind) {
858
880
  cloudflare: { fn: "cloudflareAdapter", pkg: "@pracht/adapter-cloudflare" },
859
881
  netlify: { fn: "netlifyAdapter", pkg: "@pracht/adapter-netlify" },
860
882
  vercel: { fn: "vercelAdapter", pkg: "@pracht/adapter-vercel" },
883
+ static: { fn: "staticAdapter", pkg: "@pracht/adapter-static" },
861
884
  };
862
885
 
863
886
  const info = ADAPTER_IMPORTS[adapter.id] ?? ADAPTER_IMPORTS.node;
@@ -955,7 +978,9 @@ function createHomeRoute(adapter) {
955
978
  " steps: [",
956
979
  ' "Edit src/routes/home.tsx to change this page.",',
957
980
  ' "Add more routes in src/routes.ts.",',
958
- ' "Add API handlers in src/api/*.ts.",',
981
+ adapter.id === "static"
982
+ ? ' "Fetch live data from the browser — a static export runs no server.",'
983
+ : ' "Add API handlers in src/api/*.ts.",',
959
984
  " ],",
960
985
  " };",
961
986
  "}",
@@ -974,7 +999,9 @@ function createHomeRoute(adapter) {
974
999
  " ))}",
975
1000
  " </ul>",
976
1001
  ' <p style={{ marginTop: "24px" }}>',
977
- " Check <code>/api/health</code> for a simple API route.",
1002
+ adapter.id === "static"
1003
+ ? " Run <code>pracht build</code>, then deploy <code>dist/client</code> anywhere."
1004
+ : " Check <code>/api/health</code> for a simple API route.",
978
1005
  " </p>",
979
1006
  " </section>",
980
1007
  " );",
@@ -1022,7 +1049,9 @@ function createPagesHomeRoute(adapter) {
1022
1049
  " steps: [",
1023
1050
  ' "Edit src/pages/index.tsx to change this page.",',
1024
1051
  ' "Add more pages in src/pages/.",',
1025
- ' "Add API handlers in src/api/*.ts.",',
1052
+ adapter.id === "static"
1053
+ ? ' "Fetch live data from the browser — a static export runs no server.",'
1054
+ : ' "Add API handlers in src/api/*.ts.",',
1026
1055
  " ],",
1027
1056
  " };",
1028
1057
  "}",
@@ -1041,7 +1070,9 @@ function createPagesHomeRoute(adapter) {
1041
1070
  " ))}",
1042
1071
  " </ul>",
1043
1072
  ' <p style={{ marginTop: "24px" }}>',
1044
- " Check <code>/api/health</code> for a simple API route.",
1073
+ adapter.id === "static"
1074
+ ? " Run <code>pracht build</code>, then deploy <code>dist/client</code> anywhere."
1075
+ : " Check <code>/api/health</code> for a simple API route.",
1045
1076
  " </p>",
1046
1077
  " </section>",
1047
1078
  " );",
@@ -1267,6 +1298,11 @@ function createWranglerConfig(projectName) {
1267
1298
  // validates every named export of the deployed entry module and rejects the
1268
1299
  // build metadata (buildTarget, manifests, ...) server.js also exports.
1269
1300
  ' "main": "dist/server/worker.js",',
1301
+ // Pracht's Vite build is the authoritative bundle and may contain lazy
1302
+ // server chunks. A second Wrangler bundle would inline them again; the
1303
+ // module rule makes Wrangler upload those chunks next to the entry.
1304
+ ' "no_bundle": true,',
1305
+ ' "rules": [{ "type": "ESModule", "globs": ["**/*.js", "**/*.mjs"] }],',
1270
1306
  ` "compatibility_date": ${JSON.stringify(compatibilityDate)},`,
1271
1307
  ' "assets": {',
1272
1308
  ' "binding": "ASSETS",',
@@ -1410,7 +1446,12 @@ function createAgentInstructions({ adapter, agentTools, packageManager, router,
1410
1446
  `- \`${runCmd} build\` — production build`,
1411
1447
  ];
1412
1448
 
1413
- if (adapter.id === "node" || adapter.id === "cloudflare" || adapter.id === "netlify") {
1449
+ if (
1450
+ adapter.id === "node" ||
1451
+ adapter.id === "cloudflare" ||
1452
+ adapter.id === "netlify" ||
1453
+ adapter.id === "static"
1454
+ ) {
1414
1455
  lines.push(`- \`${runCmd} preview\` — build and serve the production build locally`);
1415
1456
  }
1416
1457
 
@@ -1430,10 +1471,14 @@ function createAgentInstructions({ adapter, agentTools, packageManager, router,
1430
1471
  lines.push("- `pracht generate route --path /about` — add a route");
1431
1472
  if (router !== "pages") {
1432
1473
  lines.push("- `pracht generate shell --name app` — add a shell");
1433
- lines.push("- `pracht generate middleware --name auth` — add middleware");
1474
+ if (adapter.id !== "static") {
1475
+ lines.push("- `pracht generate middleware --name auth` — add middleware");
1476
+ }
1434
1477
  }
1435
- lines.push("- `pracht generate api --path /health --methods GET` — add an API route");
1436
- if (router !== "pages") {
1478
+ if (adapter.id !== "static") {
1479
+ lines.push("- `pracht generate api --path /health --methods GET` — add an API route");
1480
+ }
1481
+ if (router !== "pages" && adapter.id !== "static") {
1437
1482
  lines.push(
1438
1483
  "- `pracht generate capability --name notes.search --effect read --expose http` — add a capability (agent-callable operation)",
1439
1484
  );
@@ -1473,7 +1518,9 @@ function createAgentInstructions({ adapter, agentTools, packageManager, router,
1473
1518
  lines.push("- `src/shells/` — shell components (layouts)");
1474
1519
  }
1475
1520
 
1476
- lines.push("- `src/api/` — API route handlers");
1521
+ if (adapter.id !== "static") {
1522
+ lines.push("- `src/api/` — API route handlers");
1523
+ }
1477
1524
  lines.push(`- \`vite.config.ts\` — Vite config with the ${adapter.label} adapter`);
1478
1525
 
1479
1526
  if (tailwind) {
@@ -1576,6 +1623,21 @@ function createReadme({
1576
1623
  lines.push("Run the deploy command after linking or logging into your Vercel account.");
1577
1624
  }
1578
1625
 
1626
+ if (adapter.id === "static") {
1627
+ lines.push(`- \`${previewCommand}\``);
1628
+ lines.push("");
1629
+ lines.push(
1630
+ "`pracht build` writes the whole site to `dist/client`. Upload that directory to any " +
1631
+ "static host — there is no server to run. Configure the host to serve `index.html` " +
1632
+ "for directory URLs and to use `404.html` as its error document.",
1633
+ );
1634
+ lines.push("");
1635
+ lines.push(
1636
+ "A static export runs no server, so API routes, middleware, and `ssr`/`isg` routes are " +
1637
+ "build errors. Fetch live data from the browser instead, or switch to a serverful adapter.",
1638
+ );
1639
+ }
1640
+
1579
1641
  lines.push("");
1580
1642
  lines.push("## Files");
1581
1643
  lines.push("");
@@ -1597,7 +1659,9 @@ function createReadme({
1597
1659
  lines.push("- `src/routes/not-found.tsx` is the not-found page, wired via `notFound`.");
1598
1660
  }
1599
1661
 
1600
- lines.push("- `src/api/health.ts` is a sample API route.");
1662
+ if (adapter.id !== "static") {
1663
+ lines.push("- `src/api/health.ts` is a sample API route.");
1664
+ }
1601
1665
 
1602
1666
  if (packageManager === "pnpm") {
1603
1667
  lines.push(
@@ -1791,7 +1855,7 @@ Usage:
1791
1855
  create-pracht [directory] [options]
1792
1856
 
1793
1857
  Options:
1794
- --adapter=node|cf|netlify|vercel
1858
+ --adapter=node|cf|netlify|vercel|static
1795
1859
  Choose hosting adapter (default: node)
1796
1860
  --router=manifest|pages Choose routing system (default: manifest)
1797
1861
  --template=minimal|tailwind Choose starter template (minimal, or minimal + Tailwind CSS)