@donotdev/cli 0.0.18 → 0.0.20

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.
Files changed (150) hide show
  1. package/dependencies-matrix.json +42 -55
  2. package/dist/bin/commands/bump.js +5 -2
  3. package/dist/bin/commands/coach.js +8177 -0
  4. package/dist/bin/commands/create-app.js +6 -6
  5. package/dist/bin/commands/create-project.js +23 -9
  6. package/dist/bin/commands/deploy.js +99 -59
  7. package/dist/bin/commands/doctor.js +243 -698
  8. package/dist/bin/commands/emu.js +2 -2
  9. package/dist/bin/commands/format.js +4 -1
  10. package/dist/bin/commands/get-demo.js +8351 -0
  11. package/dist/bin/commands/make-admin.js +773 -152
  12. package/dist/bin/commands/setup.js +524 -1713
  13. package/dist/bin/commands/staging.js +17870 -0
  14. package/dist/bin/commands/sync-secrets.js +2 -11
  15. package/dist/bin/commands/type-check.js +7738 -1712
  16. package/dist/bin/dndev.js +868 -199
  17. package/dist/bin/donotdev.js +868 -199
  18. package/dist/index.js +127 -67
  19. package/package.json +1 -1
  20. package/templates/app-demo/index.html.example +147 -10
  21. package/templates/app-demo/public/apple-touch-icon.png.example +0 -0
  22. package/templates/app-demo/public/favicon.svg.example +1 -0
  23. package/templates/app-demo/public/icon-192x192.png.example +0 -0
  24. package/templates/app-demo/public/icon-512x512.png.example +0 -0
  25. package/templates/app-demo/src/App.tsx.example +7 -11
  26. package/templates/app-demo/src/config/app.ts.example +13 -48
  27. package/templates/app-demo/src/entities/booking.ts.example +75 -0
  28. package/templates/app-demo/src/entities/onboarding.ts.example +160 -0
  29. package/templates/app-demo/src/entities/product.ts.example +50 -0
  30. package/templates/app-demo/src/entities/quote.ts.example +70 -0
  31. package/templates/app-demo/src/globals.css.example +5 -1
  32. package/templates/app-demo/src/main.tsx.example +13 -7
  33. package/templates/app-demo/src/pages/ChangelogPage.tsx.example +41 -0
  34. package/templates/app-demo/src/pages/ConditionalFormPage.tsx.example +88 -0
  35. package/templates/app-demo/src/pages/DashboardPage.tsx.example +17 -0
  36. package/templates/app-demo/src/pages/HomePage.tsx.example +339 -60
  37. package/templates/app-demo/src/pages/OnboardingPage.tsx.example +47 -0
  38. package/templates/app-demo/src/pages/PricingPage.tsx.example +41 -0
  39. package/templates/app-demo/src/pages/ProductsPage.tsx.example +19 -0
  40. package/templates/app-demo/src/pages/ProfilePage.tsx.example +18 -0
  41. package/templates/app-demo/src/pages/SettingsPage.tsx.example +17 -0
  42. package/templates/app-demo/src/pages/ShowcaseDetailPage.tsx.example +118 -0
  43. package/templates/app-demo/src/pages/ShowcasePage.tsx.example +93 -0
  44. package/templates/app-demo/src/pages/components/ComponentRenderer.tsx.example +147 -51
  45. package/templates/app-demo/src/pages/components/ComponentsData.tsx.example +103 -21
  46. package/templates/app-demo/src/pages/components/componentConfig.ts.example +139 -59
  47. package/templates/app-demo/src/pages/legal/LegalPage.tsx.example +25 -0
  48. package/templates/app-demo/src/pages/legal/PrivacyPage.tsx.example +23 -0
  49. package/templates/app-demo/src/pages/legal/TermsPage.tsx.example +23 -0
  50. package/templates/app-demo/src/themes.css.example +289 -77
  51. package/templates/app-demo/stats.html.example +4949 -0
  52. package/templates/app-demo/tsconfig.json.example +1 -1
  53. package/templates/app-demo/vite.config.ts.example +23 -48
  54. package/templates/app-expo/README.md.example +1 -1
  55. package/templates/app-expo/app/index.tsx.example +1 -1
  56. package/templates/app-next/src/locales/home_en.json.example +6 -6
  57. package/templates/app-vite/src/locales/home_en.json.example +6 -6
  58. package/templates/app-vite/src/pages/HomePage.tsx.example +8 -10
  59. package/templates/overlay-firebase/env.fragment.example +1 -1
  60. package/templates/overlay-firebase/env.fragment.expo.example +1 -1
  61. package/templates/overlay-firebase/env.fragment.nextjs.example +1 -1
  62. package/templates/overlay-supabase/env.fragment.example +1 -1
  63. package/templates/overlay-supabase/env.fragment.expo.example +1 -1
  64. package/templates/overlay-supabase/env.fragment.nextjs.example +1 -1
  65. package/templates/overlay-vercel/env.fragment.example +1 -1
  66. package/templates/overlay-vercel/env.fragment.nextjs.example +1 -1
  67. package/templates/root-consumer/AI.md.example +4 -3
  68. package/templates/root-consumer/guides/dndev/AGENT_START_HERE.md.example +21 -6
  69. package/templates/root-consumer/guides/dndev/COMPONENTS_ADV.md.example +16 -179
  70. package/templates/root-consumer/guides/dndev/ENV_SETUP.md.example +19 -21
  71. package/templates/root-consumer/guides/dndev/GOTCHAS.md.example +14 -3
  72. package/templates/root-consumer/guides/dndev/INDEX.md.example +2 -2
  73. package/templates/root-consumer/guides/dndev/SETUP_APP_CONFIG.md.example +3 -3
  74. package/templates/root-consumer/guides/dndev/SETUP_BLOG.md.example +19 -2
  75. package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +35 -1
  76. package/templates/root-consumer/guides/dndev/SETUP_FIREBASE.md.example +17 -12
  77. package/templates/root-consumer/guides/dndev/SETUP_LAYOUTS.md.example +32 -0
  78. package/templates/root-consumer/guides/dndev/SETUP_OAUTH_PROVIDERS.md.example +1 -1
  79. package/templates/root-consumer/guides/dndev/SETUP_PAGES.md.example +19 -15
  80. package/templates/root-consumer/guides/dndev/SETUP_STRIPE.md.example +2 -2
  81. package/templates/root-consumer/guides/dndev/SETUP_SUPABASE.md.example +17 -12
  82. package/templates/root-consumer/guides/dndev/SETUP_VERCEL.md.example +37 -16
  83. package/templates/root-consumer/guides/dndev/USE_ROUTING.md.example +18 -18
  84. package/templates/root-consumer/guides/dndev/advanced/COOKIE_REFERENCE.md.example +252 -252
  85. package/templates/root-consumer/guides/dndev/advanced/VERSION_CONTROL.md.example +174 -174
  86. package/templates/root-consumer/guides/dndev/essences_reference.css.example +119 -2
  87. package/templates/root-consumer/guides/wai-way/blueprints/1_scaffold.md.example +14 -0
  88. package/templates/root-consumer/guides/wai-way/blueprints/2_entities.md.example +6 -0
  89. package/templates/root-consumer/guides/wai-way/blueprints/3_compose.md.example +14 -0
  90. package/templates/root-consumer/guides/wai-way/entity_patterns.md.example +4 -5
  91. package/templates/root-consumer/guides/wai-way/page_patterns.md.example +2 -2
  92. package/dist/bin/commands/agent-setup.d.ts +0 -6
  93. package/dist/bin/commands/agent-setup.d.ts.map +0 -1
  94. package/dist/bin/commands/agent-setup.js.map +0 -1
  95. package/dist/bin/commands/build.d.ts +0 -11
  96. package/dist/bin/commands/build.d.ts.map +0 -1
  97. package/dist/bin/commands/build.js.map +0 -1
  98. package/dist/bin/commands/bump.d.ts +0 -11
  99. package/dist/bin/commands/bump.d.ts.map +0 -1
  100. package/dist/bin/commands/bump.js.map +0 -1
  101. package/dist/bin/commands/cacheout.d.ts +0 -11
  102. package/dist/bin/commands/cacheout.d.ts.map +0 -1
  103. package/dist/bin/commands/cacheout.js.map +0 -1
  104. package/dist/bin/commands/create-app.d.ts +0 -11
  105. package/dist/bin/commands/create-app.d.ts.map +0 -1
  106. package/dist/bin/commands/create-app.js.map +0 -1
  107. package/dist/bin/commands/create-project.d.ts +0 -11
  108. package/dist/bin/commands/create-project.d.ts.map +0 -1
  109. package/dist/bin/commands/create-project.js.map +0 -1
  110. package/dist/bin/commands/deploy.d.ts +0 -11
  111. package/dist/bin/commands/deploy.d.ts.map +0 -1
  112. package/dist/bin/commands/deploy.js.map +0 -1
  113. package/dist/bin/commands/dev.d.ts +0 -11
  114. package/dist/bin/commands/dev.d.ts.map +0 -1
  115. package/dist/bin/commands/dev.js.map +0 -1
  116. package/dist/bin/commands/doctor.d.ts +0 -6
  117. package/dist/bin/commands/doctor.d.ts.map +0 -1
  118. package/dist/bin/commands/doctor.js.map +0 -1
  119. package/dist/bin/commands/emu.d.ts +0 -11
  120. package/dist/bin/commands/emu.d.ts.map +0 -1
  121. package/dist/bin/commands/emu.js.map +0 -1
  122. package/dist/bin/commands/format.d.ts +0 -11
  123. package/dist/bin/commands/format.d.ts.map +0 -1
  124. package/dist/bin/commands/format.js.map +0 -1
  125. package/dist/bin/commands/make-admin.d.ts +0 -11
  126. package/dist/bin/commands/make-admin.d.ts.map +0 -1
  127. package/dist/bin/commands/make-admin.js.map +0 -1
  128. package/dist/bin/commands/preview.d.ts +0 -11
  129. package/dist/bin/commands/preview.d.ts.map +0 -1
  130. package/dist/bin/commands/preview.js.map +0 -1
  131. package/dist/bin/commands/setup.d.ts +0 -6
  132. package/dist/bin/commands/setup.d.ts.map +0 -1
  133. package/dist/bin/commands/setup.js.map +0 -1
  134. package/dist/bin/commands/sync-secrets.d.ts +0 -11
  135. package/dist/bin/commands/sync-secrets.d.ts.map +0 -1
  136. package/dist/bin/commands/sync-secrets.js.map +0 -1
  137. package/dist/bin/commands/type-check.d.ts +0 -14
  138. package/dist/bin/commands/type-check.d.ts.map +0 -1
  139. package/dist/bin/commands/type-check.js.map +0 -1
  140. package/dist/bin/commands/wai.d.ts +0 -11
  141. package/dist/bin/commands/wai.d.ts.map +0 -1
  142. package/dist/bin/commands/wai.js.map +0 -1
  143. package/dist/index.d.ts +0 -8
  144. package/dist/index.d.ts.map +0 -1
  145. package/dist/index.js.map +0 -1
  146. package/templates/app-demo/src/components/ThemeToggle.tsx.example +0 -48
  147. package/templates/app-demo/src/pages/DetailPage.tsx.example +0 -103
  148. package/templates/app-demo/src/pages/FullPage.tsx.example +0 -142
  149. package/templates/app-demo/src/pages/components/DemoLayout.tsx.example +0 -266
  150. package/templates/app-demo/src/pages/components/LayoutRoute.tsx.example +0 -20
