nodejs-quickstart-structure 2.0.1 → 2.1.1

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 (165) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +64 -66
  3. package/bin/index.js +5 -2
  4. package/lib/generator.js +10 -4
  5. package/lib/modules/app-setup.js +76 -6
  6. package/lib/modules/auth-setup.js +143 -0
  7. package/lib/modules/caching-setup.js +8 -1
  8. package/lib/modules/config-files.js +6 -0
  9. package/lib/modules/database-setup.js +2 -1
  10. package/lib/modules/project-setup.js +1 -0
  11. package/lib/prompts.js +39 -0
  12. package/package.json +5 -4
  13. package/templates/clean-architecture/js/src/domain/models/User.js +3 -1
  14. package/templates/clean-architecture/js/src/index.js.ejs +2 -0
  15. package/templates/clean-architecture/js/src/infrastructure/config/env.js.ejs +12 -3
  16. package/templates/clean-architecture/js/src/infrastructure/repositories/UserRepository.js.ejs +25 -2
  17. package/templates/clean-architecture/js/src/infrastructure/repositories/UserRepository.spec.js.ejs +38 -1
  18. package/templates/clean-architecture/js/src/infrastructure/webserver/server.js.ejs +3 -0
  19. package/templates/clean-architecture/js/src/infrastructure/webserver/server.spec.js.ejs +51 -0
  20. package/templates/clean-architecture/js/src/infrastructure/webserver/swagger.spec.js.ejs +14 -0
  21. package/templates/clean-architecture/js/src/interfaces/controllers/userController.js.ejs +41 -4
  22. package/templates/clean-architecture/js/src/interfaces/controllers/userController.spec.js.ejs +70 -5
  23. package/templates/clean-architecture/js/src/interfaces/graphql/context.js.ejs +13 -6
  24. package/templates/clean-architecture/js/src/interfaces/graphql/context.spec.js.ejs +55 -22
  25. package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.js.ejs +10 -5
  26. package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.spec.js.ejs +32 -10
  27. package/templates/clean-architecture/js/src/interfaces/graphql/typeDefs/user.types.js.ejs +1 -1
  28. package/templates/clean-architecture/js/src/interfaces/routes/api.js.ejs +15 -0
  29. package/templates/clean-architecture/js/src/interfaces/routes/api.spec.js.ejs +4 -0
  30. package/templates/clean-architecture/js/src/usecases/CreateUser.js.ejs +34 -0
  31. package/templates/clean-architecture/js/src/usecases/CreateUser.spec.js.ejs +12 -3
  32. package/templates/clean-architecture/js/src/usecases/DeleteUser.js.ejs +27 -0
  33. package/templates/clean-architecture/js/src/usecases/DeleteUser.spec.js.ejs +9 -1
  34. package/templates/clean-architecture/js/src/usecases/GetAllUsers.js.ejs +36 -0
  35. package/templates/clean-architecture/js/src/usecases/GetAllUsers.spec.js.ejs +23 -1
  36. package/templates/clean-architecture/js/src/usecases/GetUserById.js.ejs +36 -0
  37. package/templates/clean-architecture/js/src/usecases/GetUserById.spec.js.ejs +48 -0
  38. package/templates/clean-architecture/js/src/usecases/UpdateUser.js.ejs +28 -0
  39. package/templates/clean-architecture/js/src/usecases/UpdateUser.spec.js.ejs +9 -1
  40. package/templates/clean-architecture/js/src/utils/errorMessages.js +1 -0
  41. package/templates/clean-architecture/js/src/utils/httpCodes.js +2 -0
  42. package/templates/clean-architecture/ts/src/config/env.ts.ejs +12 -3
  43. package/templates/clean-architecture/ts/src/domain/user.ts +3 -1
  44. package/templates/clean-architecture/ts/src/index.ts.ejs +4 -0
  45. package/templates/clean-architecture/ts/src/infrastructure/repositories/UserRepository.spec.ts.ejs +71 -10
  46. package/templates/clean-architecture/ts/src/infrastructure/repositories/userRepository.ts.ejs +32 -3
  47. package/templates/clean-architecture/ts/src/interfaces/controllers/userController.spec.ts.ejs +43 -9
  48. package/templates/clean-architecture/ts/src/interfaces/controllers/userController.ts.ejs +57 -15
  49. package/templates/clean-architecture/ts/src/interfaces/graphql/context.spec.ts.ejs +57 -24
  50. package/templates/clean-architecture/ts/src/interfaces/graphql/context.ts.ejs +14 -8
  51. package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/user.resolvers.spec.ts.ejs +33 -10
  52. package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/user.resolvers.ts.ejs +15 -5
  53. package/templates/clean-architecture/ts/src/interfaces/graphql/typeDefs/user.types.ts.ejs +1 -1
  54. package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.spec.ts.ejs +9 -1
  55. package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.ts.ejs +16 -0
  56. package/templates/clean-architecture/ts/src/usecases/createUser.spec.ts.ejs +12 -3
  57. package/templates/clean-architecture/ts/src/usecases/createUser.ts.ejs +35 -0
  58. package/templates/clean-architecture/ts/src/usecases/deleteUser.spec.ts.ejs +10 -1
  59. package/templates/clean-architecture/ts/src/usecases/deleteUser.ts.ejs +24 -0
  60. package/templates/clean-architecture/ts/src/usecases/getAllUsers.spec.ts.ejs +9 -1
  61. package/templates/clean-architecture/ts/src/usecases/getAllUsers.ts.ejs +21 -0
  62. package/templates/clean-architecture/ts/src/usecases/getUserById.spec.ts.ejs +55 -0
  63. package/templates/clean-architecture/ts/src/usecases/getUserById.ts.ejs +23 -0
  64. package/templates/clean-architecture/ts/src/usecases/updateUser.spec.ts.ejs +10 -1
  65. package/templates/clean-architecture/ts/src/usecases/updateUser.ts.ejs +25 -0
  66. package/templates/clean-architecture/ts/src/utils/errorMessages.ts +1 -0
  67. package/templates/clean-architecture/ts/src/utils/httpCodes.ts +1 -0
  68. package/templates/common/.cursorrules.ejs +9 -0
  69. package/templates/common/.env.example.ejs +17 -10
  70. package/templates/common/README.md.ejs +63 -18
  71. package/templates/common/auth/js/controllers/authController.js.ejs +170 -0
  72. package/templates/common/auth/js/controllers/authController.spec.js.ejs +148 -0
  73. package/templates/common/auth/js/middleware/authMiddleware.js.ejs +58 -0
  74. package/templates/common/auth/js/middleware/authMiddleware.spec.js.ejs +108 -0
  75. package/templates/common/auth/js/routes/authRoutes.js.ejs +16 -0
  76. package/templates/common/auth/js/services/jwtService.js.ejs +54 -0
  77. package/templates/common/auth/js/services/jwtService.spec.js.ejs +84 -0
  78. package/templates/common/auth/ts/controllers/authController.spec.ts.ejs +161 -0
  79. package/templates/common/auth/ts/controllers/authController.ts.ejs +167 -0
  80. package/templates/common/auth/ts/middleware/authMiddleware.spec.ts.ejs +128 -0
  81. package/templates/common/auth/ts/middleware/authMiddleware.ts.ejs +59 -0
  82. package/templates/common/auth/ts/routes/authRoutes.ts.ejs +20 -0
  83. package/templates/common/auth/ts/services/jwtService.spec.ts.ejs +89 -0
  84. package/templates/common/auth/ts/services/jwtService.ts.ejs +60 -0
  85. package/templates/common/babel.config.js.ejs +5 -0
  86. package/templates/common/caching/clean/js/CreateUser.js.ejs +14 -5
  87. package/templates/common/caching/clean/js/DeleteUser.js.ejs +2 -1
  88. package/templates/common/caching/clean/js/GetUserById.js.ejs +39 -0
  89. package/templates/common/caching/clean/js/UpdateUser.js.ejs +2 -1
  90. package/templates/common/caching/clean/ts/createUser.ts.ejs +14 -6
  91. package/templates/common/caching/clean/ts/deleteUser.ts.ejs +2 -1
  92. package/templates/common/caching/clean/ts/getUserById.ts.ejs +32 -0
  93. package/templates/common/caching/clean/ts/updateUser.ts.ejs +2 -1
  94. package/templates/common/caching/js/memoryCache.spec.js.ejs +2 -0
  95. package/templates/common/caching/js/redisClient.spec.js.ejs +2 -0
  96. package/templates/common/caching/ts/memoryCache.spec.ts.ejs +2 -0
  97. package/templates/common/caching/ts/redisClient.spec.ts.ejs +2 -0
  98. package/templates/common/database/js/models/User.js.ejs +14 -1
  99. package/templates/common/database/js/models/User.js.mongoose.ejs +7 -0
  100. package/templates/common/database/js/models/User.spec.js.ejs +12 -0
  101. package/templates/common/database/js/mongoose.spec.js.ejs +2 -0
  102. package/templates/common/database/ts/models/User.spec.ts.ejs +10 -0
  103. package/templates/common/database/ts/models/User.ts.ejs +17 -0
  104. package/templates/common/database/ts/models/User.ts.mongoose.ejs +8 -0
  105. package/templates/common/database/ts/mongoose.spec.ts.ejs +2 -0
  106. package/templates/common/docker-compose.yml.ejs +12 -0
  107. package/templates/common/ecosystem.config.js.ejs +9 -3
  108. package/templates/common/eslint.config.mjs.ejs +3 -0
  109. package/templates/common/jest.config.js.ejs +13 -9
  110. package/templates/common/kafka/js/messaging/baseConsumer.js.ejs +1 -1
  111. package/templates/common/kafka/js/services/kafkaService.js.ejs +1 -1
  112. package/templates/common/migrations/init.js.ejs +5 -4
  113. package/templates/common/package.json.ejs +11 -2
  114. package/templates/common/prompts/project-context.md.ejs +8 -1
  115. package/templates/common/src/tests/e2e/e2e.users.test.js.ejs +149 -107
  116. package/templates/common/src/tests/e2e/e2e.users.test.ts.ejs +88 -47
  117. package/templates/common/swagger.yml.ejs +148 -0
  118. package/templates/common/tsconfig.eslint.json +15 -0
  119. package/templates/common/tsconfig.json +3 -1
  120. package/templates/common/views/ejs/index.ejs +264 -30
  121. package/templates/common/views/ejs/login.ejs.ejs +244 -0
  122. package/templates/common/views/ejs/signup.ejs.ejs +282 -0
  123. package/templates/common/views/pug/index.pug +269 -38
  124. package/templates/common/views/pug/login.pug.ejs +195 -0
  125. package/templates/common/views/pug/signup.pug.ejs +241 -0
  126. package/templates/db/mysql/V1__Initial_Setup.sql.ejs +6 -0
  127. package/templates/db/postgres/V1__Initial_Setup.sql.ejs +6 -0
  128. package/templates/mvc/js/src/config/env.js.ejs +12 -3
  129. package/templates/mvc/js/src/controllers/userController.js.ejs +29 -5
  130. package/templates/mvc/js/src/controllers/userController.spec.js.ejs +27 -12
  131. package/templates/mvc/js/src/graphql/context.js.ejs +14 -3
  132. package/templates/mvc/js/src/graphql/context.spec.js.ejs +36 -21
  133. package/templates/mvc/js/src/graphql/resolvers/user.resolvers.js.ejs +10 -5
  134. package/templates/mvc/js/src/graphql/resolvers/user.resolvers.spec.js.ejs +32 -10
  135. package/templates/mvc/js/src/graphql/typeDefs/user.types.js.ejs +1 -1
  136. package/templates/mvc/js/src/index.js.ejs +16 -3
  137. package/templates/mvc/js/src/routes/api.js.ejs +14 -0
  138. package/templates/mvc/js/src/routes/api.spec.js.ejs +3 -0
  139. package/templates/mvc/js/src/utils/errorMessages.js +1 -0
  140. package/templates/mvc/js/src/utils/httpCodes.js +1 -0
  141. package/templates/mvc/ts/src/config/env.ts.ejs +12 -3
  142. package/templates/mvc/ts/src/controllers/userController.spec.ts.ejs +95 -7
  143. package/templates/mvc/ts/src/controllers/userController.ts.ejs +68 -11
  144. package/templates/mvc/ts/src/graphql/context.spec.ts.ejs +36 -23
  145. package/templates/mvc/ts/src/graphql/context.ts.ejs +15 -6
  146. package/templates/mvc/ts/src/graphql/resolvers/user.resolvers.spec.ts.ejs +32 -10
  147. package/templates/mvc/ts/src/graphql/resolvers/user.resolvers.ts.ejs +15 -5
  148. package/templates/mvc/ts/src/graphql/typeDefs/user.types.ts.ejs +1 -1
  149. package/templates/mvc/ts/src/index.ts.ejs +15 -3
  150. package/templates/mvc/ts/src/routes/api.spec.ts.ejs +6 -0
  151. package/templates/mvc/ts/src/routes/api.ts.ejs +15 -0
  152. package/templates/mvc/ts/src/utils/errorMessages.ts +1 -0
  153. package/templates/mvc/ts/src/utils/httpCodes.ts +1 -0
  154. package/templates/clean-architecture/js/src/interfaces/routes/api.js +0 -12
  155. package/templates/clean-architecture/js/src/usecases/CreateUser.js +0 -14
  156. package/templates/clean-architecture/js/src/usecases/DeleteUser.js +0 -11
  157. package/templates/clean-architecture/js/src/usecases/GetAllUsers.js +0 -12
  158. package/templates/clean-architecture/js/src/usecases/UpdateUser.js +0 -11
  159. package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.ts +0 -13
  160. package/templates/clean-architecture/ts/src/usecases/createUser.ts +0 -13
  161. package/templates/clean-architecture/ts/src/usecases/deleteUser.ts +0 -9
  162. package/templates/clean-architecture/ts/src/usecases/getAllUsers.ts +0 -10
  163. package/templates/clean-architecture/ts/src/usecases/updateUser.ts +0 -9
  164. package/templates/mvc/js/src/routes/api.js +0 -10
  165. package/templates/mvc/ts/src/routes/api.ts +0 -12
