create-velox-app 0.6.29 → 0.6.51

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 (223) hide show
  1. package/CHANGELOG.md +132 -0
  2. package/GUIDE.md +230 -0
  3. package/dist/cli.d.ts +0 -1
  4. package/dist/cli.js +1 -1
  5. package/dist/index.d.ts +0 -1
  6. package/dist/index.js +14 -5
  7. package/dist/templates/auth.d.ts +0 -1
  8. package/dist/templates/auth.js +10 -1
  9. package/dist/templates/compiler.d.ts +0 -1
  10. package/dist/templates/compiler.js +0 -1
  11. package/dist/templates/index.d.ts +0 -1
  12. package/dist/templates/index.js +30 -2
  13. package/dist/templates/placeholders.d.ts +6 -1
  14. package/dist/templates/placeholders.js +55 -1
  15. package/dist/templates/rsc-auth.d.ts +12 -0
  16. package/dist/templates/rsc-auth.js +208 -0
  17. package/dist/templates/rsc.d.ts +0 -1
  18. package/dist/templates/rsc.js +40 -2
  19. package/dist/templates/shared/css-generator.d.ts +26 -0
  20. package/dist/templates/shared/css-generator.js +553 -0
  21. package/dist/templates/shared/index.d.ts +3 -1
  22. package/dist/templates/shared/index.js +3 -1
  23. package/dist/templates/shared/root.d.ts +0 -1
  24. package/dist/templates/shared/root.js +11 -2
  25. package/dist/templates/shared/rsc-styles.d.ts +54 -0
  26. package/dist/templates/shared/rsc-styles.js +68 -0
  27. package/dist/templates/shared/theme.d.ts +133 -0
  28. package/dist/templates/shared/theme.js +141 -0
  29. package/dist/templates/shared/web-base.d.ts +0 -1
  30. package/dist/templates/shared/web-base.js +0 -1
  31. package/dist/templates/shared/web-styles.d.ts +0 -1
  32. package/dist/templates/shared/web-styles.js +0 -1
  33. package/dist/templates/shared.d.ts +0 -1
  34. package/dist/templates/shared.js +0 -1
  35. package/dist/templates/spa.d.ts +0 -1
  36. package/dist/templates/spa.js +10 -1
  37. package/dist/templates/trpc.d.ts +0 -1
  38. package/dist/templates/trpc.js +10 -1
  39. package/dist/templates/types.d.ts +2 -2
  40. package/dist/templates/types.js +6 -1
  41. package/package.json +6 -3
  42. package/src/templates/source/api/config/database.ts +13 -32
  43. package/src/templates/source/api/docker-compose.yml +21 -0
  44. package/src/templates/source/root/CLAUDE.auth.md +6 -0
  45. package/src/templates/source/root/CLAUDE.default.md +6 -0
  46. package/src/templates/source/root/package.json +6 -6
  47. package/src/templates/source/rsc/CLAUDE.md +56 -2
  48. package/src/templates/source/rsc/app/actions/posts.ts +1 -1
  49. package/src/templates/source/rsc/app/actions/users.ts +111 -20
  50. package/src/templates/source/rsc/app/layouts/dashboard.tsx +21 -16
  51. package/src/templates/source/rsc/app/layouts/marketing.tsx +34 -0
  52. package/src/templates/source/rsc/app/layouts/minimal-content.tsx +21 -0
  53. package/src/templates/source/rsc/app/layouts/minimal.tsx +86 -5
  54. package/src/templates/source/rsc/app/layouts/root.tsx +148 -44
  55. package/src/templates/source/rsc/docker-compose.yml +21 -0
  56. package/src/templates/source/rsc/package.json +3 -3
  57. package/src/templates/source/rsc/src/api/database.ts +13 -32
  58. package/src/templates/source/rsc/src/api/handler.ts +1 -1
  59. package/src/templates/source/rsc/src/entry.client.tsx +65 -18
  60. package/src/templates/source/rsc-auth/CLAUDE.md +230 -0
  61. package/src/templates/source/rsc-auth/app/actions/auth.ts +112 -0
  62. package/src/templates/source/rsc-auth/app/actions/users.ts +289 -0
  63. package/src/templates/source/rsc-auth/app/layouts/dashboard.tsx +132 -0
  64. package/src/templates/source/rsc-auth/app/layouts/marketing.tsx +59 -0
  65. package/src/templates/source/rsc-auth/app/layouts/minimal-content.tsx +21 -0
  66. package/src/templates/source/rsc-auth/app/layouts/minimal.tsx +111 -0
  67. package/src/templates/source/rsc-auth/app/layouts/root.tsx +355 -0
  68. package/src/templates/source/rsc-auth/app/pages/_not-found.tsx +15 -0
  69. package/src/templates/source/rsc-auth/app/pages/auth/login.tsx +198 -0
  70. package/src/templates/source/rsc-auth/app/pages/auth/register.tsx +225 -0
  71. package/src/templates/source/rsc-auth/app/pages/dashboard/index.tsx +267 -0
  72. package/src/templates/source/rsc-auth/app/pages/index.tsx +83 -0
  73. package/src/templates/source/rsc-auth/app/pages/users.tsx +47 -0
  74. package/src/templates/source/rsc-auth/app.config.ts +12 -0
  75. package/src/templates/source/rsc-auth/docker-compose.yml +21 -0
  76. package/src/templates/source/rsc-auth/env.example +11 -0
  77. package/src/templates/source/rsc-auth/gitignore +34 -0
  78. package/src/templates/source/rsc-auth/package.json +44 -0
  79. package/src/templates/source/rsc-auth/prisma/schema.prisma +23 -0
  80. package/src/templates/source/rsc-auth/prisma.config.ts +22 -0
  81. package/src/templates/source/rsc-auth/public/favicon.svg +4 -0
  82. package/src/templates/source/rsc-auth/src/api/database.ts +129 -0
  83. package/src/templates/source/rsc-auth/src/api/handler.ts +85 -0
  84. package/src/templates/source/rsc-auth/src/api/procedures/auth.ts +262 -0
  85. package/src/templates/source/rsc-auth/src/api/procedures/health.ts +48 -0
  86. package/src/templates/source/rsc-auth/src/api/procedures/users.ts +87 -0
  87. package/src/templates/source/rsc-auth/src/api/schemas/auth.ts +79 -0
  88. package/src/templates/source/rsc-auth/src/api/schemas/user.ts +38 -0
  89. package/src/templates/source/rsc-auth/src/api/utils/auth.ts +157 -0
  90. package/src/templates/source/rsc-auth/src/entry.client.tsx +63 -0
  91. package/src/templates/source/rsc-auth/src/entry.server.tsx +262 -0
  92. package/src/templates/source/rsc-auth/tsconfig.json +24 -0
  93. package/src/templates/source/shared/scripts/check-client-imports.sh +75 -0
  94. package/dist/cli.d.ts.map +0 -1
  95. package/dist/cli.js.map +0 -1
  96. package/dist/index.d.ts.map +0 -1
  97. package/dist/index.js.map +0 -1
  98. package/dist/templates/auth.d.ts.map +0 -1
  99. package/dist/templates/auth.js.map +0 -1
  100. package/dist/templates/compiler.d.ts.map +0 -1
  101. package/dist/templates/compiler.js.map +0 -1
  102. package/dist/templates/default.d.ts +0 -12
  103. package/dist/templates/default.d.ts.map +0 -1
  104. package/dist/templates/default.js +0 -85
  105. package/dist/templates/default.js.map +0 -1
  106. package/dist/templates/fullstack.d.ts +0 -15
  107. package/dist/templates/fullstack.d.ts.map +0 -1
  108. package/dist/templates/fullstack.js +0 -110
  109. package/dist/templates/fullstack.js.map +0 -1
  110. package/dist/templates/index.d.ts.map +0 -1
  111. package/dist/templates/index.js.map +0 -1
  112. package/dist/templates/placeholders.d.ts.map +0 -1
  113. package/dist/templates/placeholders.js.map +0 -1
  114. package/dist/templates/rsc.d.ts.map +0 -1
  115. package/dist/templates/rsc.js.map +0 -1
  116. package/dist/templates/shared/index.d.ts.map +0 -1
  117. package/dist/templates/shared/index.js.map +0 -1
  118. package/dist/templates/shared/root.d.ts.map +0 -1
  119. package/dist/templates/shared/root.js.map +0 -1
  120. package/dist/templates/shared/web-base.d.ts.map +0 -1
  121. package/dist/templates/shared/web-base.js.map +0 -1
  122. package/dist/templates/shared/web-styles.d.ts.map +0 -1
  123. package/dist/templates/shared/web-styles.js.map +0 -1
  124. package/dist/templates/shared.d.ts.map +0 -1
  125. package/dist/templates/shared.js.map +0 -1
  126. package/dist/templates/source/api/config/app.d.ts +0 -13
  127. package/dist/templates/source/api/config/app.d.ts.map +0 -1
  128. package/dist/templates/source/api/config/app.js +0 -14
  129. package/dist/templates/source/api/config/app.js.map +0 -1
  130. package/dist/templates/source/api/config/auth.d.ts +0 -34
  131. package/dist/templates/source/api/config/auth.d.ts.map +0 -1
  132. package/dist/templates/source/api/config/auth.js +0 -165
  133. package/dist/templates/source/api/config/auth.js.map +0 -1
  134. package/dist/templates/source/api/config/index.auth.d.ts +0 -6
  135. package/dist/templates/source/api/config/index.auth.d.ts.map +0 -1
  136. package/dist/templates/source/api/config/index.auth.js +0 -6
  137. package/dist/templates/source/api/config/index.auth.js.map +0 -1
  138. package/dist/templates/source/api/config/index.default.d.ts +0 -5
  139. package/dist/templates/source/api/config/index.default.d.ts.map +0 -1
  140. package/dist/templates/source/api/config/index.default.js +0 -5
  141. package/dist/templates/source/api/config/index.default.js.map +0 -1
  142. package/dist/templates/source/api/database/index.d.ts +0 -9
  143. package/dist/templates/source/api/database/index.d.ts.map +0 -1
  144. package/dist/templates/source/api/database/index.js +0 -18
  145. package/dist/templates/source/api/database/index.js.map +0 -1
  146. package/dist/templates/source/api/index.auth.d.ts +0 -5
  147. package/dist/templates/source/api/index.auth.d.ts.map +0 -1
  148. package/dist/templates/source/api/index.auth.js +0 -59
  149. package/dist/templates/source/api/index.auth.js.map +0 -1
  150. package/dist/templates/source/api/index.default.d.ts +0 -5
  151. package/dist/templates/source/api/index.default.d.ts.map +0 -1
  152. package/dist/templates/source/api/index.default.js +0 -56
  153. package/dist/templates/source/api/index.default.js.map +0 -1
  154. package/dist/templates/source/api/prisma.config.d.ts +0 -9
  155. package/dist/templates/source/api/prisma.config.d.ts.map +0 -1
  156. package/dist/templates/source/api/prisma.config.js +0 -15
  157. package/dist/templates/source/api/prisma.config.js.map +0 -1
  158. package/dist/templates/source/api/procedures/auth.d.ts +0 -14
  159. package/dist/templates/source/api/procedures/auth.d.ts.map +0 -1
  160. package/dist/templates/source/api/procedures/auth.js +0 -221
  161. package/dist/templates/source/api/procedures/auth.js.map +0 -1
  162. package/dist/templates/source/api/procedures/health.d.ts +0 -5
  163. package/dist/templates/source/api/procedures/health.d.ts.map +0 -1
  164. package/dist/templates/source/api/procedures/health.js +0 -21
  165. package/dist/templates/source/api/procedures/health.js.map +0 -1
  166. package/dist/templates/source/api/procedures/index.auth.d.ts +0 -7
  167. package/dist/templates/source/api/procedures/index.auth.d.ts.map +0 -1
  168. package/dist/templates/source/api/procedures/index.auth.js +0 -7
  169. package/dist/templates/source/api/procedures/index.auth.js.map +0 -1
  170. package/dist/templates/source/api/procedures/index.default.d.ts +0 -6
  171. package/dist/templates/source/api/procedures/index.default.d.ts.map +0 -1
  172. package/dist/templates/source/api/procedures/index.default.js +0 -6
  173. package/dist/templates/source/api/procedures/index.default.js.map +0 -1
  174. package/dist/templates/source/api/procedures/users.auth.d.ts +0 -7
  175. package/dist/templates/source/api/procedures/users.auth.d.ts.map +0 -1
  176. package/dist/templates/source/api/procedures/users.auth.js +0 -111
  177. package/dist/templates/source/api/procedures/users.auth.js.map +0 -1
  178. package/dist/templates/source/api/procedures/users.default.d.ts +0 -5
  179. package/dist/templates/source/api/procedures/users.default.d.ts.map +0 -1
  180. package/dist/templates/source/api/procedures/users.default.js +0 -86
  181. package/dist/templates/source/api/procedures/users.default.js.map +0 -1
  182. package/dist/templates/source/api/schemas/index.d.ts +0 -5
  183. package/dist/templates/source/api/schemas/index.d.ts.map +0 -1
  184. package/dist/templates/source/api/schemas/index.js +0 -5
  185. package/dist/templates/source/api/schemas/index.js.map +0 -1
  186. package/dist/templates/source/api/schemas/user.d.ts +0 -11
  187. package/dist/templates/source/api/schemas/user.d.ts.map +0 -1
  188. package/dist/templates/source/api/schemas/user.js +0 -20
  189. package/dist/templates/source/api/schemas/user.js.map +0 -1
  190. package/dist/templates/source/api/tsup.config.d.ts +0 -3
  191. package/dist/templates/source/api/tsup.config.d.ts.map +0 -1
  192. package/dist/templates/source/api/tsup.config.js +0 -10
  193. package/dist/templates/source/api/tsup.config.js.map +0 -1
  194. package/dist/templates/source/web/main.d.ts +0 -9
  195. package/dist/templates/source/web/main.d.ts.map +0 -1
  196. package/dist/templates/source/web/main.js +0 -27
  197. package/dist/templates/source/web/main.js.map +0 -1
  198. package/dist/templates/source/web/routes/__root.d.ts +0 -2
  199. package/dist/templates/source/web/routes/__root.d.ts.map +0 -1
  200. package/dist/templates/source/web/routes/__root.js +0 -28
  201. package/dist/templates/source/web/routes/__root.js.map +0 -1
  202. package/dist/templates/source/web/routes/about.d.ts +0 -2
  203. package/dist/templates/source/web/routes/about.d.ts.map +0 -1
  204. package/dist/templates/source/web/routes/about.js +0 -33
  205. package/dist/templates/source/web/routes/about.js.map +0 -1
  206. package/dist/templates/source/web/routes/index.auth.d.ts +0 -2
  207. package/dist/templates/source/web/routes/index.auth.d.ts.map +0 -1
  208. package/dist/templates/source/web/routes/index.auth.js +0 -159
  209. package/dist/templates/source/web/routes/index.auth.js.map +0 -1
  210. package/dist/templates/source/web/routes/index.default.d.ts +0 -2
  211. package/dist/templates/source/web/routes/index.default.d.ts.map +0 -1
  212. package/dist/templates/source/web/routes/index.default.js +0 -60
  213. package/dist/templates/source/web/routes/index.default.js.map +0 -1
  214. package/dist/templates/source/web/vite.config.d.ts +0 -3
  215. package/dist/templates/source/web/vite.config.d.ts.map +0 -1
  216. package/dist/templates/source/web/vite.config.js +0 -22
  217. package/dist/templates/source/web/vite.config.js.map +0 -1
  218. package/dist/templates/spa.d.ts.map +0 -1
  219. package/dist/templates/spa.js.map +0 -1
  220. package/dist/templates/trpc.d.ts.map +0 -1
  221. package/dist/templates/trpc.js.map +0 -1
  222. package/dist/templates/types.d.ts.map +0 -1
  223. package/dist/templates/types.js.map +0 -1