package/dist/index.js CHANGED
@@ -8859,21 +8859,21 @@ function getCLIInstallInstructions(tool) {
8859
8859
  ]
8860
8860
  },
8861
8861
  [CLI_TOOLS.YARN]: {
8862
- win32: ["npm install -g yarn", "Or: choco install yarn"],
8863
- darwin: ["npm install -g yarn", "Or: brew install yarn"],
8864
- linux: ["npm install -g yarn", "Or check your package manager"]
8862
+ win32: ["bun install -g yarn", "Or: choco install yarn"],
8863
+ darwin: ["bun install -g yarn", "Or: brew install yarn"],
8864
+ linux: ["bun install -g yarn", "Or check your package manager"]
8865
8865
  },
8866
8866
  [CLI_TOOLS.FIREBASE]: {
8867
8867
  win32: [
8868
- "npm install -g firebase-tools",
8868
+ "bun install -g firebase-tools",
8869
8869
  "Or download standalone binary: https://firebase.google.com/docs/cli#windows-standalone-binary"
8870
8870
  ],
8871
8871
  darwin: [
8872
- "npm install -g firebase-tools",
8872
+ "bun install -g firebase-tools",
8873
8873
  "Or: brew install firebase-cli"
8874
8874
  ],
8875
8875
  linux: [
8876
- "npm install -g firebase-tools",
8876
+ "bun install -g firebase-tools",
8877
8877
  "Or check your package manager (dnf, apt, pacman, etc.)"
8878
8878
  ]
8879
8879
  },
