create-next-pro-cli 0.1.25 → 0.1.27

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 (107) hide show
  1. package/README.md +205 -292
  2. package/create-next-pro-completion.sh +8 -38
  3. package/create-next-pro-completion.zsh +13 -0
  4. package/dist/bin.bun.js +1127 -628
  5. package/dist/bin.node.js +1170 -617
  6. package/dist/bin.node.js.map +1 -1
  7. package/dist/create-next-pro +35 -6
  8. package/package.json +49 -27
  9. package/templates/Projects/default/.env.example +17 -0
  10. package/templates/Projects/default/.github/workflows/quality.yml +24 -0
  11. package/templates/Projects/default/.gitignore.template +47 -0
  12. package/templates/Projects/default/.prettierignore +3 -0
  13. package/templates/Projects/default/README.md +66 -21
  14. package/templates/Projects/default/bun.lock +1152 -0
  15. package/templates/Projects/default/eslint.config.mjs +27 -11
  16. package/templates/Projects/default/messages/en/_global_ui.json +23 -10
  17. package/templates/Projects/default/messages/en.ts +17 -2
  18. package/templates/Projects/default/messages/fr/_global_ui.json +23 -10
  19. package/templates/Projects/default/messages/fr.ts +17 -2
  20. package/templates/Projects/default/next.config.ts +43 -3
  21. package/templates/Projects/default/package.json +42 -24
  22. package/templates/Projects/default/playwright.config.ts +26 -0
  23. package/templates/Projects/default/pnpm-workspace.yaml +5 -0
  24. package/templates/Projects/default/public/{cnp-logo.svg → logo.svg} +1 -1
  25. package/templates/Projects/default/src/app/[locale]/(public)/layout.tsx +8 -1
  26. package/templates/Projects/default/src/app/[locale]/(public)/login/page.tsx +8 -0
  27. package/templates/Projects/default/src/app/[locale]/(public)/register/page.tsx +8 -0
  28. package/templates/Projects/default/src/app/[locale]/(user)/dashboard/error.tsx +25 -0
  29. package/templates/Projects/default/src/app/[locale]/(user)/dashboard/loading.tsx +5 -0
  30. package/templates/Projects/default/src/app/[locale]/(user)/{Dashboard → dashboard}/page.tsx +1 -1
  31. package/templates/Projects/default/src/app/[locale]/(user)/layout.tsx +24 -2
  32. package/templates/Projects/default/src/app/[locale]/(user)/settings/loading.tsx +5 -0
  33. package/templates/Projects/default/src/app/[locale]/(user)/{Settings → settings}/page.tsx +1 -2
  34. package/templates/Projects/default/src/app/[locale]/(user)/userInfo/loading.tsx +5 -0
  35. package/templates/Projects/default/src/app/[locale]/(user)/{UserInfo → userInfo}/page.tsx +1 -2
  36. package/templates/Projects/default/src/app/[locale]/layout.tsx +34 -10
  37. package/templates/Projects/default/src/app/[locale]/loading.tsx +0 -9
  38. package/templates/Projects/default/src/app/[locale]/not-found.tsx +6 -15
  39. package/templates/Projects/default/src/app/[locale]/page.tsx +10 -1
  40. package/templates/Projects/default/src/app/api/auth/[...nextauth]/route.ts +8 -60
  41. package/templates/Projects/default/src/app/not-found.tsx +1 -1
  42. package/templates/Projects/default/src/app/sitemap.ts +2 -2
  43. package/templates/Projects/default/src/app/styles/globals.css +166 -113
  44. package/templates/Projects/default/src/auth.ts +20 -0
  45. package/templates/Projects/default/src/config.ts +3 -3
  46. package/templates/Projects/default/src/env.ts +65 -0
  47. package/templates/Projects/default/src/lib/i18n/messages.ts +8 -0
  48. package/templates/Projects/default/src/lib/i18n/request.ts +2 -16
  49. package/templates/Projects/default/src/lib/security/csp.ts +16 -0
  50. package/templates/Projects/default/src/lib/utils.ts +2 -1
  51. package/templates/Projects/default/src/proxy.ts +13 -0
  52. package/templates/Projects/default/src/ui/_global/BackButton.tsx +4 -2
  53. package/templates/Projects/default/src/ui/_global/Button.tsx +3 -8
  54. package/templates/Projects/default/src/ui/_global/GlobalHeader.tsx +10 -28
  55. package/templates/Projects/default/src/ui/_global/GlobalMain.tsx +1 -1
  56. package/templates/Projects/default/src/ui/_global/LocaleSwitcher.tsx +9 -10
  57. package/templates/Projects/default/src/ui/_global/PublicNav.tsx +51 -17
  58. package/templates/Projects/default/src/ui/_global/ThemeToggle.tsx +45 -39
  59. package/templates/Projects/default/src/ui/_global/UserNav.tsx +6 -6
  60. package/templates/Projects/default/src/ui/_home/page-ui.tsx +5 -7
  61. package/templates/Projects/default/src/ui/{Dashboard → dashboard}/LogoutButton.tsx +9 -7
  62. package/templates/Projects/default/src/ui/{Dashboard → dashboard}/StatsCard.tsx +4 -4
  63. package/templates/Projects/default/src/ui/{Dashboard → dashboard}/page-ui.tsx +7 -8
  64. package/templates/Projects/default/src/ui/login/page-ui.tsx +36 -0
  65. package/templates/Projects/default/src/ui/register/page-ui.tsx +38 -0
  66. package/templates/Projects/default/src/ui/settings/page-ui.tsx +15 -0
  67. package/templates/Projects/default/src/ui/userInfo/page-ui.tsx +15 -0
  68. package/templates/Projects/default/tailwind.config.ts +81 -1
  69. package/templates/Projects/default/tests/consumer/validate-template.ts +66 -0
  70. package/templates/Projects/default/tests/e2e/template-remediation.playwright.ts +106 -0
  71. package/templates/Projects/default/tests/rendering/verify-rendering.ts +56 -0
  72. package/templates/Projects/default/tests/unit/csp.test.ts +19 -0
  73. package/templates/Projects/default/tests/unit/env.test.ts +76 -0
  74. package/templates/Projects/default/tsconfig.json +6 -6
  75. package/templates/Projects/default/messages/getMergedMessages.ts +0 -31
  76. package/templates/Projects/default/middleware.ts +0 -11
  77. package/templates/Projects/default/src/app/[locale]/(public)/Login/page.tsx +0 -6
  78. package/templates/Projects/default/src/app/[locale]/(public)/Register/page.tsx +0 -6
  79. package/templates/Projects/default/src/app/[locale]/(user)/Dashboard/error.tsx +0 -38
  80. package/templates/Projects/default/src/app/[locale]/(user)/Dashboard/loading.tsx +0 -10
  81. package/templates/Projects/default/src/app/[locale]/(user)/Settings/loading.tsx +0 -17
  82. package/templates/Projects/default/src/app/[locale]/(user)/UserInfo/loading.tsx +0 -17
  83. package/templates/Projects/default/src/app/api/auth/post-login/route.ts +0 -26
  84. package/templates/Projects/default/src/app/api/hello/route.ts +0 -5
  85. package/templates/Projects/default/src/app/layout.tsx +0 -11
  86. package/templates/Projects/default/src/app/page.tsx +0 -6
  87. package/templates/Projects/default/src/auth.config.ts +0 -0
  88. package/templates/Projects/default/src/lib/auth/disconnect.ts +0 -11
  89. package/templates/Projects/default/src/lib/auth/isConnected.ts +0 -18
  90. package/templates/Projects/default/src/lib/sample/example.ts +0 -3
  91. package/templates/Projects/default/src/lib/sample/index.ts +0 -3
  92. package/templates/Projects/default/src/ui/Login/page-ui.tsx +0 -22
  93. package/templates/Projects/default/src/ui/Register/page-ui.tsx +0 -26
  94. package/templates/Projects/default/src/ui/Settings/page-ui.tsx +0 -17
  95. package/templates/Projects/default/src/ui/UserInfo/page-ui.tsx +0 -17
  96. /package/templates/Projects/default/messages/en/{Dashboard.json → dashboard.json} +0 -0
  97. /package/templates/Projects/default/messages/en/{Login.json → login.json} +0 -0
  98. /package/templates/Projects/default/messages/en/{Register.json → register.json} +0 -0
  99. /package/templates/Projects/default/messages/en/{Settings.json → settings.json} +0 -0
  100. /package/templates/Projects/default/messages/en/{UserInfo.json → userInfo.json} +0 -0
  101. /package/templates/Projects/default/messages/fr/{Dashboard.json → dashboard.json} +0 -0
  102. /package/templates/Projects/default/messages/fr/{Login.json → login.json} +0 -0
  103. /package/templates/Projects/default/messages/fr/{Register.json → register.json} +0 -0
  104. /package/templates/Projects/default/messages/fr/{Settings.json → settings.json} +0 -0
  105. /package/templates/Projects/default/messages/fr/{UserInfo.json → userInfo.json} +0 -0
  106. /package/templates/Projects/default/public/{cnp-logo.png → logo.png} +0 -0
  107. /package/templates/Projects/default/src/ui/{Dashboard → dashboard}/WelcomeCard.tsx +0 -0