@@ -21,19 +21,84 @@ export default function RootLayout({ children }: RootLayoutProps) {
21
21
  <title>VeloxTS App</title>
22
22
  <link rel="icon" href="/favicon.svg" type="image/svg+xml" />
23
23
  <style>{`
24
- * {
24
+ /* Global Reset & Dark Mode Base */
25
+ *,
26
+ *::before,
27
+ *::after {
25
28
  box-sizing: border-box;
26
29
  margin: 0;
27
30
  padding: 0;
31
+ font: inherit;
32
+ }
33
+
34
+ html {
35
+ font-size: 16px;
36
+ -webkit-font-smoothing: antialiased;
37
+ -moz-osx-font-smoothing: grayscale;
28
38
  }
29
39
 
30
40
  body {
31
- font-family: system-ui, -apple-system, sans-serif;
41
+ background: #0a0a0a;
42
+ color: #ededed;
43
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
32
44
  line-height: 1.6;
33
- color: #1a1a2e;
34
- background: #f8f9fa;
45
+ min-height: 100svh;
46
+ }
47
+
48
+ h1, h2, h3, h4, h5, h6 {
49
+ text-wrap: balance;
50
+ }
51
+
52
+ p, li, figcaption {
53
+ text-wrap: pretty;
54
+ }
55
+
56
+ img, picture, svg, video, canvas {
57
+ max-width: 100%;
35
58
  }
36
59
 
60
+ a {
61
+ color: #00d9ff;
62
+ text-decoration: none;
63
+ transition: opacity 0.2s;
64
+ }
65
+
66
+ a:hover {
67
+ opacity: 0.8;
68
+ }
69
+
70
+ code {
71
+ font-family: "SF Mono", "Fira Code", "Fira Mono", Menlo, Monaco, "Courier New", monospace;
72
+ background: #1a1a1a;
73
+ padding: 0.2em 0.4em;
74
+ border-radius: 4px;
75
+ font-size: 0.9em;
76
+ }
77
+
78
+ ::selection {
79
+ background: #00d9ff;
80
+ color: #000;
81
+ }
82
+
83
+ ::-webkit-scrollbar {
84
+ width: 8px;
85
+ height: 8px;
86
+ }
87
+
88
+ ::-webkit-scrollbar-track {
89
+ background: #111;
90
+ }
91
+
92
+ ::-webkit-scrollbar-thumb {
93
+ background: #333;
94
+ border-radius: 4px;
95
+ }
96
+
97
+ ::-webkit-scrollbar-thumb:hover {
98
+ background: #444;
99
+ }
100
+
101
+ /* Layout Structure */
37
102
  .layout {
38
103
  min-height: 100vh;
39
104
  display: flex;
@@ -41,8 +106,9 @@ export default function RootLayout({ children }: RootLayoutProps) {
41
106
  }
42
107
 
43
108
  .nav {
44
- background: #1a1a2e;
109
+ background: #111;
45
110
  padding: 1rem 2rem;
111
+ border-bottom: 1px solid #222;
46
112
  }
47
113
 
48
114
  .nav-list {
@@ -51,17 +117,21 @@ export default function RootLayout({ children }: RootLayoutProps) {
51
117
  list-style: none;
52
118
  max-width: 1200px;
53
119
  margin: 0 auto;
120
+ align-items: center;
54
121
  }
55
122
 
56
123
  .nav-link {
57
- color: #e8e8e8;
124
+ color: #ededed;
58
125
  text-decoration: none;
59
126
  font-weight: 500;
60
127
  transition: color 0.2s;
128
+ padding: 0.5rem 0.75rem;
129
+ border-radius: 4px;
61
130
  }
62
131
 
63
132
  .nav-link:hover {
64
- color: #6366f1;
133
+ color: #00d9ff;
134
+ background: #1a1a1a;
65
135
  }
66
136
 
67
137
  .main {
@@ -73,14 +143,15 @@ export default function RootLayout({ children }: RootLayoutProps) {
73
143
  }
74
144
 
75
145
  .footer {
76
- background: #1a1a2e;
77
- color: #a8a8b8;
146
+ background: #111;
147
+ color: #888;
78
148
  text-align: center;
79
149
  padding: 1rem;
80
150
  font-size: 0.875rem;
151
+ border-top: 1px solid #222;
81
152
  }
82
153
 
83
- /* Page styles */
154
+ /* Home Page Hero */
84
155
  .home-page .hero {
85
156
  text-align: center;
86
157
  padding: 3rem 0;
@@ -88,50 +159,64 @@ export default function RootLayout({ children }: RootLayoutProps) {
88
159
 
89
160
  .home-page h1 {
90
161
  font-size: 2.5rem;
91
- margin-bottom: 0.5rem;
162
+ margin-bottom: 0.75rem;
163
+ font-weight: 700;
92
164
  }
93
165
 
94
166
  .home-page .tagline {
95
- color: #666;
167
+ color: #888;
96
168
  font-size: 1.25rem;
97
169
  }
98
170
 
171
+ /* Stats Cards */
99
172
  .stats {
100
173
  display: flex;
101
174
  gap: 1rem;
102
175
  justify-content: center;
103
176
  margin: 2rem 0;
177
+ flex-wrap: wrap;
104
178
  }
105
179
 
106
180
  .stat-card {
107
- background: white;
181
+ background: #111;
108
182
  padding: 1.5rem 2rem;
109
183
  border-radius: 8px;
110
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
184
+ border: 1px solid #222;
111
185
  text-align: center;
186
+ min-width: 150px;
187
+ transition: border-color 0.2s;
188
+ }
189
+
190
+ .stat-card:hover {
191
+ border-color: #00d9ff;
112
192
  }
113
193
 
114
194
  .stat-value {
115
195
  display: block;
116
196
  font-size: 2rem;
117
197
  font-weight: 700;
118
- color: #6366f1;
198
+ color: #00d9ff;
119
199
  }
120
200
 
121
201
  .stat-label {
122
- color: #666;
202
+ color: #888;
123
203
  font-size: 0.875rem;
204
+ margin-top: 0.5rem;
124
205
  }
125
206
 
207
+ /* Features Section */
126
208
  .features {
127
- background: white;
209
+ background: #111;
128
210
  padding: 2rem;
129
211
  border-radius: 8px;
130
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
212
+ border: 1px solid #222;
213
+ margin-top: 2rem;
131
214
  }
132
215
 
133
216
  .features h2 {
134
- margin-bottom: 1rem;
217
+ margin-bottom: 1.5rem;
218
+ font-size: 1.5rem;
219
+ font-weight: 600;
135
220
  }
136
221
 
137
222
  .features ul {
@@ -139,8 +224,9 @@ export default function RootLayout({ children }: RootLayoutProps) {
139
224
  }
140
225
 
141
226
  .features li {
142
- padding: 0.5rem 0;
143
- border-bottom: 1px solid #eee;
227
+ padding: 0.75rem 0;
228
+ border-bottom: 1px solid #222;
229
+ color: #ededed;
144
230
  }
145
231
 
146
232
  .features li:last-child {
@@ -150,27 +236,23 @@ export default function RootLayout({ children }: RootLayoutProps) {
150
236
  .cta {
151
237
  text-align: center;
152
238
  margin-top: 2rem;
153
- color: #666;
239
+ color: #888;
154
240
  }
155
241
 
156
- code {
157
- background: #f0f0f0;
158
- padding: 0.2rem 0.4rem;
159
- border-radius: 4px;
160
- font-family: monospace;
161
- }
162
-
163
- /* Users page */
242
+ /* Users Page */
164
243
  .users-page h1 {
165
- margin-bottom: 1rem;
244
+ margin-bottom: 1.5rem;
245
+ font-size: 2rem;
246
+ font-weight: 700;
166
247
  }
167
248
 
168
249
  .empty-state {
169
- color: #666;
250
+ color: #888;
170
251
  padding: 2rem;
171
252
  text-align: center;
172
- background: white;
253
+ background: #111;
173
254
  border-radius: 8px;
255
+ border: 1px solid #222;
174
256
  }
175
257
 
176
258
  .user-list {
@@ -180,21 +262,48 @@ export default function RootLayout({ children }: RootLayoutProps) {
180
262
  }
181
263
 
182
264
  .user-card {
183
- background: white;
265
+ background: #111;
184
266
  padding: 1rem;
185
267
  border-radius: 8px;
186
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
268
+ border: 1px solid #222;
187
269
  display: flex;
188
270
  justify-content: space-between;
189
271
  align-items: center;
272
+ transition: border-color 0.2s;
273
+ }
274
+
275
+ .user-card:hover {
276
+ border-color: #00d9ff;
190
277
  }
191
278
 
192
279
  .user-name {
193
280
  font-weight: 600;
281
+ color: #ededed;
194
282
  }
195
283
 
196
284
  .user-email {
197
- color: #666;
285
+ color: #888;
286
+ font-size: 0.875rem;
287
+ }
288
+
289
+ /* About Page */
290
+ .about-page h1 {
291
+ font-size: 2rem;
292
+ margin-bottom: 1.5rem;
293
+ font-weight: 700;
294
+ }
295
+
296
+ .about-page h2 {
297
+ font-size: 1.5rem;
298
+ margin-top: 2rem;
299
+ margin-bottom: 1rem;
300
+ font-weight: 600;
301
+ }
302
+
303
+ .about-page p {
304
+ color: #888;
305
+ margin-bottom: 1rem;
306
+ line-height: 1.8;
198
307
  }
199
308
  `}</style>
200
309
  </head>
@@ -213,8 +322,8 @@ export default function RootLayout({ children }: RootLayoutProps) {
213
322
  </a>
214
323
  </li>
215
324
  <li>
216
- <a href="/settings" className="nav-link">
217
- Settings
325
+ <a href="/about" className="nav-link">
326
+ About
218
327
  </a>
219
328
  </li>
220
329
  <li>
@@ -222,11 +331,6 @@ export default function RootLayout({ children }: RootLayoutProps) {
222
331
  Docs
223
332
  </a>
224
333
  </li>
225
- <li>
226
- <a href="/api/health" className="nav-link">
227
- API
228
- </a>
229
- </li>
230
334
  </ul>
231
335
  </nav>
232
336
 
@@ -234,7 +338,7 @@ export default function RootLayout({ children }: RootLayoutProps) {
234
338
 
235
339
  <footer className="footer">Built with VeloxTS &bull; React Server Components</footer>
236
340
  </div>
237
- <script src="/_build/entry.client.js" type="module" />
341
+ <script src="/_build/src/entry.client.tsx" type="module" />
238
342
  </body>
239
343
  </html>
240
344
  );
@@ -0,0 +1,21 @@
1
+ services:
2
+ postgres:
3
+ image: postgres:16-alpine
4
+ container_name: __PROJECT_NAME__-postgres
5
+ restart: unless-stopped
6
+ environment:
7
+ POSTGRES_USER: ${DATABASE_USER:-user}
8
+ POSTGRES_PASSWORD: ${DATABASE_PASSWORD:-password}
9
+ POSTGRES_DB: ${DATABASE_NAME:-__PROJECT_NAME__}
10
+ ports:
11
+ - "${DATABASE_PORT:-5432}:5432"
12
+ volumes:
13
+ - postgres_data:/var/lib/postgresql/data
14
+ healthcheck:
15
+ test: ["CMD-SHELL", "pg_isready -U ${DATABASE_USER:-user} -d ${DATABASE_NAME:-__PROJECT_NAME__}"]
16
+ interval: 10s
17
+ timeout: 5s
18
+ retries: 5
19
+
20
+ volumes:
21
+ postgres_data:
@@ -11,7 +11,8 @@
11
11
  "db:push": "prisma db push",
12
12
  "db:migrate": "prisma migrate dev",
13
13
  "db:studio": "prisma studio",
14
- "type-check": "tsc --noEmit"
14
+ "type-check": "tsc --noEmit",
15
+ "lint:client": "./scripts/check-client-imports.sh"
15
16
  },
16
17
  "dependencies": {
17
18
  "@prisma/adapter-better-sqlite3": "7.2.0",
@@ -35,7 +36,6 @@
35
36
  "@types/react": "19.2.7",
36
37
  "@types/react-dom": "19.2.3",
37
38
  "prisma": "7.2.0",
38
- "typescript": "5.9.3",
39
- "vite": "7.3.0"
39
+ "typescript": "5.9.3"
40
40
  }
41
41
  }
@@ -23,7 +23,6 @@ import type { PrismaPg as PrismaPgType } from '@prisma/adapter-pg';
23
23
  /* @endif postgresql */
24
24
  import type { PrismaClient as PrismaClientType } from '@prisma/client';
25
25
  import dotenv from 'dotenv';
26
- import type { Pool as PoolType } from 'pg';
27
26
 
28
27
  // Runtime imports using createRequire for Node.js v24+ CJS interop
29
28
  const require = createRequire(import.meta.url);
@@ -36,9 +35,6 @@ const { PrismaBetterSqlite3 } = require('@prisma/adapter-better-sqlite3') as {
36
35
  const { PrismaPg } = require('@prisma/adapter-pg') as {
37
36
  PrismaPg: typeof PrismaPgType;
38
37
  };
39
- const { Pool } = require('pg') as {
40
- Pool: typeof PoolType;
41
- };
42
38
  /* @endif postgresql */
43
39
  const { PrismaClient } = require('@prisma/client') as {
44
40
  PrismaClient: typeof PrismaClientType;
@@ -56,10 +52,6 @@ declare global {
56
52
  // Allow global `var` declarations for hot reload in development
57
53
  // eslint-disable-next-line no-var
58
54
  var __db: PrismaClient | undefined;
59
- /* @if postgresql */
60
- // eslint-disable-next-line no-var
61
- var __pool: InstanceType<typeof PoolType> | undefined;
62
- /* @endif postgresql */
63
55
  }
64
56
 
65
57
  /* @if sqlite */
@@ -88,32 +80,24 @@ function createPrismaClient(): PrismaClient {
88
80
  /* @endif sqlite */
89
81
  /* @if postgresql */
90
82
  /**
91
- * Create a PostgreSQL connection pool.
92
- * Uses connection pooling for better performance in production.
83
+ * Create a Prisma client instance using the PostgreSQL adapter.
84
+ *
85
+ * Prisma 7 Breaking Change:
86
+ * - PrismaPg now takes connectionString directly (not a Pool instance)
87
+ * - Pool management is handled internally by the adapter
93
88
  */
94
- function createPool(): InstanceType<typeof PoolType> {
95
- const databaseUrl = process.env.DATABASE_URL;
89
+ function createPrismaClient(): PrismaClient {
90
+ const connectionString = process.env.DATABASE_URL;
96
91
 
97
- if (!databaseUrl) {
92
+ if (!connectionString) {
98
93
  throw new Error(
99
94
  '[VeloxTS] DATABASE_URL environment variable is not set. ' +
100
95
  'Ensure .env file exists in project root with DATABASE_URL defined.'
101
96
  );
102
97
  }
103
98
 
104
- return new Pool({
105
- connectionString: databaseUrl,
106
- max: 10, // Maximum connections in pool
107
- });
108
- }
109
-
110
- /**
111
- * Create a Prisma client instance using the PostgreSQL adapter.
112
- * Uses connection pooling for efficient database access.
113
- */
114
- function createPrismaClient(pool: InstanceType<typeof PoolType>): PrismaClient {
115
- // Prisma 7 requires driver adapters for direct connections
116
- const adapter = new PrismaPg(pool);
99
+ // Prisma 7: Pass connectionString directly to PrismaPg (not a Pool)
100
+ const adapter = new PrismaPg({ connectionString });
117
101
  return new PrismaClient({ adapter });
118
102
  }
119
103
  /* @endif postgresql */
@@ -127,19 +111,16 @@ if (process.env.NODE_ENV !== 'production') {
127
111
  }
128
112
  /* @endif sqlite */
129
113
  /* @if postgresql */
130
- // Use global singletons for hot reload in development
131
- const pool = globalThis.__pool ?? createPool();
132
- export const db = globalThis.__db ?? createPrismaClient(pool);
114
+ // Use global singleton for hot reload in development
115
+ export const db = globalThis.__db ?? createPrismaClient();
133
116
 
134
117
  if (process.env.NODE_ENV !== 'production') {
135
- globalThis.__pool = pool;
136
118
  globalThis.__db = db;
137
119
  }
138
120
 
139
- // Graceful shutdown - close pool on process exit
121
+ // Graceful shutdown - disconnect Prisma on process exit
140
122
  const shutdown = async () => {
141
123
  await db.$disconnect();
142
- await pool.end();
143
124
  process.exit(0);
144
125
  };
145
126
 
@@ -13,7 +13,7 @@
13
13
  import { veloxApp } from '@veloxts/core';
14
14
  import { databasePlugin } from '@veloxts/orm';
15
15
  import { rest } from '@veloxts/router';
16
- import { createH3ApiHandler } from '@veloxts/web';
16
+ import { createH3ApiHandler } from '@veloxts/web/adapters';
17
17
 
18
18
  import { db } from './database.js';
19
19
  import { healthProcedures } from './procedures/health.js';
@@ -1,28 +1,75 @@
1
1
  /**
2
2
  * Client Entry Point
3
3
  *
4
- * Hydrates the React application on the client side.
5
- * For SSR apps, the server streams the component tree as HTML.
6
- * We hydrate the existing DOM to attach event handlers.
4
+ * Handles client-side hydration for pages marked with 'use client'.
5
+ * Server Components remain as static HTML without hydration.
6
+ *
7
+ * IMPORTANT: The hydration tree must match exactly what the server rendered.
8
+ * Server renders: <div id="root"><MinimalContent><Page /></MinimalContent></div>
9
+ * Client hydrates: <MinimalContent><Page /></MinimalContent>
10
+ *
11
+ * This template has no client components by default.
12
+ * To add interactive pages:
13
+ * 1. Create a page with 'use client' directive
14
+ * 2. Import it here
15
+ * 3. Add it to clientRoutes with its layout
16
+ *
17
+ * @example
18
+ * import MyPage from '../app/pages/my-page.tsx';
19
+ * import MinimalContent from '../app/layouts/minimal-content.tsx';
20
+ *
21
+ * const clientRoutes: Record<string, ClientRoute> = {
22
+ * '/my-page': { Page: MyPage, Layout: MinimalContent },
23
+ * };
7
24
  */
8
25
 
9
- import { hydrateRoot } from '@veloxts/web';
26
+ import { StrictMode } from 'react';
27
+ import { hydrateRoot } from 'react-dom/client';
28
+
29
+ // Import content layouts (shared between server and client)
30
+ import MinimalContent from '../app/layouts/minimal-content.tsx';
31
+
32
+ // Route mapping for client pages with their layouts
33
+ // The layout must match what the server rendered inside <div id="root">
34
+ interface ClientRoute {
35
+ Page: React.ComponentType;
36
+ Layout: React.ComponentType<{ children: React.ReactNode }>;
37
+ }
38
+
39
+ const clientRoutes: Record<string, ClientRoute> = {
40
+ // No client pages by default in the RSC template
41
+ // Example: '/my-page': { Page: MyPage, Layout: MinimalContent },
42
+ };
43
+
44
+ // Suppress unused variable warning - MinimalContent is imported for documentation
45
+ void MinimalContent;
10
46
 
11
47
  const rootElement = document.getElementById('root');
48
+ const pathname = window.location.pathname;
12
49
 
13
- if (rootElement?.firstElementChild) {
14
- // Hydrate the server-rendered React tree
15
- // This attaches event handlers and makes the app interactive
16
- hydrateRoot(rootElement, rootElement.firstElementChild as unknown as React.ReactNode, {
17
- onRecoverableError: (error: unknown) => {
18
- // Log hydration mismatches in development
19
- if (process.env.NODE_ENV !== 'production') {
20
- console.warn('[VeloxTS] Hydration warning:', error);
21
- }
22
- },
23
- });
24
- } else {
25
- console.error(
26
- '[VeloxTS] Root element or content not found. Ensure #root exists with server-rendered content.'
50
+ // Only hydrate if this is a client page
51
+ const match = clientRoutes[pathname];
52
+
53
+ if (rootElement && match) {
54
+ const { Page, Layout } = match;
55
+
56
+ // Hydrate with the exact same tree structure as server rendered
57
+ hydrateRoot(
58
+ rootElement,
59
+ <StrictMode>
60
+ <Layout>
61
+ <Page />
62
+ </Layout>
63
+ </StrictMode>,
64
+ {
65
+ onRecoverableError: (error: unknown) => {
66
+ if (process.env.NODE_ENV !== 'production') {
67
+ console.warn('[VeloxTS] Hydration warning:', error);
68
+ }
69
+ },
70
+ }
27
71
  );
72
+ } else {
73
+ // Server-only page, no hydration needed
74
+ console.debug('[VeloxTS] Server-rendered page, no client hydration needed');
28
75
  }