@clubedge/create-clubedge-app 0.2.1 → 0.4.0

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 (199) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +67 -36
  3. package/bin/create.mjs +2 -469
  4. package/dist/cli/args.js +54 -0
  5. package/dist/cli/ui.js +87 -0
  6. package/dist/core/customize.js +95 -0
  7. package/dist/core/execute.js +60 -0
  8. package/dist/core/manifest.js +119 -0
  9. package/dist/core/plan.js +132 -0
  10. package/dist/core/source.js +107 -0
  11. package/dist/index.js +160 -0
  12. package/dist/package-info.js +8 -0
  13. package/dist/steps/git.js +11 -0
  14. package/dist/steps/install.js +19 -0
  15. package/dist/utils/fs.js +100 -0
  16. package/dist/utils/names.js +14 -0
  17. package/dist/utils/process.js +49 -0
  18. package/package.json +19 -7
  19. package/template/.dockerignore +11 -0
  20. package/template/.env.example +25 -0
  21. package/template/.gitattributes +6 -0
  22. package/template/.github/ISSUE_TEMPLATE/bug_report.yml +35 -0
  23. package/template/.github/ISSUE_TEMPLATE/config.yml +8 -0
  24. package/template/.github/ISSUE_TEMPLATE/feature_request.yml +24 -0
  25. package/template/.github/pull_request_template.md +20 -0
  26. package/template/.github/workflows/ci.yml +96 -0
  27. package/template/.prettierignore +2 -0
  28. package/template/.prettierrc.json +1 -0
  29. package/template/AGENTS.md +32 -0
  30. package/template/CODE_OF_CONDUCT.md +22 -0
  31. package/template/CONTRIBUTING.md +53 -0
  32. package/template/Dockerfile +32 -0
  33. package/template/LICENSE +201 -0
  34. package/template/NOTICE +6 -0
  35. package/template/PUBLISHING.md +27 -0
  36. package/template/README.md +170 -0
  37. package/template/SECURITY.md +15 -0
  38. package/template/SETUP.md +196 -0
  39. package/template/SUPPORT.md +8 -0
  40. package/template/_gitignore +17 -0
  41. package/template/apps/start/.env.example +27 -0
  42. package/template/apps/start/AGENTS.md +11 -0
  43. package/template/apps/start/Dockerfile +38 -0
  44. package/template/apps/start/package.json +37 -0
  45. package/template/apps/start/public/.well-known/logo.svg +1 -0
  46. package/template/apps/start/public/favicon.ico +0 -0
  47. package/template/apps/start/src/components/auth/auth-form-controls.tsx +108 -0
  48. package/template/apps/start/src/components/branding/clubedge-mark.tsx +24 -0
  49. package/template/apps/start/src/components/dashboard/account-button.tsx +33 -0
  50. package/template/apps/start/src/components/dashboard/app-sidebar.tsx +90 -0
  51. package/template/apps/start/src/components/landing/copy-command.tsx +46 -0
  52. package/template/apps/start/src/components/theme/theme-provider.tsx +41 -0
  53. package/template/apps/start/src/components/theme/theme-toggle.tsx +21 -0
  54. package/template/apps/start/src/config/site.json +11 -0
  55. package/template/apps/start/src/config/site.ts +20 -0
  56. package/template/apps/start/src/env/server.test.ts +48 -0
  57. package/template/apps/start/src/env/server.ts +67 -0
  58. package/template/apps/start/src/lib/login-url.test.ts +16 -0
  59. package/template/apps/start/src/lib/login-url.ts +16 -0
  60. package/template/apps/start/src/routeTree.gen.ts +220 -0
  61. package/template/apps/start/src/router.tsx +27 -0
  62. package/template/apps/start/src/routes/__root.tsx +59 -0
  63. package/template/apps/start/src/routes/api/health.ts +15 -0
  64. package/template/apps/start/src/routes/auth/callback.ts +10 -0
  65. package/template/apps/start/src/routes/auth/sign-in.ts +11 -0
  66. package/template/apps/start/src/routes/auth/sign-out.ts +11 -0
  67. package/template/apps/start/src/routes/auth/sign-up.ts +11 -0
  68. package/template/apps/start/src/routes/dashboard.tsx +351 -0
  69. package/template/apps/start/src/routes/index.tsx +233 -0
  70. package/template/apps/start/src/routes/login.tsx +164 -0
  71. package/template/apps/start/src/server/auth-forms.test.ts +169 -0
  72. package/template/apps/start/src/server/auth-forms.ts +118 -0
  73. package/template/apps/start/src/server/auth.functions.ts +27 -0
  74. package/template/apps/start/src/server/auth.ts +51 -0
  75. package/template/apps/start/src/server/cache.ts +38 -0
  76. package/template/apps/start/src/server/cookies.test.ts +41 -0
  77. package/template/apps/start/src/server/cookies.ts +31 -0
  78. package/template/apps/start/src/server/db.ts +16 -0
  79. package/template/apps/start/src/server/storage.ts +39 -0
  80. package/template/apps/start/src/server/users.ts +17 -0
  81. package/template/apps/start/src/start.ts +40 -0
  82. package/template/apps/start/src/styles.css +2 -0
  83. package/template/apps/start/tsconfig.json +19 -0
  84. package/template/apps/start/vite.config.ts +27 -0
  85. package/template/apps/web/AGENTS.md +9 -0
  86. package/template/apps/web/components.json +21 -0
  87. package/template/apps/web/next-env.d.ts +7 -0
  88. package/template/apps/web/next.config.ts +32 -0
  89. package/template/apps/web/package.json +33 -0
  90. package/template/apps/web/postcss.config.mjs +3 -0
  91. package/template/apps/web/public/.gitkeep +0 -0
  92. package/template/apps/web/public/.well-known/logo.svg +1 -0
  93. package/template/apps/web/scripts/start-standalone.mjs +36 -0
  94. package/template/apps/web/src/app/actions/auth.ts +85 -0
  95. package/template/apps/web/src/app/api/health/route.ts +11 -0
  96. package/template/apps/web/src/app/auth/callback/route.ts +21 -0
  97. package/template/apps/web/src/app/dashboard/_components/account-button.tsx +34 -0
  98. package/template/apps/web/src/app/dashboard/_components/app-sidebar.tsx +91 -0
  99. package/template/apps/web/src/app/dashboard/page.tsx +352 -0
  100. package/template/apps/web/src/app/favicon.ico +0 -0
  101. package/template/apps/web/src/app/layout.tsx +36 -0
  102. package/template/apps/web/src/app/login/_components/auth-form-controls.tsx +88 -0
  103. package/template/apps/web/src/app/login/page.tsx +149 -0
  104. package/template/apps/web/src/app/page.tsx +229 -0
  105. package/template/apps/web/src/app/theme-provider.tsx +43 -0
  106. package/template/apps/web/src/app/theme-toggle.tsx +23 -0
  107. package/template/apps/web/src/components/branding/clubedge-mark.tsx +25 -0
  108. package/template/apps/web/src/components/landing/copy-command.tsx +48 -0
  109. package/template/apps/web/src/config/site.json +11 -0
  110. package/template/apps/web/src/config/site.ts +20 -0
  111. package/template/apps/web/src/env/client.ts +22 -0
  112. package/template/apps/web/src/env/server.test.ts +35 -0
  113. package/template/apps/web/src/env/server.ts +45 -0
  114. package/template/apps/web/src/lib/login-url.test.ts +16 -0
  115. package/template/apps/web/src/lib/login-url.ts +16 -0
  116. package/template/apps/web/src/lib/utils.ts +1 -0
  117. package/template/apps/web/src/proxy.ts +31 -0
  118. package/template/apps/web/src/server/auth.ts +69 -0
  119. package/template/apps/web/src/server/cache.ts +38 -0
  120. package/template/apps/web/src/server/db.ts +16 -0
  121. package/template/apps/web/src/server/storage.ts +39 -0
  122. package/template/apps/web/src/server/users.ts +17 -0
  123. package/template/apps/web/tsconfig.json +36 -0
  124. package/template/clubedge.template.json +29 -0
  125. package/template/docker-compose.yml +8 -0
  126. package/template/e2e/app.ts +12 -0
  127. package/template/e2e/auth.spec.ts +37 -0
  128. package/template/e2e/home.spec.ts +15 -0
  129. package/template/eslint.config.mjs +67 -0
  130. package/template/package.json +47 -0
  131. package/template/packages/auth/package.json +23 -0
  132. package/template/packages/auth/src/index.ts +9 -0
  133. package/template/packages/auth/src/supabase.test.ts +126 -0
  134. package/template/packages/auth/src/supabase.ts +65 -0
  135. package/template/packages/auth/src/types.ts +59 -0
  136. package/template/packages/auth/tsconfig.json +4 -0
  137. package/template/packages/cache/package.json +20 -0
  138. package/template/packages/cache/src/index.test.ts +67 -0
  139. package/template/packages/cache/src/index.ts +19 -0
  140. package/template/packages/cache/src/rate-limit.test.ts +52 -0
  141. package/template/packages/cache/src/rate-limit.ts +74 -0
  142. package/template/packages/cache/src/redis.ts +106 -0
  143. package/template/packages/cache/tsconfig.json +4 -0
  144. package/template/packages/core/package.json +17 -0
  145. package/template/packages/core/src/client-ip.test.ts +19 -0
  146. package/template/packages/core/src/client-ip.ts +11 -0
  147. package/template/packages/core/src/errors.test.ts +20 -0
  148. package/template/packages/core/src/errors.ts +20 -0
  149. package/template/packages/core/src/index.ts +4 -0
  150. package/template/packages/core/src/redirect.test.ts +27 -0
  151. package/template/packages/core/src/redirect.ts +20 -0
  152. package/template/packages/core/src/result.ts +10 -0
  153. package/template/packages/core/tsconfig.json +4 -0
  154. package/template/packages/db/drizzle/0000_initial.sql +10 -0
  155. package/template/packages/db/drizzle/meta/_journal.json +13 -0
  156. package/template/packages/db/drizzle.config.ts +9 -0
  157. package/template/packages/db/package.json +30 -0
  158. package/template/packages/db/scripts/load-env.ts +14 -0
  159. package/template/packages/db/scripts/migrate.ts +11 -0
  160. package/template/packages/db/scripts/seed.ts +14 -0
  161. package/template/packages/db/src/client.ts +22 -0
  162. package/template/packages/db/src/index.ts +4 -0
  163. package/template/packages/db/src/schema/index.ts +1 -0
  164. package/template/packages/db/src/schema/users.ts +14 -0
  165. package/template/packages/db/src/users.ts +16 -0
  166. package/template/packages/db/tsconfig.json +4 -0
  167. package/template/packages/storage/package.json +24 -0
  168. package/template/packages/storage/src/index.ts +1 -0
  169. package/template/packages/storage/src/s3.test.ts +86 -0
  170. package/template/packages/storage/src/s3.ts +86 -0
  171. package/template/packages/storage/src/supabase.ts +69 -0
  172. package/template/packages/storage/src/types.ts +18 -0
  173. package/template/packages/storage/tsconfig.json +4 -0
  174. package/template/packages/ui/components.json +21 -0
  175. package/template/packages/ui/package.json +32 -0
  176. package/template/packages/ui/src/components/badge.tsx +48 -0
  177. package/template/packages/ui/src/components/breadcrumb.tsx +102 -0
  178. package/template/packages/ui/src/components/button.tsx +57 -0
  179. package/template/packages/ui/src/components/card.tsx +87 -0
  180. package/template/packages/ui/src/components/input.tsx +19 -0
  181. package/template/packages/ui/src/components/label.tsx +19 -0
  182. package/template/packages/ui/src/components/separator.tsx +20 -0
  183. package/template/packages/ui/src/components/sheet.tsx +125 -0
  184. package/template/packages/ui/src/components/sidebar.tsx +692 -0
  185. package/template/packages/ui/src/components/skeleton.tsx +13 -0
  186. package/template/packages/ui/src/components/switch.tsx +31 -0
  187. package/template/packages/ui/src/components/table.tsx +88 -0
  188. package/template/packages/ui/src/components/tooltip.tsx +53 -0
  189. package/template/packages/ui/src/hooks/use-mobile.ts +19 -0
  190. package/template/packages/ui/src/lib/utils.ts +1 -0
  191. package/template/packages/ui/src/styles/globals.css +126 -0
  192. package/template/packages/ui/tsconfig.json +19 -0
  193. package/template/playwright.config.ts +23 -0
  194. package/template/pnpm-lock.yaml +4987 -0
  195. package/template/pnpm-workspace.yaml +3 -0
  196. package/template/tsconfig.base.json +16 -0
  197. package/template/turbo.json +17 -0
  198. package/template/vitest.config.ts +10 -0
  199. package/template.lock.json +187 -0