@@ -8890,25 +8890,25 @@ function getCLIInstallInstructions(tool) {
8890
8890
  ]
8891
8891
  },
8892
8892
  [CLI_TOOLS.VERCEL]: {
8893
- win32: ["npm install -g vercel", "Or: npx vercel (no install)"],
8893
+ win32: ["bun install -g vercel", "Or: bunx vercel (no install)"],
8894
8894
  darwin: [
8895
- "npm install -g vercel",
8895
+ "bun install -g vercel",
8896
8896
  "Or: brew install vercel",
8897
- "Or: npx vercel"
8897
+ "Or: bunx vercel"
8898
8898
  ],
8899
- linux: ["npm install -g vercel", "Or: npx vercel"]
8899
+ linux: ["bun install -g vercel", "Or: bunx vercel"]
8900
8900
  },
8901
8901
  [CLI_TOOLS.SENTRY_CLI]: {
8902
8902
  win32: [
8903
- "npm install -g @sentry/cli",
8903
+ "bun install -g @sentry/cli",
8904
8904
  "Or download from: https://github.com/getsentry/sentry-cli/releases"
8905
8905
  ],
8906
8906
  darwin: [
8907
- "npm install -g @sentry/cli",
8907
+ "bun install -g @sentry/cli",
8908
8908
  "Or: brew install getsentry/tools/sentry-cli"
8909
8909
  ],
8910
8910
  linux: [
8911
- "npm install -g @sentry/cli",
8911
+ "bun install -g @sentry/cli",
8912
8912
  "Or: curl -sL https://sentry.io/get-cli/ | bash"
8913
8913
  ]
8914
8914
  },
@@ -8937,9 +8937,9 @@ function getCLIInstallInstructions(tool) {
8937
8937
  ]
8938
8938
  },
8939
8939
  [CLI_TOOLS.TSX]: {
8940
- win32: ["npm install -g tsx"],
8941
- darwin: ["npm install -g tsx"],
8942
- linux: ["npm install -g tsx"]
8940
+ win32: ["bun install -g tsx"],
8941
+ darwin: ["bun install -g tsx"],
8942
+ linux: ["bun install -g tsx"]
8943
8943
  }
8944
8944
  };
8945
8945
  const platformInstructions = instructions[tool]?.[platform6] || instructions[tool]?.linux || [];
@@ -9034,14 +9034,27 @@ function readEnvVar(filePath, varName) {
9034
9034
  }
9035
9035
  return null;
9036
9036
  }
