@donotdev/cli 0.0.5 → 0.0.6

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 (48) hide show
  1. package/dependencies-matrix.json +57 -33
  2. package/dist/bin/commands/build.js +9 -3
  3. package/dist/bin/commands/bump.js +19 -7
  4. package/dist/bin/commands/cacheout.js +9 -3
  5. package/dist/bin/commands/create-app.js +21 -7
  6. package/dist/bin/commands/create-project.js +22 -7
  7. package/dist/bin/commands/deploy.js +22 -14
  8. package/dist/bin/commands/dev.js +9 -3
  9. package/dist/bin/commands/emu.js +9 -3
  10. package/dist/bin/commands/format.js +9 -3
  11. package/dist/bin/commands/lint.js +9 -3
  12. package/dist/bin/commands/make-admin.d.ts +11 -0
  13. package/dist/bin/commands/make-admin.d.ts.map +1 -0
  14. package/dist/bin/commands/make-admin.js +12 -0
  15. package/dist/bin/commands/make-admin.js.map +1 -0
  16. package/dist/bin/commands/preview.js +9 -3
  17. package/dist/bin/commands/sync-secrets.js +9 -3
  18. package/dist/index.js +33 -17
  19. package/package.json +1 -1
  20. package/templates/app-demo/index.html.example +4 -0
  21. package/templates/app-demo/src/App.tsx.example +28 -10
  22. package/templates/app-demo/src/config/app.ts.example +56 -0
  23. package/templates/app-next/src/app/ClientLayout.tsx.example +4 -3
  24. package/templates/app-next/src/app/layout.tsx.example +17 -25
  25. package/templates/app-next/src/globals.css.example +10 -7
  26. package/templates/app-next/src/locales/dndev_en.json.example +68 -0
  27. package/templates/app-next/src/pages/locales/example_en.json.example +5 -0
  28. package/templates/app-vite/index.html.example +3 -0
  29. package/templates/app-vite/src/globals.css.example +14 -6
  30. package/templates/app-vite/src/locales/dndev_en.json.example +68 -0
  31. package/templates/functions-firebase/README.md.example +25 -0
  32. package/templates/functions-firebase/tsconfig.json.example +3 -13
  33. package/templates/functions-vercel/tsconfig.json.example +1 -13
  34. package/templates/root-consumer/firebase.json.example +1 -1
  35. package/templates/root-consumer/guides/COMPONENTS_ADV.md.example +456 -360
  36. package/templates/root-consumer/guides/COMPONENTS_ATOMIC.md.example +42 -0
  37. package/templates/root-consumer/guides/INDEX.md.example +3 -0
  38. package/templates/root-consumer/guides/SETUP_APP_CONFIG.md.example +5 -2
  39. package/templates/root-consumer/guides/SETUP_BILLING.md.example +44 -4
  40. package/templates/root-consumer/guides/SETUP_CRUD.md.example +1244 -0
  41. package/templates/root-consumer/guides/SETUP_FUNCTIONS.md.example +52 -0
  42. package/templates/root-consumer/guides/SETUP_PAGES.md.example +17 -0
  43. package/templates/root-consumer/guides/SETUP_PWA.md.example +213 -0
  44. package/templates/root-consumer/guides/USE_ROUTING.md.example +503 -0
  45. package/templates/root-consumer/vercel.json.example +315 -20
  46. package/templates/app-demo/src/Routes.tsx.example +0 -20
  47. package/templates/app-vite/src/Routes.tsx.example +0 -16
  48. package/templates/app-vite/src/pages/locales/README.md.example +0 -1