@@ -0,0 +1,16 @@
1
+ type LoginUrlOptions = {
2
+ mode?: "signin" | "signup";
3
+ error?: string;
4
+ next?: string;
5
+ checkEmail?: boolean;
6
+ };
7
+
8
+ export function loginUrl({ mode = "signin", error, next, checkEmail }: LoginUrlOptions = {}) {
9
+ const params = new URLSearchParams();
10
+ if (mode === "signup") params.set("mode", "signup");
11
+ if (error) params.set("error", error);
12
+ if (checkEmail) params.set("check-email", "1");
13
+ if (next && next !== "/dashboard") params.set("next", next);
14
+ const query = params.toString();
15
+ return query ? `/login?${query}` : "/login";
16
+ }
@@ -0,0 +1,220 @@
1
+ /* eslint-disable */
2
+
3
+ // @ts-nocheck
4
+
5
+ // noinspection JSUnusedGlobalSymbols
6
+
7
+ // This file was automatically generated by TanStack Router.
8
+ // You should NOT make any changes in this file as it will be overwritten.
9
+ // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
10
+
11
+ import { Route as rootRouteImport } from './routes/__root'
12
+ import { Route as IndexRouteImport } from './routes/index'
13
+ import { Route as DashboardRouteImport } from './routes/dashboard'
14
+ import { Route as LoginRouteImport } from './routes/login'
15
+ import { Route as ApiHealthRouteImport } from './routes/api/health'
16
+ import { Route as AuthCallbackRouteImport } from './routes/auth/callback'
17
+ import { Route as AuthSignInRouteImport } from './routes/auth/sign-in'
18
+ import { Route as AuthSignOutRouteImport } from './routes/auth/sign-out'
19
+ import { Route as AuthSignUpRouteImport } from './routes/auth/sign-up'
20
+
21
+ const IndexRoute = IndexRouteImport.update({
22
+ id: '/',
23
+ path: '/',
24
+ getParentRoute: () => rootRouteImport,
25
+ } as any)
26
+ const DashboardRoute = DashboardRouteImport.update({
27
+ id: '/dashboard',
28
+ path: '/dashboard',
29
+ getParentRoute: () => rootRouteImport,
30
+ } as any)
31
+ const LoginRoute = LoginRouteImport.update({
32
+ id: '/login',
33
+ path: '/login',
34
+ getParentRoute: () => rootRouteImport,
35
+ } as any)
36
+ const ApiHealthRoute = ApiHealthRouteImport.update({
37
+ id: '/api/health',
38
+ path: '/api/health',
39
+ getParentRoute: () => rootRouteImport,
40
+ } as any)
41
+ const AuthCallbackRoute = AuthCallbackRouteImport.update({
42
+ id: '/auth/callback',
43
+ path: '/auth/callback',
44
+ getParentRoute: () => rootRouteImport,
45
+ } as any)
46
+ const AuthSignInRoute = AuthSignInRouteImport.update({
47
+ id: '/auth/sign-in',
48
+ path: '/auth/sign-in',
49
+ getParentRoute: () => rootRouteImport,
50
+ } as any)
51
+ const AuthSignOutRoute = AuthSignOutRouteImport.update({
52
+ id: '/auth/sign-out',
53
+ path: '/auth/sign-out',
54
+ getParentRoute: () => rootRouteImport,
55
+ } as any)
56
+ const AuthSignUpRoute = AuthSignUpRouteImport.update({
57
+ id: '/auth/sign-up',
58
+ path: '/auth/sign-up',
59
+ getParentRoute: () => rootRouteImport,
60
+ } as any)
61
+
62
+ export interface FileRoutesByFullPath {
63
+ '/': typeof IndexRoute
64
+ '/dashboard': typeof DashboardRoute
65
+ '/login': typeof LoginRoute
66
+ '/api/health': typeof ApiHealthRoute
67
+ '/auth/callback': typeof AuthCallbackRoute
68
+ '/auth/sign-in': typeof AuthSignInRoute
69
+ '/auth/sign-out': typeof AuthSignOutRoute
70
+ '/auth/sign-up': typeof AuthSignUpRoute
71
+ }
72
+ export interface FileRoutesByTo {
73
+ '/': typeof IndexRoute
74
+ '/dashboard': typeof DashboardRoute
75
+ '/login': typeof LoginRoute
76
+ '/api/health': typeof ApiHealthRoute
77
+ '/auth/callback': typeof AuthCallbackRoute
78
+ '/auth/sign-in': typeof AuthSignInRoute
79
+ '/auth/sign-out': typeof AuthSignOutRoute
80
+ '/auth/sign-up': typeof AuthSignUpRoute
81
+ }
82
+ export interface FileRoutesById {
83
+ __root__: typeof rootRouteImport
84
+ '/': typeof IndexRoute
85
+ '/dashboard': typeof DashboardRoute
86
+ '/login': typeof LoginRoute
87
+ '/api/health': typeof ApiHealthRoute
88
+ '/auth/callback': typeof AuthCallbackRoute
89
+ '/auth/sign-in': typeof AuthSignInRoute
90
+ '/auth/sign-out': typeof AuthSignOutRoute
91
+ '/auth/sign-up': typeof AuthSignUpRoute
92
+ }
93
+ export interface FileRouteTypes {
94
+ fileRoutesByFullPath: FileRoutesByFullPath
95
+ fullPaths:
96
+ | '/'
97
+ | '/dashboard'
98
+ | '/login'
99
+ | '/api/health'
100
+ | '/auth/callback'
101
+ | '/auth/sign-in'
102
+ | '/auth/sign-out'
103
+ | '/auth/sign-up'
104
+ fileRoutesByTo: FileRoutesByTo
105
+ to:
106
+ | '/'
107
+ | '/dashboard'
108
+ | '/login'
109
+ | '/api/health'
110
+ | '/auth/callback'
111
+ | '/auth/sign-in'
112
+ | '/auth/sign-out'
113
+ | '/auth/sign-up'
114
+ id:
115
+ | '__root__'
116
+ | '/'
117
+ | '/dashboard'
118
+ | '/login'
119
+ | '/api/health'
120
+ | '/auth/callback'
121
+ | '/auth/sign-in'
122
+ | '/auth/sign-out'
123
+ | '/auth/sign-up'
124
+ fileRoutesById: FileRoutesById
125
+ }
126
+ export interface RootRouteChildren {
127
+ IndexRoute: typeof IndexRoute
128
+ DashboardRoute: typeof DashboardRoute
129
+ LoginRoute: typeof LoginRoute
130
+ ApiHealthRoute: typeof ApiHealthRoute
131
+ AuthCallbackRoute: typeof AuthCallbackRoute
132
+ AuthSignInRoute: typeof AuthSignInRoute
133
+ AuthSignOutRoute: typeof AuthSignOutRoute
134
+ AuthSignUpRoute: typeof AuthSignUpRoute
135
+ }
136
+
137
+ declare module '@tanstack/react-router' {
138
+ interface FileRoutesByPath {
139
+ '/': {
140
+ id: '/'
141
+ path: '/'
142
+ fullPath: '/'
143
+ preLoaderRoute: typeof IndexRouteImport
144
+ parentRoute: typeof rootRouteImport
145
+ }
146
+ '/dashboard': {
147
+ id: '/dashboard'
148
+ path: '/dashboard'
149
+ fullPath: '/dashboard'
150
+ preLoaderRoute: typeof DashboardRouteImport
151
+ parentRoute: typeof rootRouteImport
152
+ }
153
+ '/login': {
154
+ id: '/login'
155
+ path: '/login'
156
+ fullPath: '/login'
157
+ preLoaderRoute: typeof LoginRouteImport
158
+ parentRoute: typeof rootRouteImport
159
+ }
160
+ '/api/health': {
161
+ id: '/api/health'
162
+ path: '/api/health'
163
+ fullPath: '/api/health'
164
+ preLoaderRoute: typeof ApiHealthRouteImport
165
+ parentRoute: typeof rootRouteImport
166
+ }
167
+ '/auth/callback': {
168
+ id: '/auth/callback'
169
+ path: '/auth/callback'
170
+ fullPath: '/auth/callback'
171
+ preLoaderRoute: typeof AuthCallbackRouteImport
172
+ parentRoute: typeof rootRouteImport
173
+ }
174
+ '/auth/sign-in': {
175
+ id: '/auth/sign-in'
176
+ path: '/auth/sign-in'
177
+ fullPath: '/auth/sign-in'
178
+ preLoaderRoute: typeof AuthSignInRouteImport
179
+ parentRoute: typeof rootRouteImport
180
+ }
181
+ '/auth/sign-out': {
182
+ id: '/auth/sign-out'
183
+ path: '/auth/sign-out'
184
+ fullPath: '/auth/sign-out'
185
+ preLoaderRoute: typeof AuthSignOutRouteImport
186
+ parentRoute: typeof rootRouteImport
187
+ }
188
+ '/auth/sign-up': {
189
+ id: '/auth/sign-up'
190
+ path: '/auth/sign-up'
191
+ fullPath: '/auth/sign-up'
192
+ preLoaderRoute: typeof AuthSignUpRouteImport
193
+ parentRoute: typeof rootRouteImport
194
+ }
195
+ }
196
+ }
197
+
198
+ const rootRouteChildren: RootRouteChildren = {
199
+ IndexRoute: IndexRoute,
200
+ DashboardRoute: DashboardRoute,
201
+ LoginRoute: LoginRoute,
202
+ ApiHealthRoute: ApiHealthRoute,
203
+ AuthCallbackRoute: AuthCallbackRoute,
204
+ AuthSignInRoute: AuthSignInRoute,
205
+ AuthSignOutRoute: AuthSignOutRoute,
206
+ AuthSignUpRoute: AuthSignUpRoute,
207
+ }
208
+ export const routeTree = rootRouteImport
209
+ ._addFileChildren(rootRouteChildren)
210
+ ._addFileTypes<FileRouteTypes>()
211
+
212
+ import type { getRouter } from './router.tsx'
213
+ import type { startInstance } from './start.ts'
214
+ declare module '@tanstack/react-start' {
215
+ interface Register {
216
+ ssr: true
217
+ router: Awaited<ReturnType<typeof getRouter>>
218
+ config: Awaited<ReturnType<typeof startInstance.getOptions>>
219
+ }
220
+ }
@@ -0,0 +1,27 @@
1
+ import { createRouter } from "@tanstack/react-router";
2
+ import { routeTree } from "./routeTree.gen";
3
+
4
+ // Plain ?key=value search params, as in the Next.js app and the URLs built by loginUrl().
5
+ // The router's default JSON encoding would rewrite ?check-email=1 to ?check-email=%221%22.
6
+ function parseSearch(search: string): Record<string, string> {
7
+ return Object.fromEntries(new URLSearchParams(search));
8
+ }
9
+
10
+ function stringifySearch(search: Record<string, unknown>): string {
11
+ const params = new URLSearchParams();
12
+ for (const [key, value] of Object.entries(search)) {
13
+ if (value !== undefined && value !== null) params.set(key, String(value));
14
+ }
15
+ const query = params.toString();
16
+ return query ? `?${query}` : "";
17
+ }
18
+
19
+ export function getRouter() {
20
+ return createRouter({
21
+ routeTree,
22
+ parseSearch,
23
+ stringifySearch,
24
+ scrollRestoration: true,
25
+ defaultPreload: "intent",
26
+ });
27
+ }
@@ -0,0 +1,59 @@
1
+ import type { ReactNode } from "react";
2
+ import { HeadContent, Outlet, Scripts, createRootRoute } from "@tanstack/react-router";
3
+ import { TooltipProvider } from "@clubedge/ui/components/tooltip";
4
+ import { ThemeProvider } from "@/components/theme/theme-provider";
5
+ import { siteConfig } from "@/config/site";
6
+ import appCss from "../styles.css?url";
7
+
8
+ // Applies the saved or preferred theme before first paint to avoid a flash.
9
+ const themeBootstrap = `try {
10
+ const saved = localStorage.getItem("clubedge-theme");
11
+ const theme = saved === "light" || saved === "dark"
12
+ ? saved
13
+ : window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
14
+ document.documentElement.classList.toggle("dark", theme === "dark");
15
+ document.documentElement.style.colorScheme = theme;
16
+ } catch {}
17
+ `;
18
+
19
+ export const Route = createRootRoute({
20
+ head: () => ({
21
+ meta: [
22
+ { charSet: "utf-8" },
23
+ { name: "viewport", content: "width=device-width, initial-scale=1" },
24
+ { title: siteConfig.name },
25
+ { name: "description", content: siteConfig.description },
26
+ ],
27
+ links: [
28
+ { rel: "stylesheet", href: appCss },
29
+ { rel: "icon", href: "/favicon.ico" },
30
+ ],
31
+ scripts: [{ children: themeBootstrap }],
32
+ }),
33
+ shellComponent: RootDocument,
34
+ component: RootComponent,
35
+ });
36
+
37
+ function RootComponent() {
38
+ return (
39
+ <ThemeProvider>
40
+ <TooltipProvider>
41
+ <Outlet />
42
+ </TooltipProvider>
43
+ </ThemeProvider>
44
+ );
45
+ }
46
+
47
+ function RootDocument({ children }: Readonly<{ children: ReactNode }>) {
48
+ return (
49
+ <html lang="en" suppressHydrationWarning>
50
+ <head>
51
+ <HeadContent />
52
+ </head>
53
+ <body>
54
+ {children}
55
+ <Scripts />
56
+ </body>
57
+ </html>
58
+ );
59
+ }
@@ -0,0 +1,15 @@
1
+ import { createFileRoute } from "@tanstack/react-router";
2
+ import { siteConfig } from "@/config/site";
3
+
4
+ export const Route = createFileRoute("/api/health")({
5
+ server: {
6
+ handlers: {
7
+ GET: () =>
8
+ Response.json({
9
+ status: "ok",
10
+ service: siteConfig.serviceId,
11
+ timestamp: new Date().toISOString(),
12
+ }),
13
+ },
14
+ },
15
+ });
@@ -0,0 +1,10 @@
1
+ import { createFileRoute } from "@tanstack/react-router";
2
+ import { handleAuthCallback } from "@/server/auth-forms";
3
+
4
+ export const Route = createFileRoute("/auth/callback")({
5
+ server: {
6
+ handlers: {
7
+ GET: ({ request }) => handleAuthCallback(request),
8
+ },
9
+ },
10
+ });
@@ -0,0 +1,11 @@
1
+ import { createFileRoute } from "@tanstack/react-router";
2
+ import { handleFormEndpointVisit, handleSignIn } from "@/server/auth-forms";
3
+
4
+ export const Route = createFileRoute("/auth/sign-in")({
5
+ server: {
6
+ handlers: {
7
+ GET: () => handleFormEndpointVisit(),
8
+ POST: ({ request }) => handleSignIn(request),
9
+ },
10
+ },
11
+ });
@@ -0,0 +1,11 @@
1
+ import { createFileRoute } from "@tanstack/react-router";
2
+ import { handleFormEndpointVisit, handleSignOut } from "@/server/auth-forms";
3
+
4
+ export const Route = createFileRoute("/auth/sign-out")({
5
+ server: {
6
+ handlers: {
7
+ GET: () => handleFormEndpointVisit(),
8
+ POST: () => handleSignOut(),
9
+ },
10
+ },
11
+ });
@@ -0,0 +1,11 @@
1
+ import { createFileRoute } from "@tanstack/react-router";
2
+ import { handleFormEndpointVisit, handleSignUp } from "@/server/auth-forms";
3
+
4
+ export const Route = createFileRoute("/auth/sign-up")({
5
+ server: {
6
+ handlers: {
7
+ GET: () => handleFormEndpointVisit(),
8
+ POST: ({ request }) => handleSignUp(request),
9
+ },
10
+ },
11
+ });