@@ -1,16 +1,32 @@
1
- import { dirname } from "path";
2
- import { fileURLToPath } from "url";
3
- import { FlatCompat } from "@eslint/eslintrc";
4
-
5
- const __filename = fileURLToPath(import.meta.url);
6
- const __dirname = dirname(__filename);
7
-
8
- const compat = new FlatCompat({
9
- baseDirectory: __dirname,
10
- });
1
+ import nextCoreWebVitals from "eslint-config-next/core-web-vitals";
2
+ import nextTypescript from "eslint-config-next/typescript";
11
3
 
12
4
  const eslintConfig = [
13
- ...compat.extends("next/core-web-vitals", "next/typescript"),
5
+ ...nextCoreWebVitals,
6
+ ...nextTypescript,
7
+ {
8
+ rules: {
9
+ "react/jsx-key": "error",
10
+ "react/jsx-no-duplicate-props": "error",
11
+ "react/jsx-no-target-blank": "error",
12
+ "react/no-children-prop": "error",
13
+ "react/no-danger-with-children": "error",
14
+ "react/no-unknown-property": "error",
15
+ "react/no-unescaped-entities": "error",
16
+ },
17
+ },
18
+ {
19
+ ignores: [
20
+ "node_modules/**",
21
+ ".next/**",
22
+ "out/**",
23
+ "build/**",
24
+ "artifacts/**",
25
+ "playwright-report/**",
26
+ "test-results/**",
27
+ "next-env.d.ts",
28
+ ],
29
+ },
14
30
  ];