@@ -7141,11 +7141,17 @@ var init_PathResolver = __esm({
7141
7141
  /**
7142
7142
  * Get path to empty.js module for optional dependency aliasing
7143
7143
  * Used by Vite and Turbopack to alias missing optional deps
7144
- * @returns Absolute path to empty.js
7144
+ * @param returnPackageSpecifier - If true, returns package specifier '@donotdev/core/empty' for Turbopack. If false, returns absolute path for Vite.
7145
+ * @returns Package specifier or absolute path to empty.js
7145
7146
  */
7146
- getEmptyModulePath() {
7147
+ getEmptyModulePath(returnPackageSpecifier = false) {
7148
+ if (returnPackageSpecifier) {
7149
+ return "@donotdev/core/empty";
7150
+ }
7151
+ const resolved = this.resolvePackage("@donotdev/core/empty");
7152
+ if (resolved) return resolved;
7147
7153
  const thisDir = dirname(fileURLToPath(import.meta.url));
7148
- return this.normalizePath(join(thisDir, "../vite/empty.js"));
7154
+ return this.normalizePath(join(thisDir, "../empty.js"));
7149
7155
  }
7150
7156
  // === PRIVATE METHODS ===
7151
7157
  /**
@@ -7141,11 +7141,17 @@ var init_PathResolver = __esm({
7141
7141
  /**
7142
7142
  * Get path to empty.js module for optional dependency aliasing
7143
7143
  * Used by Vite and Turbopack to alias missing optional deps
7144
- * @returns Absolute path to empty.js
7144
+ * @param returnPackageSpecifier - If true, returns package specifier '@donotdev/core/empty' for Turbopack. If false, returns absolute path for Vite.
7145
+ * @returns Package specifier or absolute path to empty.js
7145
7146
  */
7146
- getEmptyModulePath() {
7147
+ getEmptyModulePath(returnPackageSpecifier = false) {
7148
+ if (returnPackageSpecifier) {
7149
+ return "@donotdev/core/empty";
7150
+ }
7151
+ const resolved = this.resolvePackage("@donotdev/core/empty");
7152
+ if (resolved) return resolved;
7147
7153
  const thisDir = dirname(fileURLToPath(import.meta.url));
7148
- return this.normalizePath(join(thisDir, "../vite/empty.js"));
7154
+ return this.normalizePath(join(thisDir, "../empty.js"));
7149
7155
  }
7150
7156
  // === PRIVATE METHODS ===
7151
7157
  /**
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @fileoverview Make Admin Command Wrapper
3
+ * @description Re-exports makeAdmin from tooling for CLI bundling.
4
+ * Each command wrapper is bundled separately as a fully self-contained script.
5
+ *
6
+ * @version 0.0.1
7
+ * @since 0.0.1
8
+ * @author AMBROISE PARK Consulting
9
+ */
10
+ export { makeAdmin as main } from '@donotdev/tooling';
11
+ //# sourceMappingURL=make-admin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"make-admin.d.ts","sourceRoot":"","sources":["../../../src/bin/commands/make-admin.ts"],"names":[],"mappings":"AACA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,IAAI,IAAI,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,12 @@
1
+ // packages/cli/src/bin/commands/make-admin.ts
2
+ /**
3
+ * @fileoverview Make Admin Command Wrapper
4
+ * @description Re-exports makeAdmin from tooling for CLI bundling.
5
+ * Each command wrapper is bundled separately as a fully self-contained script.
6
+ *
7
+ * @version 0.0.1
8
+ * @since 0.0.1
9
+ * @author AMBROISE PARK Consulting
10
+ */
11
+ export { makeAdmin as main } from '@donotdev/tooling';
12
+ //# sourceMappingURL=make-admin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"make-admin.js","sourceRoot":"","sources":["../../../src/bin/commands/make-admin.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,IAAI,IAAI,EAAE,MAAM,mBAAmB,CAAC"}
@@ -7439,11 +7439,17 @@ var init_PathResolver = __esm({
7439
7439
  /**
7440
7440
  * Get path to empty.js module for optional dependency aliasing
7441
7441
  * Used by Vite and Turbopack to alias missing optional deps
7442
- * @returns Absolute path to empty.js
7442
+ * @param returnPackageSpecifier - If true, returns package specifier '@donotdev/core/empty' for Turbopack. If false, returns absolute path for Vite.
7443
+ * @returns Package specifier or absolute path to empty.js
7443
7444
  */
7444
- getEmptyModulePath() {
7445
+ getEmptyModulePath(returnPackageSpecifier = false) {
7446
+ if (returnPackageSpecifier) {
7447
+ return "@donotdev/core/empty";
7448
+ }
7449
+ const resolved = this.resolvePackage("@donotdev/core/empty");
7450
+ if (resolved) return resolved;
7445
7451
  const thisDir = dirname(fileURLToPath(import.meta.url));
7446
- return this.normalizePath(join(thisDir, "../vite/empty.js"));
7452
+ return this.normalizePath(join(thisDir, "../empty.js"));
7447
7453
  }
7448
7454
  // === PRIVATE METHODS ===
7449
7455
  /**
@@ -7463,11 +7463,17 @@ var init_PathResolver = __esm({
7463
7463
  /**
7464
7464
  * Get path to empty.js module for optional dependency aliasing
7465
7465
  * Used by Vite and Turbopack to alias missing optional deps
7466
- * @returns Absolute path to empty.js
7466
+ * @param returnPackageSpecifier - If true, returns package specifier '@donotdev/core/empty' for Turbopack. If false, returns absolute path for Vite.
7467
+ * @returns Package specifier or absolute path to empty.js
7467
7468
  */
7468
- getEmptyModulePath() {
7469
+ getEmptyModulePath(returnPackageSpecifier = false) {
7470
+ if (returnPackageSpecifier) {
7471
+ return "@donotdev/core/empty";
7472
+ }
7473
+ const resolved = this.resolvePackage("@donotdev/core/empty");
7474
+ if (resolved) return resolved;
7469
7475
  const thisDir = dirname(fileURLToPath(import.meta.url));
7470
- return this.normalizePath(join(thisDir, "../vite/empty.js"));
7476
+ return this.normalizePath(join(thisDir, "../empty.js"));
7471
7477
  }
7472
7478
  // === PRIVATE METHODS ===
7473
7479
  /**
package/dist/index.js CHANGED
@@ -7762,11 +7762,17 @@ var init_PathResolver = __esm({
7762
7762
  /**
7763
7763
  * Get path to empty.js module for optional dependency aliasing
7764
7764
  * Used by Vite and Turbopack to alias missing optional deps
7765
- * @returns Absolute path to empty.js
7765
+ * @param returnPackageSpecifier - If true, returns package specifier '@donotdev/core/empty' for Turbopack. If false, returns absolute path for Vite.
7766
+ * @returns Package specifier or absolute path to empty.js
7766
7767
  */
7767
- getEmptyModulePath() {
7768
+ getEmptyModulePath(returnPackageSpecifier = false) {
7769
+ if (returnPackageSpecifier) {
7770
+ return "@donotdev/core/empty";
7771
+ }
7772
+ const resolved = this.resolvePackage("@donotdev/core/empty");
7773
+ if (resolved) return resolved;
7768
7774
  const thisDir = dirname(fileURLToPath(import.meta.url));
7769
- return this.normalizePath(join(thisDir, "../vite/empty.js"));
7775
+ return this.normalizePath(join(thisDir, "../empty.js"));
7770
7776
  }
7771
7777
  // === PRIVATE METHODS ===
7772
7778
  /**
@@ -8772,12 +8778,7 @@ function executeFirebaseCommand(args, options) {
8772
8778
  env: deployEnv
8773
8779
  };
8774
8780
  let result;
8775
- if (process.platform === "win32") {
8776
- const firebaseCmd = "C:\\Program Files\\nodejs\\firebase.cmd";
8777
- result = spawnSync2(firebaseCmd, args, { ...spawnOptions, shell: false });
8778
- } else {
8779
- result = spawnSync2("firebase", args, { ...spawnOptions, shell: true });
8780
- }
8781
+ result = spawnSync2("firebase", args, { ...spawnOptions, shell: true });
8781
8782
  if (result.error) {
8782
8783
  return {
8783
8784
  success: false,
@@ -10376,11 +10377,15 @@ async function deployFunctions(appDir, serviceAccountPath, projectId, config) {
10376
10377
  }
10377
10378
  const s = Y2();
10378
10379
  s.start("Validating function dependencies...");
10379
- const nodeModulesPath = joinPath(functionsDir, "node_modules");
10380
10380
  const requiredPackages = ["firebase-functions", "firebase-admin"];
10381
- const missingPackages = requiredPackages.filter(
10382
- (pkg) => !pathExists(joinPath(nodeModulesPath, pkg))
10383
- );
10381
+ const missingPackages = requiredPackages.filter((pkg) => {
10382
+ try {
10383
+ resolvePackage(pkg, functionsDir);
10384
+ return false;
10385
+ } catch {
10386
+ return true;
10387
+ }
10388
+ });
10384
10389
  if (missingPackages.length > 0) {
10385
10390
  s.stop("Missing dependencies");
10386
10391
  throw new DoNotDevError(
@@ -10395,6 +10400,8 @@ To fix this, run:
10395
10400
  }
10396
10401
  s.stop("Dependencies validated");
10397
10402
  prepareFunctionsForDeployment(functionsDir, config.verbose);
10403
+ log.debug("Waiting for file system sync...");
10404
+ await new Promise((resolve4) => setTimeout(resolve4, 1e3));
10398
10405
  try {
10399
10406
  if (!config.skipBuild) {
10400
10407
  const s2 = Y2();
@@ -11125,7 +11132,7 @@ function generateScripts(templateName, options) {
11125
11132
  const scripts = {};
11126
11133
  if (templateName.includes("vite")) {
11127
11134
  scripts.dev = "vite";
11128
- scripts.build = "tsc --noEmit && cross-env NODE_ENV=production VITE_NODE_POLYFILL=true vite build";
11135
+ scripts.build = "vite build";
11129
11136
  scripts.preview = "vite preview";
11130
11137
  scripts.lint = "eslint src/";
11131
11138
  scripts["type-check"] = "tsc --noEmit";
@@ -11161,7 +11168,9 @@ function generateScripts(templateName, options) {
11161
11168
  function generatePackageJson(templateName, mode, options = {}) {
11162
11169
  const matrixResult = loadMatrix(mode);
11163
11170
  if (!matrixResult) {
11164
- throw new Error("dependencies-matrix.json not found. This command requires the matrix file.");
11171
+ throw new Error(
11172
+ "dependencies-matrix.json not found. This command requires the matrix file."
11173
+ );
11165
11174
  }
11166
11175
  const { matrix, cliVersion } = matrixResult;
11167
11176
  const template = matrix.templateMapping?.[templateName];
@@ -11221,6 +11230,11 @@ function generatePackageJson(templateName, mode, options = {}) {
11221
11230
  result.main = "./index.ts";
11222
11231
  result.types = "./index.ts";
11223
11232
  }
11233
+ if (templateName.includes("vite") || templateName.includes("nextjs") || templateName.includes("functions")) {
11234
+ if (!dependencies.entities) {
11235
+ dependencies.entities = "workspace:*";
11236
+ }
11237
+ }
11224
11238
  if (templateName.includes("functions")) {
11225
11239
  result.engines = { node: "20" };
11226
11240
  if (options.appName) {
@@ -11343,7 +11357,8 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
11343
11357
  firebaseProjectId: appName.toLowerCase(),
11344
11358
  firebaseSecretName: appName.toUpperCase().replace(/-/g, "_"),
11345
11359
  monorepoRelativePath: "../../packages/tooling",
11346
- appTemplate
11360
+ appTemplate,
11361
+ isNextjs: appTemplate === "nextjs"
11347
11362
  };
11348
11363
  const templateSourceDir = joinPath(templatesRoot, templateDir);
11349
11364
  const templateFiles = await glob("**/*", {
@@ -11436,7 +11451,7 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
11436
11451
  await replacePlaceholders(firebaseJsonDest, replacements);
11437
11452
  }
11438
11453
  }
11439
- if (appConfig.needsBackend && appConfig.backendPlatform === "vercel") {
11454
+ if (appTemplate === "nextjs" || appConfig.needsBackend && appConfig.backendPlatform === "vercel") {
11440
11455
  const vercelJsonSource = joinPath(
11441
11456
  deploymentTemplateDir,
11442
11457
  "vercel.json.example"
@@ -11817,6 +11832,7 @@ async function main8(options) {
11817
11832
  setupGithubActions: false,
11818
11833
  monorepoRelativePath: relativeMonorepoPath,
11819
11834
  appTemplate: "vite",
11835
+ isNextjs: false,
11820
11836
  firebaseProjectId: projectName.toLowerCase(),
11821
11837
  firebaseSecretName: projectName.toUpperCase().replace(/-/g, "_"),
11822
11838
  needsAuth,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@donotdev/cli",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "description": "Command-line interface for DoNotDev Framework",
5
5
  "type": "module",
6
6
  "private": false,
@@ -4,6 +4,10 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
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
+
7
11
  <style>
8
12
  body {
9
13
  margin: 0;
@@ -1,17 +1,35 @@
1
- // apps/demo/src/App.tsx
1
+ /**
2
+ * @fileoverview Main application component
3
+ * @description Root application component with configuration-driven architecture
4
+ * @version 0.0.4
5
+ * @since 0.0.1
6
+ * @author AMBROISE PARK Consulting
7
+ */
2
8
 
3
- import { BrowserRouter } from 'react-router-dom';
4
- import { TooltipProvider, Toaster } from '@donotdev/components';
9
+ import { ViteAppProviders } from '@donotdev/ui/vite';
5
10
 
6
- import { Routes } from './Routes';
11
+ import { appConfig } from './config/app';
7
12
 
13
+ /**
14
+ * Main application component
15
+ *
16
+ * Configuration-driven architecture with smart defaults.
17
+ * Layout preset comes from appConfig.preset (configured in config/app.ts).
18
+ * Routes are automatically discovered from src/pages/*Page.tsx files.
19
+ *
20
+ * Note: HomePage.tsx in src/pages/ is automatically used for the root route "/"
21
+ *
22
+ * @version 0.0.4
23
+ * @since 0.0.1
24
+ * @author AMBROISE PARK Consulting
25
+ */
8
26
  export function App() {
9
27
  return (
10
- <BrowserRouter>
11
- <TooltipProvider>
12
- <Routes />
13
- <Toaster />
14
- </TooltipProvider>
15
- </BrowserRouter>
28
+ <ViteAppProviders
29
+ config={appConfig}
30
+ layout={{
31
+ breadcrumbs: 'smart', // 'smart' | 'always' | 'never'
32
+ }}
33
+ />
16
34
  );
17
35
  }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @fileoverview Application configuration
3
+ * @description Defines application metadata and feature flags
4
+ * @version 0.0.1
5
+ * @since 0.0.1
6
+ * @author AMBROISE PARK Consulting
7
+ */
8
+
9
+ import type { AppConfig } from '@donotdev/core';
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}}';
19
+
20
+ /**
21
+ * Application short name constant
22
+ *
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
44
+ */
45
+ export const appConfig: AppConfig = {
46
+ app: {
47
+ name: APP_NAME,
48
+ shortName: APP_SHORT_NAME,
49
+ description: APP_DESCRIPTION,
50
+ },
51
+ preset: 'landing', // 'landing' | 'admin' | 'moolti' | 'docs' | 'blog' | 'game' | 'plain'
52
+ features: {
53
+ // Optional: Enable debug tools in development
54
+ // debug: true,
55
+ },
56
+ };
@@ -6,7 +6,6 @@ import { appConfig } from '../config/app';
6
6
 
7
7
  interface ClientLayoutProps {
8
8
  children: React.ReactNode;
9
- serverCookies?: string;
10
9
  }
11
10
 
12
11
  /**
@@ -17,13 +16,14 @@ interface ClientLayoutProps {
17
16
  * Layout prop is for breadcrumbs and slot customizations only.
18
17
  * CSS variable overrides should be done in themes.css.
19
18
  * Override only what you need - everything else has sensible defaults.
19
+ *
20
+ * Theme detection happens client-side to avoid Next.js 16 race condition.
20
21
  */
21
- export function ClientLayout({ children, serverCookies }: ClientLayoutProps) {
22
+ export function ClientLayout({ children }: ClientLayoutProps) {
22
23
  return (
23
24
  <div id="root">
24
25
  <NextJsAppProviders
25
26
  config={appConfig}
26
- serverCookies={serverCookies}
27
27
  layout={{
28
28
  breadcrumbs: 'smart', // 'smart' | 'always' | 'never'
29
29
  header: {
@@ -37,3 +37,4 @@ export function ClientLayout({ children, serverCookies }: ClientLayoutProps) {
37
37
  </div>
38
38
  );
39
39
  }
40
+
@@ -1,13 +1,12 @@
1
1
  import type { Metadata } from 'next';
2
- import { cookies } from 'next/headers';
3
2
  import '../globals.css';
4
3
  import { ClientLayout } from './ClientLayout';
5
4
 
6
5
  /**
7
6
  * Framework fonts are loaded via CSS @font-face rules in dndev.css
8
7
  *
9
- * The framework CSS includes optimized @font-face declarations for Roboto
10
- * with proper unicode-range subsetting for performance.
8
+ * The framework CSS includes optimized @font-face declarations for Inter
9
+ * (default) and Roboto (optional) with proper unicode-range subsetting for performance.
11
10
  * Fonts are copied from framework to public/fonts/ by AssetDiscovery during build.
12
11
  */
13
12
 
@@ -16,36 +15,29 @@ export const metadata: Metadata = {
16
15
  description: 'Next.js site using DNDev framework',
17
16
  };
18
17
 
19
- export default async function RootLayout({
18
+ /**
19
+ * Root layout for Next.js App Router
20
+ *
21
+ * Theme detection happens client-side via ClientLayout to avoid
22
+ * Next.js 16 + Turbopack race condition with async layouts.
23
+ * Brief FOUC possible on first load, but prevents build-manifest.json errors.
24
+ */
25
+ export default function RootLayout({
20
26
  children,
21
27
  }: {
22
28
  children: React.ReactNode;
23
29
  }) {
24
- /**
25
- * SSR: Read theme from cookies to apply correct theme class to HTML
26
- *
27
- * This ensures the server-rendered HTML has the correct theme class,
28
- * preventing FOUC (Flash of Unstyled Content) when client hydrates.
29
- *
30
- * Flow:
31
- * 1. Server reads cookie → applies theme class to <html>/<body>
32
- * 2. NextJsStoresInitializer hydrates store from cookie
33
- * 3. Client hydrates → Zustand persist matches server state
34
- * 4. setAvailableThemes() ensures DOM matches persisted theme
35
- */
36
- const cookieStore = await cookies();
37
- const themeCookie = cookieStore.get('dndev-theme');
38
- const themeClass = themeCookie?.value || 'light';
39
-
40
30
  return (
41
- <html lang="en" className={`dndev-design-tokens ${themeClass}`}>
31
+ <html
32
+ lang="en"
33
+ className="dndev-design-tokens light"
34
+ suppressHydrationWarning
35
+ >
42
36
  <head>
43
37
  <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
44
38
  </head>
45
- <body className={themeClass}>
46
- <ClientLayout serverCookies={cookieStore.toString()}>
47
- {children}
48
- </ClientLayout>
39
+ <body className="light">
40
+ <ClientLayout>{children}</ClientLayout>
49
41
  </body>
50
42
  </html>
51
43
  );
@@ -6,10 +6,13 @@
6
6
  /**
7
7
  * Font configuration
8
8
  *
9
- * Uses --font-roboto CSS variable from next/font/local (defined in layout.tsx).
10
- * Next.js automatically handles font preloading and optimization.
11
- */
12
- :root {
13
- --font-sans: var(--font-roboto, 'Roboto', sans-serif);
14
- --font-family: var(--font-sans);
15
- }
9
+ * Framework defaults to Inter (defined in @donotdev/components/styles/variables.css).
10
+ * Fonts are loaded via CSS @font-face rules in @donotdev/ui/assets/fonts/fonts.css
11
+ * and copied to public/fonts/ by AssetDiscovery during build.
12
+ *
13
+ * To override, uncomment and customize:
14
+ * :root {
15
+ * --font-sans: 'YourFont', sans-serif;
16
+ * --font-family: var(--font-sans);
17
+ * }
18
+ */
@@ -496,6 +496,10 @@
496
496
  "copied": "Copied!",
497
497
  "copyCodeToClipboard": "Copy code to clipboard"
498
498
  },
499
+ "video": {
500
+ "clickToWatch": "Click to watch video",
501
+ "watchVideo": "Watch Video"
502
+ },
499
503
  "inspector": {
500
504
  "pageSource": "Page Source",
501
505
  "inspectPageSourceCode": "Inspect page source code"
@@ -512,5 +516,69 @@
512
516
  "goHome": "Go Home",
513
517
  "goBack": "Go Back",
514
518
  "contactSupport": "If the problem persists, please contact support."
519
+ },
520
+ "redirectOverlay": {
521
+ "phases": {
522
+ "connecting": "Connecting to secure server...",
523
+ "preparing": "Preparing your session...",
524
+ "redirecting": "Redirecting...",
525
+ "timeout": "Taking longer than expected..."
526
+ },
527
+ "cancel": "Cancel",
528
+ "doNotRefresh": "Please do not refresh or press back",
529
+ "default": {
530
+ "title": "Redirecting",
531
+ "message": "Please wait while we redirect you...",
532
+ "subtitle": "This may take a moment",
533
+ "ariaLabel": "Redirecting, please wait"
534
+ },
535
+ "stripe-checkout": {
536
+ "title": "Redirecting to Stripe",
537
+ "message": "Initializing secure payment...",
538
+ "subtitle": "This may take a moment on first load",
539
+ "ariaLabel": "Preparing secure checkout, please wait"
540
+ },
541
+ "stripe-portal": {
542
+ "title": "Redirecting to Stripe",
543
+ "message": "Opening billing portal...",
544
+ "subtitle": "Manage your subscription and invoices",
545
+ "ariaLabel": "Opening billing portal, please wait"
546
+ },
547
+ "oauth-google": {
548
+ "title": "Signing in with Google",
549
+ "message": "Connecting to Google...",
550
+ "subtitle": "You will be redirected to sign in",
551
+ "ariaLabel": "Signing in with Google, please wait"
552
+ },
553
+ "oauth-github": {
554
+ "title": "Signing in with GitHub",
555
+ "message": "Connecting to GitHub...",
556
+ "subtitle": "You will be redirected to sign in",
557
+ "ariaLabel": "Signing in with GitHub, please wait"
558
+ },
559
+ "oauth-apple": {
560
+ "title": "Signing in with Apple",
561
+ "message": "Connecting to Apple...",
562
+ "subtitle": "You will be redirected to sign in",
563
+ "ariaLabel": "Signing in with Apple, please wait"
564
+ },
565
+ "oauth-microsoft": {
566
+ "title": "Signing in with Microsoft",
567
+ "message": "Connecting to Microsoft...",
568
+ "subtitle": "You will be redirected to sign in",
569
+ "ariaLabel": "Signing in with Microsoft, please wait"
570
+ },
571
+ "oauth-facebook": {
572
+ "title": "Signing in with Facebook",
573
+ "message": "Connecting to Facebook...",
574
+ "subtitle": "You will be redirected to sign in",
575
+ "ariaLabel": "Signing in with Facebook, please wait"
576
+ },
577
+ "auth-email-link": {
578
+ "title": "Sending verification",
579
+ "message": "Preparing your verification link...",
580
+ "subtitle": "Check your email inbox",
581
+ "ariaLabel": "Sending verification email, please wait"
582
+ }
515
583
  }
516
584
  }
@@ -0,0 +1,5 @@
1
+ {
2
+ "title": "Example Page",
3
+ "description": "Example page locale file that is dynamically loaded on demand only"
4
+ }
5
+
@@ -30,6 +30,9 @@
30
30
  <title>Loading...</title>
31
31
  <meta name="description" content="Modern web application powered by DoNotDev" />
32
32
 
33
+ <!-- ✅ PERFORMANCE: Critical font preloads (loads before CSS) -->
34
+ <!-- Only preload fonts with font-display: swap (not optional) -->
35
+ <!-- Example: <link rel="preload" href="/fonts/YourFont.woff2" as="font" type="font/woff2" crossorigin="anonymous"> -->
33
36
 
34
37
  <!-- ✅ PERFORMANCE: Critical CSS inlined here by build -->
35
38
  <style>
@@ -3,9 +3,17 @@
3
3
 
4
4
  @import './themes.css';
5
5
 
6
- /* Override framework's default font to use Roboto */
7
- :root {
8
- --font-sans: 'Roboto', sans-serif;
9
- --font-mono: 'Roboto Mono', monospace;
10
- --font-family: var(--font-sans);
11
- }
6
+ /**
7
+ * Font configuration
8
+ *
9
+ * Framework defaults to Inter (defined in @donotdev/components/styles/variables.css).
10
+ * Fonts are loaded via CSS @font-face rules in @donotdev/ui/assets/fonts/fonts.css
11
+ * and copied to public/fonts/ by AssetDiscovery during build.
12
+ *
13
+ * To override, uncomment and customize:
14
+ * :root {
15
+ * --font-sans: 'YourFont', sans-serif;
16
+ * --font-mono: 'YourMonoFont', monospace;
17
+ * --font-family: var(--font-sans);
18
+ * }
19
+ */