@donotdev/cli 0.0.18 → 0.0.19

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 (131) hide show
  1. package/dependencies-matrix.json +55 -156
  2. package/dist/bin/commands/coach.js +8177 -0
  3. package/dist/bin/commands/create-app.js +5 -5
  4. package/dist/bin/commands/create-project.js +10 -7
  5. package/dist/bin/commands/deploy.js +81 -59
  6. package/dist/bin/commands/doctor.js +243 -698
  7. package/dist/bin/commands/emu.js +2 -2
  8. package/dist/bin/commands/format.js +4 -1
  9. package/dist/bin/commands/get-demo.js +8351 -0
  10. package/dist/bin/commands/make-admin.js +773 -152
  11. package/dist/bin/commands/setup.js +519 -1711
  12. package/dist/bin/commands/staging.js +17852 -0
  13. package/dist/bin/commands/sync-secrets.js +2 -11
  14. package/dist/bin/commands/type-check.js +7733 -1713
  15. package/dist/bin/dndev.js +913 -185
  16. package/dist/bin/donotdev.js +913 -185
  17. package/dist/index.js +96 -65
  18. package/package.json +1 -1
  19. package/templates/app-demo/index.html.example +147 -10
  20. package/templates/app-demo/src/App.tsx.example +7 -13
  21. package/templates/app-demo/src/config/app.ts.example +12 -48
  22. package/templates/app-demo/src/entities/product.ts.example +38 -0
  23. package/templates/app-demo/src/globals.css.example +5 -1
  24. package/templates/app-demo/src/main.tsx.example +13 -7
  25. package/templates/app-demo/src/pages/ChangelogPage.tsx.example +14 -0
  26. package/templates/app-demo/src/pages/DashboardPage.tsx.example +15 -0
  27. package/templates/app-demo/src/pages/HomePage.tsx.example +3 -77
  28. package/templates/app-demo/src/pages/PricingPage.tsx.example +14 -0
  29. package/templates/app-demo/src/pages/ProductsPage.tsx.example +17 -0
  30. package/templates/app-demo/src/pages/ProfilePage.tsx.example +16 -0
  31. package/templates/app-demo/src/pages/SettingsPage.tsx.example +15 -0
  32. package/templates/app-demo/src/pages/ShowcaseDetailPage.tsx.example +112 -0
  33. package/templates/app-demo/src/pages/ShowcasePage.tsx.example +91 -0
  34. package/templates/app-demo/src/pages/legal/LegalPage.tsx.example +14 -0
  35. package/templates/app-demo/src/pages/legal/PrivacyPage.tsx.example +14 -0
  36. package/templates/app-demo/src/pages/legal/TermsPage.tsx.example +14 -0
  37. package/templates/app-demo/tsconfig.json.example +1 -1
  38. package/templates/app-demo/vite.config.ts.example +23 -48
  39. package/templates/app-expo/README.md.example +1 -1
  40. package/templates/app-expo/app/index.tsx.example +1 -1
  41. package/templates/app-vite/src/pages/HomePage.tsx.example +8 -10
  42. package/templates/overlay-firebase/env.fragment.example +1 -1
  43. package/templates/overlay-firebase/env.fragment.expo.example +1 -1
  44. package/templates/overlay-firebase/env.fragment.nextjs.example +1 -1
  45. package/templates/overlay-supabase/env.fragment.example +1 -1
  46. package/templates/overlay-supabase/env.fragment.expo.example +1 -1
  47. package/templates/overlay-supabase/env.fragment.nextjs.example +1 -1
  48. package/templates/overlay-vercel/env.fragment.example +1 -1
  49. package/templates/overlay-vercel/env.fragment.nextjs.example +1 -1
  50. package/templates/root-consumer/AI.md.example +4 -3
  51. package/templates/root-consumer/guides/dndev/AGENT_START_HERE.md.example +21 -6
  52. package/templates/root-consumer/guides/dndev/COMPONENTS_ADV.md.example +16 -179
  53. package/templates/root-consumer/guides/dndev/ENV_SETUP.md.example +19 -21
  54. package/templates/root-consumer/guides/dndev/GOTCHAS.md.example +14 -3
  55. package/templates/root-consumer/guides/dndev/INDEX.md.example +2 -2
  56. package/templates/root-consumer/guides/dndev/SETUP_APP_CONFIG.md.example +3 -3
  57. package/templates/root-consumer/guides/dndev/SETUP_BLOG.md.example +19 -2
  58. package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +35 -1
  59. package/templates/root-consumer/guides/dndev/SETUP_FIREBASE.md.example +17 -12
  60. package/templates/root-consumer/guides/dndev/SETUP_LAYOUTS.md.example +32 -0
  61. package/templates/root-consumer/guides/dndev/SETUP_OAUTH_PROVIDERS.md.example +1 -1
  62. package/templates/root-consumer/guides/dndev/SETUP_PAGES.md.example +19 -15
  63. package/templates/root-consumer/guides/dndev/SETUP_STRIPE.md.example +2 -2
  64. package/templates/root-consumer/guides/dndev/SETUP_SUPABASE.md.example +17 -12
  65. package/templates/root-consumer/guides/dndev/SETUP_VERCEL.md.example +37 -16
  66. package/templates/root-consumer/guides/dndev/USE_ROUTING.md.example +18 -18
  67. package/templates/root-consumer/guides/dndev/essences_reference.css.example +119 -2
  68. package/templates/root-consumer/guides/wai-way/blueprints/1_scaffold.md.example +14 -0
  69. package/templates/root-consumer/guides/wai-way/blueprints/2_entities.md.example +6 -0
  70. package/templates/root-consumer/guides/wai-way/blueprints/3_compose.md.example +14 -0
  71. package/templates/root-consumer/guides/wai-way/entity_patterns.md.example +4 -5
  72. package/templates/root-consumer/guides/wai-way/page_patterns.md.example +2 -2
  73. package/dist/bin/commands/agent-setup.d.ts +0 -6
  74. package/dist/bin/commands/agent-setup.d.ts.map +0 -1
  75. package/dist/bin/commands/agent-setup.js.map +0 -1
  76. package/dist/bin/commands/build.d.ts +0 -11
  77. package/dist/bin/commands/build.d.ts.map +0 -1
  78. package/dist/bin/commands/build.js.map +0 -1
  79. package/dist/bin/commands/bump.d.ts +0 -11
  80. package/dist/bin/commands/bump.d.ts.map +0 -1
  81. package/dist/bin/commands/bump.js.map +0 -1
  82. package/dist/bin/commands/cacheout.d.ts +0 -11
  83. package/dist/bin/commands/cacheout.d.ts.map +0 -1
  84. package/dist/bin/commands/cacheout.js.map +0 -1
  85. package/dist/bin/commands/create-app.d.ts +0 -11
  86. package/dist/bin/commands/create-app.d.ts.map +0 -1
  87. package/dist/bin/commands/create-app.js.map +0 -1
  88. package/dist/bin/commands/create-project.d.ts +0 -11
  89. package/dist/bin/commands/create-project.d.ts.map +0 -1
  90. package/dist/bin/commands/create-project.js.map +0 -1
  91. package/dist/bin/commands/deploy.d.ts +0 -11
  92. package/dist/bin/commands/deploy.d.ts.map +0 -1
  93. package/dist/bin/commands/deploy.js.map +0 -1
  94. package/dist/bin/commands/dev.d.ts +0 -11
  95. package/dist/bin/commands/dev.d.ts.map +0 -1
  96. package/dist/bin/commands/dev.js.map +0 -1
  97. package/dist/bin/commands/doctor.d.ts +0 -6
  98. package/dist/bin/commands/doctor.d.ts.map +0 -1
  99. package/dist/bin/commands/doctor.js.map +0 -1
  100. package/dist/bin/commands/emu.d.ts +0 -11
  101. package/dist/bin/commands/emu.d.ts.map +0 -1
  102. package/dist/bin/commands/emu.js.map +0 -1
  103. package/dist/bin/commands/format.d.ts +0 -11
  104. package/dist/bin/commands/format.d.ts.map +0 -1
  105. package/dist/bin/commands/format.js.map +0 -1
  106. package/dist/bin/commands/make-admin.d.ts +0 -11
  107. package/dist/bin/commands/make-admin.d.ts.map +0 -1
  108. package/dist/bin/commands/make-admin.js.map +0 -1
  109. package/dist/bin/commands/preview.d.ts +0 -11
  110. package/dist/bin/commands/preview.d.ts.map +0 -1
  111. package/dist/bin/commands/preview.js.map +0 -1
  112. package/dist/bin/commands/setup.d.ts +0 -6
  113. package/dist/bin/commands/setup.d.ts.map +0 -1
  114. package/dist/bin/commands/setup.js.map +0 -1
  115. package/dist/bin/commands/sync-secrets.d.ts +0 -11
  116. package/dist/bin/commands/sync-secrets.d.ts.map +0 -1
  117. package/dist/bin/commands/sync-secrets.js.map +0 -1
  118. package/dist/bin/commands/type-check.d.ts +0 -14
  119. package/dist/bin/commands/type-check.d.ts.map +0 -1
  120. package/dist/bin/commands/type-check.js.map +0 -1
  121. package/dist/bin/commands/wai.d.ts +0 -11
  122. package/dist/bin/commands/wai.d.ts.map +0 -1
  123. package/dist/bin/commands/wai.js.map +0 -1
  124. package/dist/index.d.ts +0 -8
  125. package/dist/index.d.ts.map +0 -1
  126. package/dist/index.js.map +0 -1
  127. package/templates/app-demo/src/components/ThemeToggle.tsx.example +0 -48
  128. package/templates/app-demo/src/pages/DetailPage.tsx.example +0 -103
  129. package/templates/app-demo/src/pages/FullPage.tsx.example +0 -142
  130. package/templates/app-demo/src/pages/components/DemoLayout.tsx.example +0 -266
  131. 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
 