@@ -0,0 +1,244 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Login - <%= projectName %></title>
7
+ <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600&display=swap" rel="stylesheet">
8
+ <style>
9
+ :root {
10
+ --primary: #6366f1;
11
+ --primary-glow: rgba(99, 102, 241, 0.5);
12
+ --bg-dark: #0f172a;
13
+ --card-bg: rgba(255, 255, 255, 0.03);
14
+ --card-border: rgba(255, 255, 255, 0.08);
15
+ --text-main: #f8fafc;
16
+ --text-muted: #94a3b8;
17
+ }
18
+
19
+ * {
20
+ margin: 0;
21
+ padding: 0;
22
+ box-sizing: border-box;
23
+ font-family: 'Poppins', sans-serif;
24
+ }
25
+
26
+ body {
27
+ background-color: var(--bg-dark);
28
+ color: var(--text-main);
29
+ min-height: 100vh;
30
+ display: flex;
31
+ align-items: center;
32
+ justify-content: center;
33
+ overflow: hidden;
34
+ position: relative;
35
+ }
36
+
37
+ /* Animated Background Blobs */
38
+ .background-blobs {
39
+ position: absolute;
40
+ width: 100%;
41
+ height: 100%;
42
+ z-index: -1;
43
+ filter: blur(80px);
44
+ }
45
+
46
+ .blob {
47
+ position: absolute;
48
+ width: 400px;
49
+ height: 400px;
50
+ border-radius: 50%;
51
+ opacity: 0.4;
52
+ animation: float 20s infinite alternate;
53
+ }
54
+
55
+ .blob-1 {
56
+ background: radial-gradient(circle, #6366f1 0%, transparent 70%);
57
+ top: -100px;
58
+ left: -100px;
59
+ }
60
+
61
+ .blob-2 {
62
+ background: radial-gradient(circle, #ec4899 0%, transparent 70%);
63
+ bottom: -150px;
64
+ right: -100px;
65
+ animation-delay: -5s;
66
+ }
67
+
68
+ @keyframes float {
69
+ 0% { transform: translate(0, 0) scale(1); }
70
+ 100% { transform: translate(100px, 50px) scale(1.2); }
71
+ }
72
+
73
+ .auth-card {
74
+ background: var(--card-bg);
75
+ backdrop-filter: blur(12px);
76
+ -webkit-backdrop-filter: blur(12px);
77
+ border: 1px solid var(--card-border);
78
+ border-radius: 24px;
79
+ padding: 48px;
80
+ width: 100%;
81
+ max-width: 440px;
82
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
83
+ z-index: 1;
84
+ animation: slideUp 0.6s cubic-bezier(0.16, 1, 0.3, 1);
85
+ }
86
+
87
+ @keyframes slideUp {
88
+ from { opacity: 0; transform: translateY(20px); }
89
+ to { opacity: 1; transform: translateY(0); }
90
+ }
91
+
92
+ .auth-card h2 {
93
+ font-size: 32px;
94
+ font-weight: 600;
95
+ margin-bottom: 8px;
96
+ text-align: center;
97
+ background: linear-gradient(to right, #fff, #94a3b8);
98
+ -webkit-background-clip: text;
99
+ -webkit-text-fill-color: transparent;
100
+ }
101
+
102
+ .subtitle {
103
+ text-align: center;
104
+ color: var(--text-muted);
105
+ font-size: 14px;
106
+ margin-bottom: 32px;
107
+ }
108
+
109
+ .form-group {
110
+ margin-bottom: 24px;
111
+ }
112
+
113
+ .form-group label {
114
+ display: block;
115
+ margin-bottom: 8px;
116
+ font-size: 14px;
117
+ font-weight: 500;
118
+ color: var(--text-muted);
119
+ transition: color 0.3s;
120
+ }
121
+
122
+ .input-wrapper {
123
+ position: relative;
124
+ }
125
+
126
+ .form-group input {
127
+ width: 100%;
128
+ background: rgba(255, 255, 255, 0.05);
129
+ border: 1px solid var(--card-border);
130
+ border-radius: 12px;
131
+ padding: 12px 16px;
132
+ color: #fff;
133
+ font-size: 15px;
134
+ transition: all 0.3s ease;
135
+ outline: none;
136
+ }
137
+
138
+ .form-group input:focus {
139
+ background: rgba(255, 255, 255, 0.08);
140
+ border-color: var(--primary);
141
+ box-shadow: 0 0 0 4px var(--primary-glow);
142
+ }
143
+
144
+ .form-group input:focus + label {
145
+ color: var(--primary);
146
+ }
147
+
148
+ .btn-primary {
149
+ width: 100%;
150
+ background: var(--primary);
151
+ color: white;
152
+ border: none;
153
+ border-radius: 12px;
154
+ padding: 14px;
155
+ font-size: 16px;
156
+ font-weight: 600;
157
+ cursor: pointer;
158
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
159
+ margin-top: 8px;
160
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
161
+ }
162
+
163
+ .btn-primary:hover {
164
+ transform: translateY(-2px);
165
+ background: #4f46e5;
166
+ box-shadow: 0 10px 15px -3px rgba(99, 102, 241, 0.4);
167
+ }
168
+
169
+ .btn-primary:active {
170
+ transform: translateY(0);
171
+ }
172
+
173
+ .footer {
174
+ margin-top: 32px;
175
+ text-align: center;
176
+ font-size: 14px;
177
+ color: var(--text-muted);
178
+ }
179
+
180
+ .footer a {
181
+ color: var(--primary);
182
+ text-decoration: none;
183
+ font-weight: 500;
184
+ transition: color 0.3s;
185
+ }
186
+
187
+ .footer a:hover {
188
+ color: #818cf8;
189
+ text-decoration: underline;
190
+ }
191
+
192
+ .back-link {
193
+ display: inline-block;
194
+ margin-top: 16px;
195
+ font-size: 13px;
196
+ opacity: 0.6;
197
+ transition: opacity 0.3s;
198
+ }
199
+
200
+ .back-link:hover {
201
+ opacity: 1;
202
+ }
203
+
204
+ /* Responsive adjustments */
205
+ @media (max-width: 480px) {
206
+ .auth-card {
207
+ padding: 32px 24px;
208
+ margin: 20px;
209
+ border-radius: 20px;
210
+ }
211
+ }
212
+ </style>
213
+ </head>
214
+ <body>
215
+ <div class="background-blobs">
216
+ <div class="blob blob-1"></div>
217
+ <div class="blob blob-2"></div>
218
+ </div>
219
+
220
+ <div class="auth-card">
221
+ <h2>Welcome Back</h2>
222
+ <p class="subtitle">Please enter your details to sign in</p>
223
+
224
+ <form action="/api/auth/login" method="POST">
225
+ <div class="form-group">
226
+ <label for="email">Email Address</label>
227
+ <input type="email" id="email" name="email" placeholder="name@example.com" required>
228
+ </div>
229
+
230
+ <div class="form-group">
231
+ <label for="password">Password</label>
232
+ <input type="password" id="password" name="password" placeholder="••••••••" required>
233
+ </div>
234
+
235
+ <button type="submit" class="btn-primary">Sign In</button>
236
+ </form>
237
+
238
+ <div class="footer">
239
+ <p>Don't have an account? <a href="/signup">Create account</a></p>
240
+ <a href="/" class="back-link">← Back to home</a>
241
+ </div>
242
+ </div>
243
+ </body>
244
+ </html>
@@ -0,0 +1,282 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Sign Up - <%= projectName %></title>
7
+ <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600&display=swap" rel="stylesheet">
8
+ <style>
9
+ :root {
10
+ --primary: #22c55e;
11
+ --primary-glow: rgba(34, 197, 94, 0.4);
12
+ --bg-dark: #0f172a;
13
+ --card-bg: rgba(255, 255, 255, 0.03);
14
+ --card-border: rgba(255, 255, 255, 0.08);
15
+ --text-main: #f8fafc;
16
+ --text-muted: #94a3b8;
17
+ }
18
+
19
+ * {
20
+ margin: 0;
21
+ padding: 0;
22
+ box-sizing: border-box;
23
+ font-family: 'Poppins', sans-serif;
24
+ }
25
+
26
+ body {
27
+ background-color: var(--bg-dark);
28
+ color: var(--text-main);
29
+ min-height: 100vh;
30
+ display: flex;
31
+ align-items: center;
32
+ justify-content: center;
33
+ overflow-x: hidden;
34
+ position: relative;
35
+ }
36
+
37
+ /* Animated Background Blobs */
38
+ .background-blobs {
39
+ position: absolute;
40
+ width: 100%;
41
+ height: 100%;
42
+ z-index: -1;
43
+ filter: blur(80px);
44
+ }
45
+
46
+ .blob {
47
+ position: absolute;
48
+ width: 500px;
49
+ height: 500px;
50
+ border-radius: 50%;
51
+ opacity: 0.3;
52
+ animation: float 25s infinite alternate;
53
+ }
54
+
55
+ .blob-1 {
56
+ background: radial-gradient(circle, #22c55e 0%, transparent 70%);
57
+ top: -200px;
58
+ right: -100px;
59
+ }
60
+
61
+ .blob-2 {
62
+ background: radial-gradient(circle, #3b82f6 0%, transparent 70%);
63
+ bottom: -200px;
64
+ left: -100px;
65
+ animation-delay: -7s;
66
+ }
67
+
68
+ @keyframes float {
69
+ 0% { transform: translate(0, 0) scale(1); }
70
+ 100% { transform: translate(-150px, 100px) scale(1.3); }
71
+ }
72
+
73
+ .auth-card {
74
+ background: var(--card-bg);
75
+ backdrop-filter: blur(15px);
76
+ -webkit-backdrop-filter: blur(15px);
77
+ border: 1px solid var(--card-border);
78
+ border-radius: 28px;
79
+ padding: 48px;
80
+ width: 100%;
81
+ max-width: 480px;
82
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.6);
83
+ z-index: 1;
84
+ margin: 40px 20px;
85
+ animation: fadeIn 0.8s ease-out;
86
+ }
87
+
88
+ @keyframes fadeIn {
89
+ from { opacity: 0; transform: translateY(15px); }
90
+ to { opacity: 1; transform: translateY(0); }
91
+ }
92
+
93
+ .auth-card h2 {
94
+ font-size: 32px;
95
+ font-weight: 600;
96
+ margin-bottom: 8px;
97
+ text-align: center;
98
+ background: linear-gradient(to right, #fff, #94a3b8);
99
+ -webkit-background-clip: text;
100
+ -webkit-text-fill-color: transparent;
101
+ }
102
+
103
+ .subtitle {
104
+ text-align: center;
105
+ color: var(--text-muted);
106
+ font-size: 14px;
107
+ margin-bottom: 40px;
108
+ }
109
+
110
+ .form-grid {
111
+ display: grid;
112
+ gap: 20px;
113
+ }
114
+
115
+ .form-group label {
116
+ display: block;
117
+ margin-bottom: 8px;
118
+ font-size: 13px;
119
+ font-weight: 500;
120
+ color: var(--text-muted);
121
+ }
122
+
123
+ .form-group input {
124
+ width: 100%;
125
+ background: rgba(255, 255, 255, 0.04);
126
+ border: 1px solid var(--card-border);
127
+ border-radius: 14px;
128
+ padding: 13px 18px;
129
+ color: #fff;
130
+ font-size: 15px;
131
+ transition: all 0.3s;
132
+ outline: none;
133
+ }
134
+
135
+ .form-group input:focus {
136
+ background: rgba(255, 255, 255, 0.07);
137
+ border-color: var(--primary);
138
+ box-shadow: 0 0 0 4px var(--primary-glow);
139
+ }
140
+
141
+ .btn-primary {
142
+ width: 100%;
143
+ background: var(--primary);
144
+ color: white;
145
+ border: none;
146
+ border-radius: 14px;
147
+ padding: 15px;
148
+ font-size: 16px;
149
+ font-weight: 600;
150
+ cursor: pointer;
151
+ transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
152
+ margin-top: 15px;
153
+ box-shadow: 0 10px 15px -3px rgba(34, 197, 94, 0.3);
154
+ }
155
+
156
+ .btn-primary:hover {
157
+ transform: scale(1.02);
158
+ filter: brightness(1.1);
159
+ box-shadow: 0 15px 25px -5px rgba(34, 197, 94, 0.4);
160
+ }
161
+
162
+ .btn-primary:active {
163
+ transform: scale(0.98);
164
+ }
165
+
166
+ .footer {
167
+ margin-top: 40px;
168
+ text-align: center;
169
+ font-size: 14px;
170
+ color: var(--text-muted);
171
+ }
172
+
173
+ .footer a {
174
+ color: var(--primary);
175
+ text-decoration: none;
176
+ font-weight: 600;
177
+ transition: 0.3s;
178
+ }
179
+
180
+ .footer a:hover {
181
+ opacity: 0.8;
182
+ text-decoration: underline;
183
+ }
184
+
185
+ .back-home {
186
+ display: block;
187
+ margin-top: 20px;
188
+ font-size: 12px;
189
+ opacity: 0.5;
190
+ transition: 0.3s;
191
+ }
192
+
193
+ .back-home:hover {
194
+ opacity: 1;
195
+ }
196
+
197
+ /* Responsive adjustments */
198
+ @media (max-width: 480px) {
199
+ .auth-card {
200
+ padding: 35px 20px;
201
+ }
202
+ }
203
+ </style>
204
+ </head>
205
+ <body>
206
+ <div class="background-blobs">
207
+ <div class="blob blob-1"></div>
208
+ <div class="blob blob-2"></div>
209
+ </div>
210
+
211
+ <div class="auth-card">
212
+ <h2>Join Us</h2>
213
+ <p class="subtitle">Create your account in seconds</p>
214
+
215
+ <form action="/api/users" method="POST" class="form-grid">
216
+ <div class="form-group">
217
+ <label for="name">Full Name</label>
218
+ <input type="text" id="name" name="name" placeholder="John Doe" required>
219
+ </div>
220
+
221
+ <div class="form-group">
222
+ <label for="email">Email Address</label>
223
+ <input type="email" id="email" name="email" placeholder="john@example.com" required>
224
+ </div>
225
+
226
+ <div class="form-group">
227
+ <label for="password">Choose Password</label>
228
+ <input type="password" id="password" name="password" placeholder="••••••••" required>
229
+ </div>
230
+
231
+ <button type="submit" class="btn-primary">Create Account</button>
232
+ </form>
233
+
234
+ <div class="footer">
235
+ <p>Already have an account? <a href="/login">Sign in</a></p>
236
+ <a href="/" class="back-home">← Back to home</a>
237
+ </div>
238
+ </div>
239
+
240
+ <% if (communication === 'GraphQL') { %>
241
+ <script>
242
+ document.querySelector('form').addEventListener('submit', async (e) => {
243
+ e.preventDefault();
244
+ const formData = new FormData(e.target);
245
+ const data = Object.fromEntries(formData.entries());
246
+
247
+ const query = `
248
+ mutation CreateUser($name: String!, $email: String!, $password: String!) {
249
+ createUser(name: $name, email: $email, password: $password) {
250
+ id
251
+ name
252
+ email
253
+ }
254
+ }
255
+ `;
256
+
257
+ try {
258
+ const response = await fetch('/graphql', {
259
+ method: 'POST',
260
+ headers: { 'Content-Type': 'application/json' },
261
+ body: JSON.stringify({
262
+ query,
263
+ variables: data
264
+ })
265
+ });
266
+
267
+ const result = await response.json();
268
+ if (result.errors) {
269
+ alert('Error: ' + result.errors[0].message);
270
+ } else {
271
+ alert('Account created successfully! Please login.');
272
+ window.location.href = '/login';
273
+ }
274
+ } catch (err) {
275
+ console.error(err);
276
+ alert('An error occurred during signup.');
277
+ }
278
+ });
279
+ </script>
280
+ <% } %>
281
+ </body>
282
+ </html>