9037
- function resolveVercelToken(appDir) {
9038
- if (process.env.VERCEL_TOKEN) return process.env.VERCEL_TOKEN;
9039
- const fromEnv = readEnvVar(joinPath(appDir, ".env"), "VERCEL_TOKEN");
9040
- if (fromEnv) return fromEnv;
9041
- const fromLocal = readEnvVar(joinPath(appDir, ".env.local"), "VERCEL_TOKEN");
9037
+ function resolveVercelVar(appDir, varName) {
9038
+ if (process.env[varName]) return process.env[varName];
9039
+ const fromLocal = readEnvVar(joinPath(appDir, ".env.local"), varName);
9042
9040
  if (fromLocal) return fromLocal;
9041
+ const fromEnv = readEnvVar(joinPath(appDir, ".env"), varName);
9042
+ if (fromEnv) return fromEnv;
9043
9043
  return null;
9044
9044
  }
9045
+ function resolveVercelCredentials(appDir) {
9046
+ const token = resolveVercelVar(appDir, "VERCEL_TOKEN");
9047
+ const orgId = resolveVercelVar(appDir, "VERCEL_ORG_ID");
9048
+ const projectId = resolveVercelVar(appDir, "VERCEL_PROJECT_ID");
9049
+ const missing = [];
9050
+ if (!token) missing.push("VERCEL_TOKEN");
9051
+ if (!orgId) missing.push("VERCEL_ORG_ID");
9052
+ if (!projectId) missing.push("VERCEL_PROJECT_ID");
9053
+ if (missing.length > 0) return { missing };
9054
+ return {
9055
+ credentials: { token, orgId, projectId }
9056
+ };
9057
+ }
9045
9058
  var init_vercel_token = __esm({
9046
9059
  "packages/tooling/src/cli/setup/vercel-token.ts"() {
9047
9060
  "use strict";
@@ -16621,10 +16634,7 @@ async function setFirebaseSecret(key, value, projectId, dryRun = false, cwd) {
16621
16634
  }
16622
16635
  try {
16623
16636
  log.info(`Setting Firebase secret: ${key} (project: ${finalProjectId})`);
16624
- const tempDir = joinPath(process.cwd(), ".tmp");
16625
- await ensureDir(tempDir);
16626
- const tempFile = joinPath(tempDir, `secret-${key}-${Date.now()}.txt`);
16627
- await write(tempFile, value);
16637
+ const tempFile = "";
16628
16638
  try {
16629
16639
  const args = ["functions:secrets:set", key, "--project", finalProjectId];
16630
16640
  const firebaseCmd = process.platform === "win32" ? "firebase.cmd" : "firebase";
@@ -16699,9 +16709,6 @@ ${errorOutput}`
16699
16709
  }
16700
16710
  log.success(`Firebase secret ${key} set successfully`);
16701
16711
  } finally {
16702
- if (pathExists(tempFile)) {
16703
- await remove(tempFile);
16704
- }
16705
16712
  }
16706
16713
  } catch (err) {
16707
16714
  log.error(`Failed to set Firebase secret ${key}:`, err);
@@ -17934,7 +17941,7 @@ async function startSupabase(app, _projectRoot) {
17934
17941
  execSync5("supabase --version", { stdio: "pipe" });
17935
17942
  } catch {
17936
17943
  log.error("Supabase CLI not found. Install it:");
17937
- log.error(" npm install -g supabase\n");
17944
+ log.error(" bun install -g supabase\n");
17938
17945
  return 1;
17939
17946
  }
17940
17947
  const isWindows = platform3() === "win32";
@@ -18004,7 +18011,7 @@ async function startVercel(app, _projectRoot) {
18004
18011
  execSync6("vercel --version", { stdio: "pipe" });
18005
18012
  } catch {
18006
18013
  log.error("Vercel CLI not found. Install it:");
18007
- log.error(" npm install -g vercel\n");
18014
+ log.error(" bun install -g vercel\n");
18008
18015
  return 1;
18009
18016
  }
18010
18017
  const isWindows = platform4() === "win32";
@@ -18782,33 +18789,39 @@ init_cli_output();
18782
18789
  init_vercel_token();
18783
18790
  import { spawnSync as spawnSync6 } from "node:child_process";
18784
18791
  async function deployVercelFrontend(appDir, _config) {
18785
- const s = Y2();
18786
- s.start("Deploying frontend to Vercel...");
18787
- const token = resolveVercelToken(appDir);
18788
- if (token) {
18789
- log.debug("Using VERCEL_TOKEN from .env (token-based auth)");
18790
- }
18791
- const args = ["vercel", "--prod", "--yes"];
18792
- if (token) {
18793
- args.push("--token", token);
18792
+ const result = resolveVercelCredentials(appDir);
18793
+ if (result.missing) {
18794
+ throw new Error(
18795
+ `Missing Vercel credentials in .env.local: ${result.missing.join(", ")}
18796
+ Add them to apps/<app>/.env.local \u2014 see guides/dndev/SETUP_VERCEL.md`
18797
+ );
18794
18798
  }
18795
- try {
18796
- const result = spawnSync6("bunx", args, {
18799
+ const { token, orgId, projectId } = result.credentials;
18800
+ log.debug("Using Vercel credentials from .env (token-based auth)");
18801
+ log.info("Deploying to Vercel...");
18802
+ const deployResult = spawnSync6(
18803
+ "bunx",
18804
+ ["vercel", "deploy", "--prod", "--yes", "--token", token],
18805
+ {
18797
18806
  cwd: appDir,
18798
- stdio: "pipe",
18799
- encoding: "utf-8"
18800
- });
18801
- if (result.status !== 0) {
18802
- s.stop("Vercel deployment failed");
18803
- const errOutput = result.stderr?.trim();
18804
- throw new Error(
18805
- errOutput || `Vercel deploy exited with code ${result.status}`
18806
- );
18807
+ // stdout piped to capture deployment URL, stderr inherits for progress
18808
+ stdio: ["inherit", "pipe", "inherit"],
18809
+ encoding: "utf-8",
18810
+ env: {
18811
+ ...process.env,
18812
+ VERCEL_ORG_ID: orgId,
18813
+ VERCEL_PROJECT_ID: projectId
18814
+ }
18807
18815
  }
18808
- s.stop("Frontend deployed to Vercel");
18809
- } catch (err) {
18810
- s.stop("Vercel deployment failed");
18811
- throw err;
18816
+ );
18817
+ if (deployResult.status !== 0) {
18818
+ throw new Error(`vercel deploy exited with code ${deployResult.status}`);
18819
+ }
18820
+ const deployUrl = deployResult.stdout?.trim();
18821
+ if (deployUrl) {
18822
+ log.success(`Production: ${deployUrl}`);
18823
+ } else {
18824
+ log.success("Frontend deployed to Vercel");
18812
18825
  }
18813
18826
  }
18814
18827
 
@@ -18872,6 +18885,14 @@ function generateCleanPackageJson(functionsDir) {
18872
18885
  }
18873
18886
  const cleanPackageJson = { ...packageJson };
18874
18887
  if (cleanPackageJson.dependencies) {
18888
+ const removedDeps = Object.entries(cleanPackageJson.dependencies).filter(
18889
+ ([, version]) => String(version).startsWith("file:") || String(version).startsWith("workspace:")
18890
+ );
18891
+ if (removedDeps.length > 0) {
18892
+ log.warn(
18893
+ `Filtering out ${removedDeps.length} workspace/file dep(s) from dependencies: ${removedDeps.map(([name]) => name).join(", ")}`
18894
+ );
18895
+ }
18875
18896
  cleanPackageJson.dependencies = Object.fromEntries(
18876
18897
  Object.entries(cleanPackageJson.dependencies).filter(
18877
18898
  ([, version]) => !String(version).startsWith("file:") && !String(version).startsWith("workspace:")
@@ -18879,6 +18900,16 @@ function generateCleanPackageJson(functionsDir) {
18879
18900
  );
18880
18901
  }
18881
18902
  if (cleanPackageJson.devDependencies) {
18903
+ const removedDevDeps = Object.entries(
18904
+ cleanPackageJson.devDependencies
18905
+ ).filter(
18906
+ ([, version]) => String(version).startsWith("file:") || String(version).startsWith("workspace:")
18907
+ );
18908
+ if (removedDevDeps.length > 0) {
18909
+ log.warn(
18910
+ `Filtering out ${removedDevDeps.length} workspace/file dep(s) from devDependencies: ${removedDevDeps.map(([name]) => name).join(", ")}`
18911
+ );
18912
+ }
18882
18913
  cleanPackageJson.devDependencies = Object.fromEntries(
18883
18914
  Object.entries(cleanPackageJson.devDependencies).filter(
18884
18915
  ([, version]) => !String(version).startsWith("file:") && !String(version).startsWith("workspace:")
@@ -19170,7 +19201,7 @@ async function deployFunctions(appDir, serviceAccountPath, projectId, config) {
19170
19201
 
19171
19202
  To fix this, run:
19172
19203
  cd ${functionsDir}
19173
- npm install --production`,
19204
+ bun install --production`,
19174
19205
  "file-not-found",
19175
19206
  { context: { missingPackages, functionsDir } }
19176
19207
  );
@@ -19535,7 +19566,19 @@ function detectProvider(appDir) {
19535
19566
  const supabaseFunctionsDir = joinPath(supabaseDir, "functions");
19536
19567
  const supabaseMigrationsDir = joinPath(supabaseDir, "migrations");
19537
19568
  const hasFirebase = pathExists(firebaseJsonPath);
19538
- const hasSupabase = pathExists(supabaseDir) || pathExists(supabaseConfigPath);
19569
+ let hasSupabase = pathExists(supabaseDir) || pathExists(supabaseConfigPath);
19570
+ if (!hasSupabase) {
19571
+ try {
19572
+ const envPath = joinPath(appDir, ".env");
19573
+ if (pathExists(envPath)) {
19574
+ const envContent = readSync(envPath);
19575
+ if (envContent.match(/VITE_SUPABASE_URL=.+/)) {
19576
+ hasSupabase = true;
19577
+ }
19578
+ }
19579
+ } catch {
19580
+ }
19581
+ }
19539
19582
  let provider = "unknown";
19540
19583
  if (hasFirebase && hasSupabase) {
19541
19584
  provider = "both";
@@ -19899,7 +19942,7 @@ async function main6(options = {}) {
19899
19942
  if (shouldDeployVercelFrontend) {
19900
19943
  requireCLI(
19901
19944
  CLI_TOOLS.VERCEL,
19902
- "Vercel CLI is required to deploy the frontend.\nInstall: npm i -g vercel or use npx vercel"
19945
+ "Vercel CLI is required to deploy the frontend.\nInstall: bun install -g vercel"
19903
19946
  );
19904
19947
  }
19905
19948
  if (shouldDeployFirebaseFrontend && serviceAccountPath && config.project) {
@@ -20014,10 +20057,10 @@ function generateScripts(templateName, options) {
20014
20057
  scripts.lint = "eslint .";
20015
20058
  scripts["type-check"] = "tsc --noEmit";
20016
20059
  } else if (templateName === "consumer-root") {
20017
- scripts.dev = "turbo run dev";
20060
+ scripts.dev = "dndev dev";
20018
20061
  scripts.build = "turbo run build";
20019
20062
  scripts.lint = "turbo run lint";
20020
- scripts["type-check"] = "turbo run type-check";
20063
+ scripts["type-check"] = "dndev tc";
20021
20064
  } else if (templateName.includes("functions")) {
20022
20065
  scripts.build = "node build.mjs";
20023
20066
  scripts["build:tsc"] = "tsc";
@@ -20028,9 +20071,9 @@ function generateScripts(templateName, options) {
20028
20071
  scripts.dev = "vercel dev";
20029
20072
  }
20030
20073
  } else if (templateName === "demo") {
20031
- scripts.dev = "bunx vite";
20032
- scripts.build = "tsc --noEmit && bunx vite build";
20033
- scripts.preview = "bunx vite preview";
20074
+ scripts.dev = "vite";
20075
+ scripts.build = "tsc --noEmit && vite build --mode production";
20076
+ scripts.preview = "vite preview";
20034
20077
  scripts["type-check"] = "tsc --noEmit";
20035
20078
  } else if (templateName === "entities") {
20036
20079
  }
@@ -20468,7 +20511,7 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
20468
20511
  const firebaseJson = readSync(firebaseJsonDest, {
20469
20512
  format: "json"
20470
20513
  });
20471
- if (firebaseJson.hosting?.rewrites) {
20514
+ if (firebaseJson.hosting?.rewrites && Array.isArray(firebaseJson.hosting.rewrites)) {
20472
20515
  firebaseJson.hosting.rewrites = firebaseJson.hosting.rewrites.filter(
20473
20516
  (r2) => r2.destination !== "/index.html"
20474
20517
  );
@@ -20756,6 +20799,14 @@ async function main9(options) {
20756
20799
  process.exit(0);
20757
20800
  }
20758
20801
  if (action === "replace") {
20802
+ const confirmDelete = await askForConfirmation(
20803
+ `This will permanently delete "${projectDirNormalized}". Are you sure?`,
20804
+ false
20805
+ );
20806
+ if (!confirmDelete) {
20807
+ Se("Project creation cancelled.");
20808
+ process.exit(0);
20809
+ }
20759
20810
  const s2 = Y2();
20760
20811
  s2.start("Removing existing project...");
20761
20812
  await remove(projectDirNormalized);
@@ -20810,7 +20861,8 @@ async function main9(options) {
20810
20861
  Me(`Configuring "${trimmedName}"...`, "\u2699\uFE0F");
20811
20862
  const config = await collectAppConfig(trimmedName);
20812
20863
  appConfigs[trimmedName] = config;
20813
- if (config.backend !== "none" || config.functions !== "none") anyAppNeedsBackend = true;
20864
+ if (config.backend !== "none" || config.functions !== "none")
20865
+ anyAppNeedsBackend = true;
20814
20866
  }
20815
20867
  let installDemoApp = await askForConfirmation(
20816
20868
  "Would you like to install the demo app? (component showcase)",
@@ -20936,7 +20988,9 @@ async function main9(options) {
20936
20988
  overwrite: true
20937
20989
  });
20938
20990
  const relativeMonorepoPath = executionMode === "development" ? calculateRelativePath(projectDirNormalized, monorepoRoot) : "";
20939
- const primaryPlatform = Object.values(appConfigs).find((c) => c.backend !== "none")?.backend ?? "firebase";
20991
+ const primaryPlatform = Object.values(appConfigs).find(
20992
+ (c) => c.backend !== "none"
20993
+ )?.backend ?? "firebase";
20940
20994
  const rootPackageJson = generatePackageJson(
20941
20995
  "consumer-root",
20942
20996
  executionMode,
@@ -21111,7 +21165,10 @@ async function main9(options) {
21111
21165
  await createApp(appName, appConfig, projectDirNormalized, templatesRoot);
21112
21166
  }
21113
21167
  s.start("Updating root package.json with scripts...");
21114
- await updateRootPackageJson(projectDirNormalized, appNames);
21168
+ await updateRootPackageJson(
21169
+ projectDirNormalized,
21170
+ isMergeMode ? allAppNames : appNames
21171
+ );
21115
21172
  s.stop("Root package.json updated");
21116
21173
  Se("\u{1F389} Project created successfully!");
21117
21174
  const cdCommand = executionMode === "development" ? `cd ../${projectName}` : `cd ${projectName}`;
@@ -21297,13 +21354,16 @@ async function addPathComments(files, rootDir, dryRun, verbose) {
21297
21354
  let useClientLine = -1;
21298
21355
  let useClientValue = "";
21299
21356
  if (!isCss) {
21300
- for (let i = 0; i < Math.min(5, contentLines.length); i++) {
21357
+ for (let i = 0; i < contentLines.length; i++) {
21301
21358
  const line = contentLines[i]?.trim();
21302
21359
  if (line === '"use client";' || line === "'use client';") {
21303
21360
  useClientLine = i;
21304
21361
  useClientValue = line;
21305
21362
  break;
21306
21363
  }
21364
+ if (line?.startsWith("import ") || line?.startsWith("export ") || line?.startsWith("function ") || line?.startsWith("class ") || line?.startsWith("const ") || line?.startsWith("let ") || line?.startsWith("var ")) {
21365
+ break;
21366
+ }
21307
21367
  }
21308
21368
  }
21309
21369
  const invalidFormat = isCss ? COMMENT_FORMATS[".ts"] : null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@donotdev/cli",
3
- "version": "0.0.18",
3
+ "version": "0.0.20",
4
4
  "description": "Command-line interface for DoNotDev Framework",
5
5
  "type": "module",
6
6
  "private": false,
@@ -1,24 +1,161 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en">
3
+
3
4
  <head>
4
5
  <meta charset="UTF-8" />
6
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
7
+
8
+ <!-- Meta tags -->
5
9
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>DoNotDev Components Demo</title>
7
-
8
- <!-- ✅ PERFORMANCE: Critical font preloads (loads before CSS) -->
9
- <link rel="preload" href="/fonts/Inter-latin.woff2" as="font" type="font/woff2" crossorigin="anonymous">
10
-
10
+ <title>DoNotDev Demo</title>
11
+
12
+ <!-- Fonts: Inter, Space Grotesk, Playfair, Roboto from @donotdev/ui/dndev.css (bundled). -->
13
+
14
+ <!-- ✅ CRITICAL CSS: ECG waveform loader -->
11
15
  <style>
12
- body {
13
- margin: 0;
14
- font-family: var(--font-family, system-ui, sans-serif);
16
+ /* Critical above-the-fold styles */
17
+ html, body {
18
+ margin: 0;
19
+ padding: 0;
20
+ box-sizing: border-box;
21
+ }
22
+ body {
23
+ font-family: 'Inter', var(--font-family, ui-sans-serif, system-ui, -apple-system, sans-serif);
24
+ line-height: 1.5;
25
+ -webkit-font-smoothing: antialiased;
26
+ -moz-osx-font-smoothing: grayscale;
27
+ background: #ffffff;
28
+ color: #000000;
29
+ }
30
+ @media (prefers-color-scheme: dark) {
31
+ body {
32
+ background: #000000;
33
+ color: #ffffff;
34
+ }
35
+ }
36
+ /* Critical shell loader styles - pure CSS, instant render */
37
+ #shell-loader {
38
+ position: fixed;
39
+ inset: 0;
15
40
  background: #000000;
16
- color: #ffffff;
41
+ display: flex;
42
+ align-items: center;
43
+ justify-content: center;
44
+ z-index: 9999;
45
+ opacity: 1;
46
+ transition: opacity 0.3s ease-out;
47
+ will-change: opacity;
48
+ margin: 0;
49
+ padding: 0;
50
+ box-sizing: border-box;
51
+ }
52
+ #shell-loader.shell-loader--fading {
53
+ opacity: 0;
54
+ pointer-events: none;
55
+ }
56
+ .shell-loader__content {
57
+ text-align: center;
58
+ color: white;
59
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
60
+ width: 100%;
61
+ max-width: 500px;
62
+ margin: 0;
63
+ padding: 0;
64
+ box-sizing: border-box;
65
+ line-height: 1.2;
66
+ }
67
+ .shell-loader__brand {
68
+ display: block;
69
+ font-size: clamp(3rem, 10vw, 5rem);
70
+ font-weight: 800;
71
+ letter-spacing: -0.05em;
72
+ margin: 0 0 1rem 0;
73
+ padding: 0;
74
+ box-sizing: border-box;
75
+ }
76
+ /* ECG Waveform Animation */
77
+ .shell-loader__dots {
78
+ display: block;
79
+ width: 300px;
80
+ height: 60px;
81
+ margin: 0 auto;
82
+ padding: 0;
83
+ box-sizing: border-box;
84
+ }
85
+ .shell-loader__dots svg {
86
+ width: 100%;
87
+ height: 100%;
88
+ display: block;
89
+ }
90
+ .shell-loader__dots path {
91
+ stroke: #667eea;
92
+ stroke-width: 3;
93
+ fill: none;
94
+ stroke-linecap: round;
95
+ stroke-linejoin: round;
96
+ stroke-dasharray: 400;
97
+ stroke-dashoffset: 400;
98
+ animation: ecg-draw 2s linear infinite;
99
+ }
100
+ @keyframes ecg-draw {
101
+ 0% {
102
+ stroke-dashoffset: 400;
103
+ opacity: 0;
104
+ }
105
+ 10% {
106
+ opacity: 1;
107
+ }
108
+ 70% {
109
+ stroke-dashoffset: 0;
110
+ opacity: 1;
111
+ }
112
+ 90%, 100% {
113
+ stroke-dashoffset: 0;
114
+ opacity: 0;
115
+ }
17
116
  }
18
117
  </style>
118
+
119
+ <!-- ✅ THEME DETECTION: Force dark on first visit, remember user choice -->
120
+ <script>
121
+ (function () {
122
+ 'use strict';
123
+
124
+ function getInitialTheme() {
125
+ try {
126
+ var saved = localStorage.getItem('dndev-theme');
127
+ if (saved) {
128
+ return saved;
129
+ }
130
+ return 'dark';
131
+ } catch (e) {
132
+ return 'dark';
133
+ }
134
+ }
135
+
136
+ var theme = getInitialTheme();
137
+ document.documentElement.className = theme;
138
+ })();
139
+ </script>
19
140
  </head>
141
+
20
142
  <body>
143
+ <!-- ✅ SHELL LOADER: Branded loading experience before React loads -->
144
+ <div id="shell-loader">
145
+ <div class="shell-loader__content">
146
+ <span class="shell-loader__brand">DoNotDev</span>
147
+ <span class="shell-loader__dots">
148
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 60" preserveAspectRatio="xMidYMid meet">
149
+ <path d="M0,30 L100,30 L110,20 L120,30 L130,30 L140,5 L150,55 L160,30 L175,30 L190,20 L205,30 L300,30" />
150
+ </svg>
151
+ </span>
152
+ </div>
153
+ </div>
154
+
155
+ <!-- React mounts here -->
21
156
  <div id="root"></div>
157
+
22
158
  <script type="module" src="/src/main.tsx"></script>
23
159
  </body>
24
- </html>
160
+
161
+ </html>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500" xmlns:v="https://vecta.io/nano"><path d="M11.995 68.133c-.747.14-2.114 1.276-2.986 2.409l-1.557 2.199-.062 104.273.684 251.717c.935 2.835 3.423 4.749 6.347 4.89 2.366.142 3.61-.566 10.767-5.599l42.311-30.054L112.3 366.14l16.366-11.768c3.234-2.268 6.098-4.749 6.346-5.599 1.369-3.828 9.271-32.679 9.023-32.891-.124-.213-1.743.78-3.547 2.198-1.803 1.347-8.773 6.309-15.432 10.916L87.1 355.862l-24.891 17.65-23.831 16.729c-5.413 3.898-10.143 7.017-10.454 7.017-.685 0-.809-291.837-.063-292.334.249-.141 1.619.497 3.049 1.559l51.521 37.711 18.668 13.61 20.222 14.674 13.69 9.996 9.333 6.734 12.756 9.215c10.455 7.798 15.992 11.767 16.553 11.908.374.073 1.99-4.889 3.609-11.058l3.048-11.202-5.537-4.038-10.641-7.799c-2.863-1.984-10.391-7.584-16.8-12.405l-23.21-17.154-20.721-15.24L89.4 121.157c-2.613-1.986-7.653-5.671-11.2-8.223L23.506 73.096c-6.471-4.679-8.774-5.671-11.512-4.962l.001-.001zm235.829 4.466c-1.057.708-2.302 2.055-2.737 2.977-.622 1.276-.809 14.673-.746 62.733l.062 61.104 4.915 8.01 10.206 16.871 5.225 8.861.187-62.308 1.057-61.812c.56.212 6.098 4.111 12.321 8.648l43.806 31.97c1.307.991 1.431.708 5.973-9.641l4.667-10.705-1.618-1.346-14.747-10.845-20.844-15.313-36.65-26.864c-5.788-4.182-7.841-4.608-11.077-2.34zm-34.784 196.85l-7.279 15.807-11.511 25.166c.123.141 5.351-3.474 11.697-7.939l18.356-13.042 8.027-5.813c1.057-.922.685-1.701-6.347-13.469l-7.466-12.546-5.477 11.838v-.002z" fill="var(--primary,#dc143c)"/><path d="M376.752 57.145l-4.977 11.2c-1.432 2.907-4.792 10.066-7.468 15.95l-9.955 21.619-25.388 54.583-11.2 24.101-20.658 43.949-11.7 24.81-7.84 16.304c-.809 1.347-.621 1.631-15.679-23.747l-26.072-43.949-22.213-37.71c-8.587-14.815-10.267-16.73-12.322-14.319-.435.566-2.676 8.009-4.978 16.586l-22.711 82.228-13.378 47.494-8.153 29.064-18.232 64.86-12.133 43.382-4.355 16.162c.186 0 3.671-7.443 14.871-31.898l10.578-22.684 8.088-17.013 8.774-18.43 9.771-20.556 7.901-16.659 9.333-19.848 9.957-21.267 10.765-23.038c6.844-14.957 9.397-20.061 10.08-20.273.374-.142 3.485 4.606 6.968 10.562l24.828 41.255 31.981 52.809c5.289 8.932 6.846 11.06 8.153 11.2.87.142 1.929-.212 2.302-.779.685-.851 19.6-65.499 44.054-150.421l25.823-88.889 17.798-62.168c-.125-.141-1.308 2.34-2.615 5.53h.002z" fill="var(--accent,#ffd700)"/><path d="M359.081 153.904l-3.111 11.555c-1.369 4.89-2.302 9.074-2.053 9.287s5.041 3.757 10.703 7.869l33.289 24.314 37.645 27.505 19.601 14.318 6.409 4.536c2.489 1.49 5.538-.991-32.542 26.369l-38.269 27.432-31.236 22.402-33.913 24.456-28.187 20.273-12.134 8.648c-10.019 7.16-19.413 13.681-19.848 13.681-.188 0-.374-14.248-.374-31.757v-31.686l-4.419-7.088-10.019-16.518c-3.111-5.102-5.849-9.356-6.098-9.356s-.375 11.909-.249 26.37l.249 64.223v37.711l2.054 2.623c1.866 2.268 2.489 2.553 4.914 2.553 3.237 0 4.169-.568 18.855-11.202l76.535-55.291 21.78-15.807 120.403-86.411c3.67-2.552 5.102-4.748 5.475-8.434.188-2.409 0-3.971-.746-5.599-1.244-2.623-2.677-3.686-48.908-37.711l-51.023-37.642-14.624-10.774-12.88-9.427c-2.986-2.199-5.724-4.041-6.035-4.041-.374 0-.934 1.206-1.245 2.622l.001-.003z" fill="var(--primary,#dc143c)"/></svg>
@@ -1,14 +1,15 @@
1
+ // apps/demo/src/App.tsx
2
+
1
3
  /**
2
- * @fileoverview Main application component
3
- * @description Root application component with configuration-driven architecture
4
- * @version 0.0.4
4
+ * @fileoverview Main application component for the demo app
5
+ * @description Root component that configures the application with Vite providers and layout.
6
+ * @version 0.0.5
5
7
  * @since 0.0.1
6
8
  * @author AMBROISE PARK Consulting
7
9
  */
8
10
 
9
11
  import { ViteAppProviders } from '@donotdev/ui/vite';
10
12
 
11
- import './config/providers';
12
13
  import { appConfig } from './config/app';
13
14
 
14
15
  /**
@@ -20,17 +21,12 @@ import { appConfig } from './config/app';
20
21
  *
21
22
  * Note: HomePage.tsx in src/pages/ is automatically used for the root route "/"
22
23
  *
23
- * @version 0.0.4
24
+ * @version 0.0.5
24
25
  * @since 0.0.1
25
26
  * @author AMBROISE PARK Consulting
26
27
  */
27
28
  export function App() {
28
29
  return (
29
- <ViteAppProviders
30
- config={appConfig}
31
- layout={{
32
- breadcrumbs: 'smart', // 'smart' | 'always' | 'never'
33
- }}
34
- />
30
+ <ViteAppProviders config={appConfig} layout={{ breadcrumbs: 'smart' }} />
35
31
  );
36
32
  }