@@ -19170,7 +19183,7 @@ async function deployFunctions(appDir, serviceAccountPath, projectId, config) {
19170
19183
 
19171
19184
  To fix this, run:
19172
19185
  cd ${functionsDir}
19173
- npm install --production`,
19186
+ bun install --production`,
19174
19187
  "file-not-found",
19175
19188
  { context: { missingPackages, functionsDir } }
19176
19189
  );
@@ -19535,7 +19548,19 @@ function detectProvider(appDir) {
19535
19548
  const supabaseFunctionsDir = joinPath(supabaseDir, "functions");
19536
19549
  const supabaseMigrationsDir = joinPath(supabaseDir, "migrations");
19537
19550
  const hasFirebase = pathExists(firebaseJsonPath);
19538
- const hasSupabase = pathExists(supabaseDir) || pathExists(supabaseConfigPath);
19551
+ let hasSupabase = pathExists(supabaseDir) || pathExists(supabaseConfigPath);
19552
+ if (!hasSupabase) {
19553
+ try {
19554
+ const envPath = joinPath(appDir, ".env");
19555
+ if (pathExists(envPath)) {
19556
+ const envContent = readSync(envPath);
19557
+ if (envContent.match(/VITE_SUPABASE_URL=.+/)) {
19558
+ hasSupabase = true;
19559
+ }
19560
+ }
19561
+ } catch {
19562
+ }
19563
+ }
19539
19564
  let provider = "unknown";
19540
19565
  if (hasFirebase && hasSupabase) {
19541
19566
  provider = "both";
@@ -19899,7 +19924,7 @@ async function main6(options = {}) {
19899
19924
  if (shouldDeployVercelFrontend) {
19900
19925
  requireCLI(
19901
19926
  CLI_TOOLS.VERCEL,
19902
- "Vercel CLI is required to deploy the frontend.\nInstall: npm i -g vercel or use npx vercel"
19927
+ "Vercel CLI is required to deploy the frontend.\nInstall: bun install -g vercel"
19903
19928
  );
19904
19929
  }
19905
19930
  if (shouldDeployFirebaseFrontend && serviceAccountPath && config.project) {
@@ -20014,10 +20039,10 @@ function generateScripts(templateName, options) {
20014
20039
  scripts.lint = "eslint .";
20015
20040
  scripts["type-check"] = "tsc --noEmit";
20016
20041
  } else if (templateName === "consumer-root") {
20017
- scripts.dev = "turbo run dev";
20042
+ scripts.dev = "dndev dev";
20018
20043
  scripts.build = "turbo run build";
20019
20044
  scripts.lint = "turbo run lint";
20020
- scripts["type-check"] = "turbo run type-check";
20045
+ scripts["type-check"] = "dndev tc";
20021
20046
  } else if (templateName.includes("functions")) {
20022
20047
  scripts.build = "node build.mjs";
20023
20048
  scripts["build:tsc"] = "tsc";
@@ -20028,9 +20053,9 @@ function generateScripts(templateName, options) {
20028
20053
  scripts.dev = "vercel dev";
20029
20054
  }
20030
20055
  } else if (templateName === "demo") {
20031
- scripts.dev = "bunx vite";
20032
- scripts.build = "tsc --noEmit && bunx vite build";
20033
- scripts.preview = "bunx vite preview";
20056
+ scripts.dev = "vite";
20057
+ scripts.build = "tsc --noEmit && vite build --mode production";
20058
+ scripts.preview = "vite preview";
20034
20059
  scripts["type-check"] = "tsc --noEmit";
20035
20060
  } else if (templateName === "entities") {
20036
20061
  }
@@ -20810,7 +20835,8 @@ async function main9(options) {
20810
20835
  Me(`Configuring "${trimmedName}"...`, "\u2699\uFE0F");
20811
20836
  const config = await collectAppConfig(trimmedName);
20812
20837
  appConfigs[trimmedName] = config;
20813
- if (config.backend !== "none" || config.functions !== "none") anyAppNeedsBackend = true;
20838
+ if (config.backend !== "none" || config.functions !== "none")
20839
+ anyAppNeedsBackend = true;
20814
20840
  }
20815
20841
  let installDemoApp = await askForConfirmation(
20816
20842
  "Would you like to install the demo app? (component showcase)",
@@ -20936,7 +20962,9 @@ async function main9(options) {
20936
20962
  overwrite: true
20937
20963
  });
20938
20964
  const relativeMonorepoPath = executionMode === "development" ? calculateRelativePath(projectDirNormalized, monorepoRoot) : "";
20939
- const primaryPlatform = Object.values(appConfigs).find((c) => c.backend !== "none")?.backend ?? "firebase";
20965
+ const primaryPlatform = Object.values(appConfigs).find(
20966
+ (c) => c.backend !== "none"
20967
+ )?.backend ?? "firebase";
20940
20968
  const rootPackageJson = generatePackageJson(
20941
20969
  "consumer-root",
20942
20970
  executionMode,
@@ -21297,13 +21325,16 @@ async function addPathComments(files, rootDir, dryRun, verbose) {
21297
21325
  let useClientLine = -1;
21298
21326
  let useClientValue = "";
21299
21327
  if (!isCss) {
21300
- for (let i = 0; i < Math.min(5, contentLines.length); i++) {
21328
+ for (let i = 0; i < contentLines.length; i++) {
21301
21329
  const line = contentLines[i]?.trim();
21302
21330
  if (line === '"use client";' || line === "'use client';") {
21303
21331
  useClientLine = i;
21304
21332
  useClientValue = line;
21305
21333
  break;
21306
21334
  }
21335
+ if (line?.startsWith("import ") || line?.startsWith("export ") || line?.startsWith("function ") || line?.startsWith("class ") || line?.startsWith("const ") || line?.startsWith("let ") || line?.startsWith("var ")) {
21336
+ break;
21337
+ }
21307
21338
  }
21308
21339
  }
21309
21340
  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.19",
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>
@@ -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,10 @@ 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
- return (
29
- <ViteAppProviders
30
- config={appConfig}
31
- layout={{
32
- breadcrumbs: 'smart', // 'smart' | 'always' | 'never'
33
- }}
34
- />
35
- );
29
+ return <ViteAppProviders config={appConfig} layout={{ breadcrumbs: 'smart' }} />;
36
30
  }
@@ -1,46 +1,22 @@
1
1
  /**
2
2
  * @fileoverview Application configuration
3
- * @description Defines application metadata and feature flags
4
- * @version 0.0.1
3
+ * @description Defines application metadata, layout preset, and feature flags
4
+ * @version 0.1.0
5
5
  * @since 0.0.1
6
6
  * @author AMBROISE PARK Consulting
7
7
  */
8
8
 
9
9
  import type { AppConfig } from '@donotdev/core';
10
10
 
11
- /**
12
- * Application name constant
13
- *
14
- * @version 0.0.1
15
- * @since 0.0.1
16
- * @author AMBROISE PARK Consulting
17
- */
18
- export const APP_NAME = '{{appName}}';
11
+ export const APP_NAME = 'DoNotDev';
12
+ export const APP_SHORT_NAME = 'DoNotDev';
13
+ export const APP_DESCRIPTION = 'DoNotDev SaaS Template';
19
14
 
20
15
  /**
21
- * Application short name constant
16
+ * Application configuration
22
17
  *
23
- * @version 0.0.1
24
- * @since 0.0.1
25
- * @author AMBROISE PARK Consulting
26
- */
27
- export const APP_SHORT_NAME = '{{appShortName}}';
28
-
29
- /**
30
- * Application description constant
31
- *
32
- * @version 0.0.1
33
- * @since 0.0.1
34
- * @author AMBROISE PARK Consulting
35
- */
36
- export const APP_DESCRIPTION = 'DoNotDev Components Demo';
37
-
38
- /**
39
- * Application configuration object
40
- *
41
- * @version 0.0.1
42
- * @since 0.0.1
43
- * @author AMBROISE PARK Consulting
18
+ * - preset: 'landing' is the app default. Pages can override via PageMeta.preset.
19
+ * - auth: Configure auth routes and menu items.
44
20
  */
45
21
  export const appConfig: AppConfig = {
46
22
  app: {
@@ -48,21 +24,9 @@ export const appConfig: AppConfig = {
48
24
  shortName: APP_SHORT_NAME,
49
25
  description: APP_DESCRIPTION,
50
26
  },
51
- preset: 'landing', // 'landing' | 'admin' | 'moolti' | 'docs' | 'blog' | 'game' | 'plain'
52
- features: {
53
- // Optional: Enable debug tools in development
54
- // debug: true,
27
+ preset: 'landing',
28
+ auth: {
29
+ authRoute: '/pricing',
30
+ profilePath: '/profile',
55
31
  },
56
- // Optional: Override query cache defaults
57
- // Framework defaults (infinite cache - cost-optimized):
58
- // - staleTime: Infinity (data never becomes stale)
59
- // - refetchOnWindowFocus: false (no auto-refetch on focus)
60
- // - refetchOnReconnect: false (no auto-refetch on reconnect)
61
- // This minimizes API costs and is ideal for single-admin apps with manual refresh buttons.
62
- // Uncomment below to enable auto-refetch behavior:
63
- // query: {
64
- // staleTime: 1000 * 60 * 5, // 5 minutes - data becomes stale after 5 minutes
65
- // refetchOnWindowFocus: true, // Automatically refetch when window regains focus
66
- // refetchOnReconnect: true, // Automatically refetch when network reconnects
67
- // },
68
32
  };
@@ -0,0 +1,38 @@
1
+ import { defineEntity } from '@donotdev/core';
2
+
3
+ export const productEntity = defineEntity({
4
+ name: 'Product',
5
+ collection: 'products',
6
+ fields: {
7
+ name: {
8
+ type: 'text',
9
+ visibility: 'user',
10
+ validation: { required: true, minLength: 3 },
11
+ },
12
+ description: {
13
+ type: 'textarea',
14
+ visibility: 'user',
15
+ },
16
+ price: {
17
+ type: 'number',
18
+ visibility: 'user',
19
+ validation: { required: true, min: 0 },
20
+ },
21
+ category: {
22
+ type: 'select',
23
+ visibility: 'user',
24
+ validation: {
25
+ options: [
26
+ { value: 'electronics', label: 'Electronics' },
27
+ { value: 'clothing', label: 'Clothing' },
28
+ { value: 'food', label: 'Food & Drink' },
29
+ { value: 'other', label: 'Other' },
30
+ ],
31
+ },
32
+ },
33
+ image: {
34
+ type: 'image',
35
+ visibility: 'user',
36
+ },
37
+ },
38
+ });
@@ -1,4 +1,8 @@
1
1
  /* apps/demo/src/globals.css */
2
2
 
3
- @import '@donotdev/components/styles';
3
+ /* 1. Group all imports at the top. */
4
+ @import '@donotdev/ui/dndev.css';
4
5
  @import './themes.css';
6
+
7
+ /* 2. App-specific overrides — DO NOT set --font-family here,
8
+ it would clobber theme overrides (dark/terminal set it to mono) */