15
31
 
16
32
  export default eslintConfig;
@@ -1,5 +1,21 @@
1
1
  {
2
+ "user_nav": {
3
+ "links": {
4
+ "home": "Home",
5
+ "dashboard": "Dashboard",
6
+ "settings": "Settings",
7
+ "user_info": "User Information"
8
+ }
9
+ },
10
+ "Loading": {
11
+ "title": "Loading",
12
+ "description": "Please wait while we prepare your experience..."
13
+ },
14
+ "back": "Back",
15
+ "select_language": "Select language",
16
+ "toggle_theme": "Toggle theme",
2
17
  "public_nav": {
18
+ "menu": "Public navigation menu",
3
19
  "links": {
4
20
  "home": "Home",
5
21
  "login": "Login",
@@ -19,16 +35,13 @@
19
35
  "search": "Search"
20
36
  }
21
37
  },
22
- "user_nav": {
23
- "links": {
24
- "home": "Home",
25
- "dashboard": "Dashboard",
26
- "settings": "Settings",
27
- "user_info": "User Information"
28
- }
38
+ "error": {
39
+ "title": "Something went wrong!",
40
+ "retry": "Try again"
29
41
  },
30
- "Loading": {
31
- "title": "Loading",
32
- "description": "Please wait while we prepare your experience..."
42
+ "not_found": {
43
+ "title": "Not Found",
44
+ "description": "Could not find the requested resource",
45
+ "home": "Return Home"
33
46
  }
34
47
  }
@@ -1,4 +1,19 @@
1
- import getMergedMessages from "./getMergedMessages";
1
+ import globalUi from "./en/_global_ui.json";
2
+ import home from "./en/_home.json";
3
+ import dashboard from "./en/dashboard.json";
4
+ import login from "./en/login.json";
5
+ import register from "./en/register.json";
6
+ import settings from "./en/settings.json";
7
+ import userInfo from "./en/userInfo.json";
8
+
9
+ const messages = {
10
+ _global_ui: globalUi,
11
+ _home: home,
12
+ dashboard,
13
+ login,
14
+ register,
15
+ settings,
16
+ userInfo,
17
+ };
2
18
 
3
- const messages = await getMergedMessages(import.meta.url);
4
19
  export default messages;
@@ -1,5 +1,21 @@
1
1
  {
2
+ "user_nav": {
3
+ "links": {
4
+ "home": "Accueil",
5
+ "dashboard": "Tableau de bord",
6
+ "settings": "Paramètres",
7
+ "user_info": "Informations sur l'utilisateur"
8
+ }
9
+ },
10
+ "Loading": {
11
+ "title": "Chargement en cours",
12
+ "description": "Veuillez patienter pendant que nous préparons votre expérience..."
13
+ },
14
+ "back": "Retour",
15
+ "select_language": "Choisir la langue",
16
+ "toggle_theme": "Changer de thème",
2
17
  "public_nav": {
18
+ "menu": "Menu de navigation publique",
3
19
  "links": {
4
20
  "home": "Accueil",
5
21
  "login": "Connexion",
@@ -19,16 +35,13 @@
19
35
  "search": "Recherche"
20
36
  }
21
37
  },
22
- "user_nav": {
23
- "links": {
24
- "home": "Accueil",
25
- "dashboard": "Tableau de bord",
26
- "settings": "Paramètres",
27
- "user_info": "Informations sur l'utilisateur"
28
- }
38
+ "error": {
39
+ "title": "Une erreur est survenue !",
40
+ "retry": "Réessayer"
29
41
  },
30
- "Loading": {
31
- "title": "Chargement en cours",
32
- "description": "Veuillez patienter pendant que nous préparons votre expérience..."
42
+ "not_found": {
43
+ "title": "Page introuvable",
44
+ "description": "La ressource demandée est introuvable",
45
+ "home": "Retour à l'accueil"
33
46
  }
34
47
  }
@@ -1,4 +1,19 @@
1
- import getMergedMessages from "./getMergedMessages";
1
+ import globalUi from "./fr/_global_ui.json";
2
+ import home from "./fr/_home.json";
3
+ import dashboard from "./fr/dashboard.json";
4
+ import login from "./fr/login.json";
5
+ import register from "./fr/register.json";
6
+ import settings from "./fr/settings.json";
7
+ import userInfo from "./fr/userInfo.json";
8
+
9
+ const messages = {
10
+ _global_ui: globalUi,
11
+ _home: home,
12
+ dashboard,
13
+ login,
14
+ register,
15
+ settings,
16
+ userInfo,
17
+ };
2
18
 
3
- const messages = await getMergedMessages(import.meta.url);
4
19
  export default messages;
@@ -1,10 +1,50 @@
1
1
  import { NextConfig } from "next";
2
2
  import createNextIntlPlugin from "next-intl/plugin";
3
+ import { createContentSecurityPolicy } from "./src/lib/security/csp";
4
+
5
+ const contentSecurityPolicy = createContentSecurityPolicy(
6
+ process.env.NODE_ENV !== "production",
7
+ );
3
8
 
4
9
  const nextConfig: NextConfig = {
5
- /* devIndicators: {
6
- buildActivity: true,
7
- }, */
10
+ poweredByHeader: false,
11
+ async headers() {
12
+ const headers = [
13
+ {
14
+ key: "X-Frame-Options",
15
+ value: "DENY",
16
+ },
17
+ {
18
+ key: "X-Content-Type-Options",
19
+ value: "nosniff",
20
+ },
21
+ {
22
+ key: "Referrer-Policy",
23
+ value: "strict-origin-when-cross-origin",
24
+ },
25
+ {
26
+ key: "Permissions-Policy",
27
+ value: "camera=(), microphone=(), geolocation=()",
28
+ },
29
+ {
30
+ key: "Content-Security-Policy",
31
+ value: contentSecurityPolicy,
32
+ },
33
+ ];
34
+ if (process.env.NODE_ENV === "production") {
35
+ headers.push({
36
+ key: "Strict-Transport-Security",
37
+ value: "max-age=31536000; includeSubDomains",
38
+ });
39
+ }
40
+
41
+ return [
42
+ {
43
+ source: "/(.*)",
44
+ headers,
45
+ },
46
+ ];
47
+ },
8
48
  };
9
49
 
10
50
  const withNextIntl = createNextIntlPlugin("./src/lib/i18n/request.ts");
@@ -2,37 +2,55 @@
2
2
  "name": "my-next-pro",
3
3
  "version": "0.1.0",
4
4
  "private": true,
5
+ "type": "module",
6
+ "packageManager": "bun@1.3.14",
7
+ "engines": {
8
+ "node": ">=24.0.0",
9
+ "bun": ">=1.3.14"
10
+ },
5
11
  "scripts": {
6
12
  "dev": "next dev --turbopack",
7
13
  "build": "next build",
8
14
  "start": "next start",
9
- "lint": "next lint"
15
+ "lint": "eslint .",
16
+ "typecheck": "tsc --noEmit",
17
+ "format": "prettier --write .",
18
+ "format:check": "prettier --check .",
19
+ "test": "vitest run",
20
+ "test:e2e": "playwright test",
21
+ "verify:rendering": "node --experimental-strip-types tests/rendering/verify-rendering.ts",
22
+ "check": "prettier --check . && eslint . && tsc --noEmit && vitest run && next build && node --experimental-strip-types tests/rendering/verify-rendering.ts",
23
+ "test:consumer": "node --experimental-strip-types tests/consumer/validate-template.ts",
24
+ "audit": "bun audit"
10
25
  },
11
26
  "dependencies": {
12
- "@radix-ui/react-slot": "^1.2.3",
13
- "class-variance-authority": "^0.7.1",
14
- "clsx": "^2.1.1",
15
- "cookie": "^1.0.2",
16
- "jsonwebtoken": "^9.0.2",
17
- "lucide-react": "^0.539.0",
18
- "next": "15.4.5",
19
- "next-auth": "^4.24.11",
20
- "next-intl": "^4.3.4",
21
- "react": "19.1.0",
22
- "react-dom": "19.1.0",
23
- "tailwind-merge": "^3.3.1",
24
- "tailwindcss-animate": "^1.0.7"
27
+ "@radix-ui/react-slot": "1.3.0",
28
+ "class-variance-authority": "0.7.1",
29
+ "clsx": "2.1.1",
30
+ "lucide-react": "1.24.0",
31
+ "next": "16.2.10",
32
+ "next-auth": "5.0.0-beta.31",
33
+ "next-intl": "4.13.2",
34
+ "react": "19.2.7",
35
+ "react-dom": "19.2.7",
36
+ "simple-icons": "16.26.0",
37
+ "tailwind-merge": "3.6.0",
38
+ "tailwindcss-animate": "1.0.7"
25
39
  },
26
40
  "devDependencies": {
27
- "@eslint/eslintrc": "^3",
28
- "@tailwindcss/postcss": "^4",
29
- "@types/jsonwebtoken": "^9.0.10",
30
- "@types/node": "^20",
31
- "@types/react": "^19",
32
- "@types/react-dom": "^19",
33
- "eslint": "^9",
34
- "eslint-config-next": "15.4.5",
35
- "tailwindcss": "^4",
36
- "typescript": "^5"
41
+ "@playwright/test": "1.61.1",
42
+ "@tailwindcss/postcss": "4.3.3",
43
+ "@types/node": "24.13.3",
44
+ "@types/react": "19.2.17",
45
+ "@types/react-dom": "19.2.3",
46
+ "eslint": "9.39.4",
47
+ "eslint-config-next": "16.2.10",
48
+ "prettier": "3.9.5",
49
+ "tailwindcss": "4.3.3",
50
+ "typescript": "6.0.3",
51
+ "vitest": "4.1.10"
52
+ },
53
+ "overrides": {
54
+ "postcss": "8.5.15"
37
55
  }
38
56
  }
@@ -0,0 +1,26 @@
1
+ import { defineConfig, devices } from "@playwright/test";
2
+
3
+ export default defineConfig({
4
+ testDir: "./tests/e2e",
5
+ testMatch: "**/*.playwright.ts",
6
+ fullyParallel: true,
7
+ retries: process.env.CI ? 2 : 0,
8
+ reporter: process.env.CI ? "github" : "list",
9
+ use: {
10
+ baseURL: "http://127.0.0.1:3100",
11
+ trace: "retain-on-failure",
12
+ },
13
+ projects: [
14
+ { name: "desktop", use: { ...devices["Desktop Chrome"] } },
15
+ { name: "mobile", use: { ...devices["Pixel 5"] } },
16
+ ],
17
+ webServer: {
18
+ command: "next build && next start --hostname 127.0.0.1 --port 3100",
19
+ url: "http://127.0.0.1:3100/en",
20
+ reuseExistingServer: !process.env.CI,
21
+ env: {
22
+ AUTH_DISABLED: "true",
23
+ NEXT_PUBLIC_APP_URL: "http://127.0.0.1:3100",
24
+ },
25
+ },
26
+ });
@@ -0,0 +1,5 @@
1
+ allowBuilds:
2
+ "@parcel/watcher": true
3
+ "@swc/core": true
4
+ sharp: true
5
+ unrs-resolver: true
@@ -8,7 +8,7 @@
8
8
  version="1.1"
9
9
  id="svg1484"
10
10
  inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
11
- sodipodi:docname="cnp-logo.svg"
11
+ sodipodi:docname="logo.svg"
12
12
  xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
13
13
  xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
14
14
  xmlns="http://www.w3.org/2000/svg"
@@ -1,9 +1,16 @@
1
1
  import React from "react";
2
+ import GlobalHeader from "@/ui/_global/GlobalHeader";
3
+ import GlobalMain from "@/ui/_global/GlobalMain";
2
4
 
3
5
  export default function PublicLayout({
4
6
  children,
5
7
  }: {
6
8
  children: React.ReactNode;
7
9
  }) {
8
- return children;
10
+ return (
11
+ <>
12
+ <GlobalHeader hasSessionInitial={false} />
13
+ <GlobalMain>{children}</GlobalMain>
14
+ </>
15
+ );
9
16
  }
@@ -0,0 +1,8 @@
1
+ // src/app/[locale]/(public)/login/page.tsx
2
+ import LoginPageUI from "@/ui/login/page-ui";
3
+
4
+ export const dynamic = "force-static";
5
+
6
+ export default function LoginPage() {
7
+ return <LoginPageUI />;
8
+ }
@@ -0,0 +1,8 @@
1
+ // src/app/[locale]/(public)/register/page.tsx
2
+ import RegisterPageUI from "@/ui/register/page-ui";
3
+
4
+ export const dynamic = "force-static";
5
+
6
+ export default function RegisterPage() {
7
+ return <RegisterPageUI />;
8
+ }
@@ -0,0 +1,25 @@
1
+ // app/[locale]/error.tsx
2
+ "use client";
3
+
4
+ import { useEffect } from "react";
5
+ import { useTranslations } from "next-intl";
6
+
7
+ export default function Error({
8
+ error,
9
+ reset,
10
+ }: {
11
+ error: Error & { digest?: string };
12
+ reset: () => void;
13
+ }) {
14
+ const t = useTranslations("_global_ui.error");
15
+ useEffect(() => {
16
+ console.error(error);
17
+ }, [error]);
18
+
19
+ return (
20
+ <div>
21
+ <h2>{t("title")}</h2>
22
+ <button onClick={() => reset()}>{t("retry")}</button>
23
+ </div>
24
+ );
25
+ }
@@ -0,0 +1,5 @@
1
+ import LoadingUI from "@/ui/_global/Loading";
2
+
3
+ export default function Loading() {
4
+ return <LoadingUI />;
5
+ }
@@ -1,4 +1,4 @@
1
- import Dashboard from "@/ui/Dashboard/page-ui";
1
+ import Dashboard from "@/ui/dashboard/page-ui";
2
2
 
3
3
  export default function DashboardPage() {
4
4
  return <Dashboard />;
@@ -1,9 +1,31 @@
1
1
  // app/[locale]/(user)/layout.tsx
2
+ import { auth, isAuthConfigured } from "@/auth";
3
+ import { redirect } from "@/lib/i18n/navigation";
4
+ import GlobalHeader from "@/ui/_global/GlobalHeader";
5
+ import GlobalMain from "@/ui/_global/GlobalMain";
2
6
 
3
- export default function UserLayout({
7
+ export default async function UserLayout({
4
8
  children,
9
+ params,
5
10
  }: {
6
11
  children: React.ReactNode;
12
+ params: Promise<{ locale: string }>;
7
13
  }) {
8
- return children;
14
+ const { locale } = await params;
15
+ if (!isAuthConfigured()) {
16
+ redirect({ href: "/login", locale });
17
+ }
18
+
19
+ const session = await auth();
20
+
21
+ if (!session?.user) {
22
+ redirect({ href: "/login", locale });
23
+ }
24
+
25
+ return (
26
+ <>
27
+ <GlobalHeader hasSessionInitial />
28
+ <GlobalMain>{children}</GlobalMain>
29
+ </>
30
+ );
9
31
  }
@@ -0,0 +1,5 @@
1
+ import LoadingUI from "@/ui/_global/Loading";
2
+
3
+ export default function Loading() {
4
+ return <LoadingUI />;
5
+ }
@@ -1,5 +1,4 @@
1
- "use client";
2
- import SettingsPageUI from "@/ui/Settings/page-ui";
1
+ import SettingsPageUI from "@/ui/settings/page-ui";
3
2
 
4
3
  export default function UserInfoPage() {
5
4
  return <SettingsPageUI />;
@@ -0,0 +1,5 @@
1
+ import LoadingUI from "@/ui/_global/Loading";
2
+
3
+ export default function Loading() {
4
+ return <LoadingUI />;
5
+ }
@@ -1,5 +1,4 @@
1
- "use client";
2
- import UserInfoPageUI from "@/ui/UserInfo/page-ui";
1
+ import UserInfoPageUI from "@/ui/userInfo/page-ui";
3
2
 
4
3
  export default function UserInfoPage() {
5
4
  return <UserInfoPageUI />;
@@ -1,11 +1,26 @@
1
1
  // app/[locale]/layout.tsx
2
2
  import { NextIntlClientProvider } from "next-intl";
3
3
  import { setRequestLocale } from "next-intl/server";
4
+ import { hasLocale } from "next-intl";
5
+ import type { Metadata } from "next";
6
+ import { notFound } from "next/navigation";
7
+ import Script from "next/script";
4
8
  import React from "react";
5
- import "@/app/styles/globals.css"; // Import global styles
6
- import GlobalHeader from "@/ui/_global/GlobalHeader";
7
- import GlobalMain from "@/ui/_global/GlobalMain";
8
- import { isConnected } from "@/lib/auth/isConnected";
9
+ import "@/app/styles/globals.css";
10
+ import { routing } from "@/lib/i18n/routing";
11
+ import { getMessages } from "@/lib/i18n/messages";
12
+
13
+ export const metadata: Metadata = {
14
+ title: {
15
+ default: "Create Next Pro",
16
+ template: "%s | Create Next Pro",
17
+ },
18
+ description: "A Bun-first Next.js template for create-next-pro-cli.",
19
+ };
20
+
21
+ export function generateStaticParams() {
22
+ return routing.locales.map((locale) => ({ locale }));
23
+ }
9
24
 
10
25
  export default async function LocaleLayout({
11
26
  children,
@@ -15,16 +30,25 @@ export default async function LocaleLayout({
15
30
  params: Promise<{ locale: string }>;
16
31
  }) {
17
32
  const { locale } = await params;
18
- setRequestLocale(locale);
19
- const isConnectedInitial = await isConnected();
33
+ if (!hasLocale(routing.locales, locale)) {
34
+ notFound();
35
+ }
20
36
 
37
+ setRequestLocale(locale);
38
+ const messages = getMessages(locale);
21
39
  return (
22
- <html lang={locale}>
40
+ <html lang={locale} className="light" suppressHydrationWarning>
23
41
  <body>
24
- <NextIntlClientProvider>
25
- <GlobalHeader isConnectedInitial={isConnectedInitial} />
26
- <GlobalMain>{children}</GlobalMain>
42
+ <NextIntlClientProvider locale={locale} messages={messages}>
43
+ {children}
27
44
  </NextIntlClientProvider>
45
+ <Script
46
+ id="theme-initializer"
47
+ strategy="beforeInteractive"
48
+ dangerouslySetInnerHTML={{
49
+ __html: `try{var t=localStorage.getItem("theme");var d=t?t==="dark":window.matchMedia("(prefers-color-scheme: dark)").matches;document.documentElement.classList.toggle("dark",d);document.documentElement.classList.toggle("light",!d);}catch{document.documentElement.classList.add("light");}`,
50
+ }}
51
+ />
28
52
  </body>
29
53
  </html>
30
54
  );
@@ -1,14 +1,5 @@
1
- // app/[locale]/dashboard/loading.tsx
2
-
3
1
  import LoadingUI from "@/ui/_global/Loading";
4
2
 
5
3
  export default function Loading() {
6
4
  return <LoadingUI />;
7
5
  }
8
- // This component is used to show a loading state while the dashboard is being prepared
9
- // You can customize it with a spinner, skeletons, or any loading UI you prefer
10
- // It will be displayed when the dashboard is loading, for example during data fetching or component rendering
11
- // This is useful for providing feedback to users that something is happening in the background
12
- // You can also use this to implement a more complex loading state with animations or placeholders
13
- // Make sure to keep it lightweight to avoid blocking the main thread
14
- // This component is part of the Next.js app directory structure and will be automatically used by Next.js
@@ -1,22 +1,13 @@
1
- // app/[locale]/not-found.tsx
1
+ import { getTranslations } from "next-intl/server";
2
2
  import { Link } from "@/lib/i18n/navigation";
3
3
 
4
- export default function NotFound() {
4
+ export default async function NotFound() {
5
+ const t = await getTranslations("_global_ui.not_found");
5
6
  return (
6
7
  <div>
7
- <h2>Not Found</h2>
8
- <p>Could not find requested resource</p>
9
- <Link href="/">Return Home</Link>
8
+ <h2>{t("title")}</h2>
9
+ <p>{t("description")}</p>
10
+ <Link href="/">{t("home")}</Link>
10
11
  </div>
11
12
  );
12
13
  }
13
- // This page is used to handle 404 errors in the application
14
- // You can customize this page to display a user-friendly error message
15
- // or redirect to a different page if needed
16
- // This is part of the Next.js app directory structure and will be automatically used by Next.js
17
- // when a requested page is not found
18
- // Make sure to handle 404 errors gracefully to improve user experience
19
- // You can also log errors or send them to an error tracking service
20
- // This component can be styled with CSS or Tailwind CSS to match your application's design
21
- // You can also add additional links or actions for the user to take, such as searching or navigating to other parts of the site
22
- // This component is lightweight and does not block the main thread
@@ -1,6 +1,15 @@
1
1
  import React from "react";
2
2
  import HomePage from "@/app/[locale]/(public)/_home/page";
3
+ import GlobalHeader from "@/ui/_global/GlobalHeader";
4
+ import GlobalMain from "@/ui/_global/GlobalMain";
3
5
 
4
6
  export default async function FallbackPage() {
5
- return <HomePage />;
7
+ return (
8
+ <>
9
+ <GlobalHeader hasSessionInitial={false} />
10
+ <GlobalMain>
11
+ <HomePage />
12
+ </GlobalMain>
13
+ </>
14
+ );
6
15
  }