@aurostack/stacks 0.1.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 (601) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +209 -0
  3. package/cli/src/extract.mjs +165 -0
  4. package/cli/src/fsx.mjs +197 -0
  5. package/cli/src/generate.mjs +235 -0
  6. package/cli/src/hooks.mjs +55 -0
  7. package/cli/src/manifest.mjs +163 -0
  8. package/cli/src/strip.mjs +208 -0
  9. package/cli/src/tokens.mjs +102 -0
  10. package/cli/stack.mjs +672 -0
  11. package/package.json +37 -0
  12. package/templates/nest-api/files/.bin/db.ts +123 -0
  13. package/templates/nest-api/files/.bin/dc.ts +74 -0
  14. package/templates/nest-api/files/.bin/helpers.ts +49 -0
  15. package/templates/nest-api/files/.bin/secrets.ts +68 -0
  16. package/templates/nest-api/files/.bin/start.ts +47 -0
  17. package/templates/nest-api/files/.dockerignore +7 -0
  18. package/templates/nest-api/files/.env.example +91 -0
  19. package/templates/nest-api/files/.env.test.example +75 -0
  20. package/templates/nest-api/files/.forgejo/workflows/build-and-push.yml +41 -0
  21. package/templates/nest-api/files/.forgejo/workflows/test-e2e.yml +83 -0
  22. package/templates/nest-api/files/.forgejo/workflows/test.yml +53 -0
  23. package/templates/nest-api/files/.npmrc.example +1 -0
  24. package/templates/nest-api/files/.nvmrc +1 -0
  25. package/templates/nest-api/files/.prettierrc +8 -0
  26. package/templates/nest-api/files/.swcrc +15 -0
  27. package/templates/nest-api/files/.watchmanconfig +3 -0
  28. package/templates/nest-api/files/.yarnrc.yml +1 -0
  29. package/templates/nest-api/files/Dockerfile +40 -0
  30. package/templates/nest-api/files/__mocks__/activation-twofa.js +7 -0
  31. package/templates/nest-api/files/__mocks__/activation.js +7 -0
  32. package/templates/nest-api/files/__mocks__/forgot-password.js +7 -0
  33. package/templates/nest-api/files/__mocks__/main-layout.js +7 -0
  34. package/templates/nest-api/files/__mocks__/password-changed.js +7 -0
  35. package/templates/nest-api/files/__mocks__/reset-password.js +7 -0
  36. package/templates/nest-api/files/__mocks__/set-password.js +7 -0
  37. package/templates/nest-api/files/__mocks__/welcome.js +7 -0
  38. package/templates/nest-api/files/_gitignore +62 -0
  39. package/templates/nest-api/files/compose.test.yml +33 -0
  40. package/templates/nest-api/files/compose.yml +39 -0
  41. package/templates/nest-api/files/emails/activation-twofa.tsx +58 -0
  42. package/templates/nest-api/files/emails/activation.tsx +36 -0
  43. package/templates/nest-api/files/emails/forgot-password.tsx +29 -0
  44. package/templates/nest-api/files/emails/main-layout.tsx +134 -0
  45. package/templates/nest-api/files/emails/password-changed.tsx +24 -0
  46. package/templates/nest-api/files/emails/reset-password.tsx +24 -0
  47. package/templates/nest-api/files/emails/set-password.tsx +25 -0
  48. package/templates/nest-api/files/emails/welcome.tsx +39 -0
  49. package/templates/nest-api/files/eslint.config.mjs +28 -0
  50. package/templates/nest-api/files/global.d.ts +5 -0
  51. package/templates/nest-api/files/nest-cli.json +8 -0
  52. package/templates/nest-api/files/package.json +150 -0
  53. package/templates/nest-api/files/prisma/schema/auth.prisma +75 -0
  54. package/templates/nest-api/files/prisma/schema/base.prisma +17 -0
  55. package/templates/nest-api/files/prisma/schema/enum.prisma +17 -0
  56. package/templates/nest-api/files/prisma/schema/notification.prisma +14 -0
  57. package/templates/nest-api/files/prisma.config.ts +13 -0
  58. package/templates/nest-api/files/public/.gitkeep +0 -0
  59. package/templates/nest-api/files/seeders/index.ts +27 -0
  60. package/templates/nest-api/files/seeders/util.ts +88 -0
  61. package/templates/nest-api/files/src/__tests__/app.controller.spec.ts +29 -0
  62. package/templates/nest-api/files/src/app.controller.ts +40 -0
  63. package/templates/nest-api/files/src/app.module.ts +268 -0
  64. package/templates/nest-api/files/src/app.resolver.ts +32 -0
  65. package/templates/nest-api/files/src/app.setup.ts +178 -0
  66. package/templates/nest-api/files/src/common/__tests__/auth.service.spec.ts +31 -0
  67. package/templates/nest-api/files/src/common/__tests__/cache.service.spec.ts +214 -0
  68. package/templates/nest-api/files/src/common/__tests__/config.service.spec.ts +56 -0
  69. package/templates/nest-api/files/src/common/__tests__/generator.service.spec.ts +114 -0
  70. package/templates/nest-api/files/src/common/__tests__/health.controller.spec.ts +72 -0
  71. package/templates/nest-api/files/src/common/__tests__/helpers.spec.ts +124 -0
  72. package/templates/nest-api/files/src/common/__tests__/mail.service.spec.ts +75 -0
  73. package/templates/nest-api/files/src/common/__tests__/prisma.indicator.spec.ts +39 -0
  74. package/templates/nest-api/files/src/common/__tests__/prisma.service.spec.ts +15 -0
  75. package/templates/nest-api/files/src/common/__tests__/records.spec.ts +87 -0
  76. package/templates/nest-api/files/src/common/__tests__/schemas.spec.ts +142 -0
  77. package/templates/nest-api/files/src/common/__tests__/throttler-storage.service.spec.ts +80 -0
  78. package/templates/nest-api/files/src/common/common.module.ts +72 -0
  79. package/templates/nest-api/files/src/common/constants/index.ts +2 -0
  80. package/templates/nest-api/files/src/common/constants/options.ts +52 -0
  81. package/templates/nest-api/files/src/common/constants/pino.ts +24 -0
  82. package/templates/nest-api/files/src/common/controllers/health.controller.ts +54 -0
  83. package/templates/nest-api/files/src/common/controllers/index.ts +2 -0
  84. package/templates/nest-api/files/src/common/controllers/metrics.controller.ts +21 -0
  85. package/templates/nest-api/files/src/common/decorators/index.ts +2 -0
  86. package/templates/nest-api/files/src/common/decorators/misc.decorator.ts +49 -0
  87. package/templates/nest-api/files/src/common/decorators/multi-part.decorator.ts +6 -0
  88. package/templates/nest-api/files/src/common/dto/filters.dto.ts +25 -0
  89. package/templates/nest-api/files/src/common/dto/index.ts +1 -0
  90. package/templates/nest-api/files/src/common/entity/index.ts +2 -0
  91. package/templates/nest-api/files/src/common/entity/ok.entity.ts +11 -0
  92. package/templates/nest-api/files/src/common/entity/pagination.entity.ts +24 -0
  93. package/templates/nest-api/files/src/common/exceptions/index.ts +1 -0
  94. package/templates/nest-api/files/src/common/exceptions/prisma.exception.ts +57 -0
  95. package/templates/nest-api/files/src/common/guards/feature-flag.guard.ts +51 -0
  96. package/templates/nest-api/files/src/common/guards/index.ts +1 -0
  97. package/templates/nest-api/files/src/common/interceptors/index.ts +1 -0
  98. package/templates/nest-api/files/src/common/interceptors/metrics.interceptor.ts +37 -0
  99. package/templates/nest-api/files/src/common/misc/helpers.ts +26 -0
  100. package/templates/nest-api/files/src/common/misc/index.ts +3 -0
  101. package/templates/nest-api/files/src/common/misc/origin-builder.ts +56 -0
  102. package/templates/nest-api/files/src/common/misc/prisma.indicator.ts +24 -0
  103. package/templates/nest-api/files/src/common/modules/index.ts +3 -0
  104. package/templates/nest-api/files/src/common/modules/logger.module.ts +104 -0
  105. package/templates/nest-api/files/src/common/modules/metrics.module.ts +28 -0
  106. package/templates/nest-api/files/src/common/modules/queue.module.ts +23 -0
  107. package/templates/nest-api/files/src/common/processors/index.ts +1 -0
  108. package/templates/nest-api/files/src/common/processors/mail/index.ts +47 -0
  109. package/templates/nest-api/files/src/common/processors/mail/process.ts +225 -0
  110. package/templates/nest-api/files/src/common/schemas/fields.ts +76 -0
  111. package/templates/nest-api/files/src/common/schemas/index.ts +1 -0
  112. package/templates/nest-api/files/src/common/services/auth-rate-limit.storage.ts +79 -0
  113. package/templates/nest-api/files/src/common/services/auth.service.ts +16 -0
  114. package/templates/nest-api/files/src/common/services/cache.service.ts +118 -0
  115. package/templates/nest-api/files/src/common/services/config.service.ts +388 -0
  116. package/templates/nest-api/files/src/common/services/feature-flag.service.ts +117 -0
  117. package/templates/nest-api/files/src/common/services/generator.service.ts +54 -0
  118. package/templates/nest-api/files/src/common/services/index.ts +10 -0
  119. package/templates/nest-api/files/src/common/services/logger.service.ts +14 -0
  120. package/templates/nest-api/files/src/common/services/mail.service.ts +44 -0
  121. package/templates/nest-api/files/src/common/services/prisma.service.ts +106 -0
  122. package/templates/nest-api/files/src/common/services/throttler-storage.service.ts +112 -0
  123. package/templates/nest-api/files/src/common/types/email.ts +55 -0
  124. package/templates/nest-api/files/src/common/types/index.ts +3 -0
  125. package/templates/nest-api/files/src/common/types/misc.ts +20 -0
  126. package/templates/nest-api/files/src/common/types/prisma.ts +18 -0
  127. package/templates/nest-api/files/src/common/utils/enum.ts +39 -0
  128. package/templates/nest-api/files/src/common/utils/helpers.ts +139 -0
  129. package/templates/nest-api/files/src/common/utils/index.ts +5 -0
  130. package/templates/nest-api/files/src/common/utils/ip.ts +22 -0
  131. package/templates/nest-api/files/src/common/utils/records.ts +66 -0
  132. package/templates/nest-api/files/src/common/utils/redis.keys.ts +31 -0
  133. package/templates/nest-api/files/src/lib/__tests__/access.spec.ts +33 -0
  134. package/templates/nest-api/files/src/lib/access.ts +114 -0
  135. package/templates/nest-api/files/src/lib/auth.ts +76 -0
  136. package/templates/nest-api/files/src/lib/rate-limit.ts +20 -0
  137. package/templates/nest-api/files/src/main.ts +28 -0
  138. package/templates/nest-api/files/src/media/__tests__/media.service.spec.ts +60 -0
  139. package/templates/nest-api/files/src/media/__tests__/s3.service.spec.ts +159 -0
  140. package/templates/nest-api/files/src/media/entity/file.entity.ts +7 -0
  141. package/templates/nest-api/files/src/media/entity/index.ts +1 -0
  142. package/templates/nest-api/files/src/media/media.module.ts +20 -0
  143. package/templates/nest-api/files/src/media/processors/index.ts +44 -0
  144. package/templates/nest-api/files/src/media/services/index.ts +2 -0
  145. package/templates/nest-api/files/src/media/services/media.service.ts +29 -0
  146. package/templates/nest-api/files/src/media/services/s3.service.ts +168 -0
  147. package/templates/nest-api/files/src/notifications/controllers/index.ts +1 -0
  148. package/templates/nest-api/files/src/notifications/controllers/notifications.controller.ts +72 -0
  149. package/templates/nest-api/files/src/notifications/dto/index.ts +1 -0
  150. package/templates/nest-api/files/src/notifications/dto/notification.dto.ts +11 -0
  151. package/templates/nest-api/files/src/notifications/entity/index.ts +1 -0
  152. package/templates/nest-api/files/src/notifications/entity/notification.entity.ts +37 -0
  153. package/templates/nest-api/files/src/notifications/notifications.module.ts +11 -0
  154. package/templates/nest-api/files/src/notifications/services/index.ts +1 -0
  155. package/templates/nest-api/files/src/notifications/services/notifications.service.ts +98 -0
  156. package/templates/nest-api/files/src/realtime/__tests__/events.gateway.spec.ts +88 -0
  157. package/templates/nest-api/files/src/realtime/__tests__/rooms.spec.ts +29 -0
  158. package/templates/nest-api/files/src/realtime/__tests__/ws-permissions.guard.spec.ts +54 -0
  159. package/templates/nest-api/files/src/realtime/adapters/redis-io.adapter.ts +57 -0
  160. package/templates/nest-api/files/src/realtime/constants/index.ts +68 -0
  161. package/templates/nest-api/files/src/realtime/decorators/index.ts +1 -0
  162. package/templates/nest-api/files/src/realtime/decorators/ws-permissions.decorator.ts +14 -0
  163. package/templates/nest-api/files/src/realtime/gateways/events.gateway.ts +187 -0
  164. package/templates/nest-api/files/src/realtime/guards/index.ts +2 -0
  165. package/templates/nest-api/files/src/realtime/guards/ws-auth.guard.ts +20 -0
  166. package/templates/nest-api/files/src/realtime/guards/ws-permissions.guard.ts +35 -0
  167. package/templates/nest-api/files/src/realtime/misc/session-from-socket.ts +54 -0
  168. package/templates/nest-api/files/src/realtime/realtime.module.ts +26 -0
  169. package/templates/nest-api/files/src/realtime/services/presence.service.ts +56 -0
  170. package/templates/nest-api/files/src/realtime/services/realtime.service.ts +72 -0
  171. package/templates/nest-api/files/src/users/__tests__/current-user.controller.spec.ts +77 -0
  172. package/templates/nest-api/files/src/users/__tests__/current-user.service.spec.ts +159 -0
  173. package/templates/nest-api/files/src/users/__tests__/user.entity.spec.ts +175 -0
  174. package/templates/nest-api/files/src/users/__tests__/users.controller.spec.ts +89 -0
  175. package/templates/nest-api/files/src/users/__tests__/users.service.spec.ts +398 -0
  176. package/templates/nest-api/files/src/users/controllers/current-user.controller.ts +82 -0
  177. package/templates/nest-api/files/src/users/controllers/index.ts +2 -0
  178. package/templates/nest-api/files/src/users/controllers/users.controller.ts +40 -0
  179. package/templates/nest-api/files/src/users/decorators/index.ts +1 -0
  180. package/templates/nest-api/files/src/users/decorators/permissions.decorator.ts +24 -0
  181. package/templates/nest-api/files/src/users/dto/avatar.dto.ts +13 -0
  182. package/templates/nest-api/files/src/users/dto/filters.dto.ts +8 -0
  183. package/templates/nest-api/files/src/users/dto/index.ts +2 -0
  184. package/templates/nest-api/files/src/users/entity/index.ts +1 -0
  185. package/templates/nest-api/files/src/users/entity/user.entity.ts +53 -0
  186. package/templates/nest-api/files/src/users/services/current-user.service.ts +46 -0
  187. package/templates/nest-api/files/src/users/services/index.ts +2 -0
  188. package/templates/nest-api/files/src/users/services/users.service.ts +88 -0
  189. package/templates/nest-api/files/src/users/users.module.ts +10 -0
  190. package/templates/nest-api/files/test/app.spec.ts +102 -0
  191. package/templates/nest-api/files/test/auth.spec.ts +108 -0
  192. package/templates/nest-api/files/test/current-user.spec.ts +154 -0
  193. package/templates/nest-api/files/test/factory/app.ts +172 -0
  194. package/templates/nest-api/files/test/factory/constants.ts +22 -0
  195. package/templates/nest-api/files/test/factory/dto.ts +27 -0
  196. package/templates/nest-api/files/test/factory/entity.ts +70 -0
  197. package/templates/nest-api/files/test/factory/gen.ts +75 -0
  198. package/templates/nest-api/files/test/factory/util.ts +21 -0
  199. package/templates/nest-api/files/test/notifications.spec.ts +176 -0
  200. package/templates/nest-api/files/test/rate-limit.spec.ts +180 -0
  201. package/templates/nest-api/files/test/setup.ts +1 -0
  202. package/templates/nest-api/files/test/users.spec.ts +437 -0
  203. package/templates/nest-api/files/tsconfig.build.json +13 -0
  204. package/templates/nest-api/files/tsconfig.json +35 -0
  205. package/templates/nest-api/files/vitest.config.ts +53 -0
  206. package/templates/nest-api/template.json +452 -0
  207. package/templates/node-worker/files/.bin/db.ts +123 -0
  208. package/templates/node-worker/files/.bin/helpers.ts +49 -0
  209. package/templates/node-worker/files/.bin/secrets.ts +68 -0
  210. package/templates/node-worker/files/.dockerignore +5 -0
  211. package/templates/node-worker/files/.env.example +21 -0
  212. package/templates/node-worker/files/.forgejo/workflows/build-and-push.yml +41 -0
  213. package/templates/node-worker/files/.nvmrc +1 -0
  214. package/templates/node-worker/files/.prettierignore +4 -0
  215. package/templates/node-worker/files/.prettierrc +8 -0
  216. package/templates/node-worker/files/.yarnrc.yml +5 -0
  217. package/templates/node-worker/files/Dockerfile +63 -0
  218. package/templates/node-worker/files/Dockerfile.dev +59 -0
  219. package/templates/node-worker/files/_gitignore +48 -0
  220. package/templates/node-worker/files/ecosystem.config.cjs +10 -0
  221. package/templates/node-worker/files/eslint.config.js +37 -0
  222. package/templates/node-worker/files/package.json +67 -0
  223. package/templates/node-worker/files/prisma/_gitignore +1 -0
  224. package/templates/node-worker/files/prisma/schema/base.prisma +36 -0
  225. package/templates/node-worker/files/prisma.config.ts +13 -0
  226. package/templates/node-worker/files/src/config.ts +55 -0
  227. package/templates/node-worker/files/src/db.ts +118 -0
  228. package/templates/node-worker/files/src/index.ts +7 -0
  229. package/templates/node-worker/files/src/logger.ts +45 -0
  230. package/templates/node-worker/files/src/types.ts +23 -0
  231. package/templates/node-worker/files/src/utils/browser.ts +16 -0
  232. package/templates/node-worker/files/src/utils/date.ts +68 -0
  233. package/templates/node-worker/files/src/utils/helpers.ts +17 -0
  234. package/templates/node-worker/files/src/utils/number.ts +47 -0
  235. package/templates/node-worker/files/src/utils/worker.ts +29 -0
  236. package/templates/node-worker/files/src/workers/constants.ts +6 -0
  237. package/templates/node-worker/files/src/workers/example/index.ts +27 -0
  238. package/templates/node-worker/files/src/workers/index.ts +1 -0
  239. package/templates/node-worker/files/tsconfig.json +30 -0
  240. package/templates/node-worker/template.json +135 -0
  241. package/templates/py-worker/files/.dockerignore +176 -0
  242. package/templates/py-worker/files/.env.example +20 -0
  243. package/templates/py-worker/files/.forgejo/workflows/build-amd-push.yml +39 -0
  244. package/templates/py-worker/files/Dockerfile +10 -0
  245. package/templates/py-worker/files/README.md +3 -0
  246. package/templates/py-worker/files/_gitignore +176 -0
  247. package/templates/py-worker/files/config.py +89 -0
  248. package/templates/py-worker/files/models/decorators.py +42 -0
  249. package/templates/py-worker/files/models/enums.py +32 -0
  250. package/templates/py-worker/files/models/mixins.py +61 -0
  251. package/templates/py-worker/files/requirements.txt +18 -0
  252. package/templates/py-worker/files/utils/db.py +67 -0
  253. package/templates/py-worker/files/utils/logger.py +97 -0
  254. package/templates/py-worker/files/utils/misc.py +45 -0
  255. package/templates/py-worker/files/utils/worker.py +80 -0
  256. package/templates/py-worker/files/worker.py +41 -0
  257. package/templates/py-worker/files/workers/hello/process.py +22 -0
  258. package/templates/py-worker/template.json +87 -0
  259. package/templates/react-app/README.md +78 -0
  260. package/templates/react-app/derive.sh +128 -0
  261. package/templates/react-app/files/.bin/openapi.js +32 -0
  262. package/templates/react-app/files/.bin/secrets.js +47 -0
  263. package/templates/react-app/files/.dockerignore +16 -0
  264. package/templates/react-app/files/.editorconfig +12 -0
  265. package/templates/react-app/files/.env.example +34 -0
  266. package/templates/react-app/files/.forgejo/workflows/build-and-push.yml +55 -0
  267. package/templates/react-app/files/.forgejo/workflows/ci.yml +39 -0
  268. package/templates/react-app/files/.husky/pre-commit +1 -0
  269. package/templates/react-app/files/.nvmrc +1 -0
  270. package/templates/react-app/files/.prettierignore +6 -0
  271. package/templates/react-app/files/.prettierrc +9 -0
  272. package/templates/react-app/files/.yarnrc.yml +2 -0
  273. package/templates/react-app/files/Dockerfile +52 -0
  274. package/templates/react-app/files/_gitignore +33 -0
  275. package/templates/react-app/files/build.sh +53 -0
  276. package/templates/react-app/files/docker/nginx.conf +134 -0
  277. package/templates/react-app/files/eslint.config.mjs +75 -0
  278. package/templates/react-app/files/index.html +62 -0
  279. package/templates/react-app/files/openapi-ts.config.ts +22 -0
  280. package/templates/react-app/files/package.json +80 -0
  281. package/templates/react-app/files/src/app/nav.tsx +32 -0
  282. package/templates/react-app/files/src/app/providers.tsx +39 -0
  283. package/templates/react-app/files/src/app/router.tsx +142 -0
  284. package/templates/react-app/files/src/app/store.ts +20 -0
  285. package/templates/react-app/files/src/features/auth/components/auth-card.tsx +23 -0
  286. package/templates/react-app/files/src/features/auth/components/checkbox-field.tsx +32 -0
  287. package/templates/react-app/files/src/features/auth/components/google-button.tsx +41 -0
  288. package/templates/react-app/files/src/features/auth/components/or-divider.tsx +9 -0
  289. package/templates/react-app/files/src/features/auth/components/password-field.tsx +70 -0
  290. package/templates/react-app/files/src/features/auth/components/submit-button.tsx +16 -0
  291. package/templates/react-app/files/src/features/auth/lib/auth-actions.ts +68 -0
  292. package/templates/react-app/files/src/features/auth/lib/password-strength.ts +20 -0
  293. package/templates/react-app/files/src/features/auth/lib/redirect.ts +6 -0
  294. package/templates/react-app/files/src/features/auth/lib/schemas.ts +37 -0
  295. package/templates/react-app/files/src/features/seo/routes.ts +65 -0
  296. package/templates/react-app/files/src/lib/env.ts +28 -0
  297. package/templates/react-app/files/src/lib/paths.ts +58 -0
  298. package/templates/react-app/files/src/main.tsx +19 -0
  299. package/templates/react-app/files/src/routes/admin/home.tsx +24 -0
  300. package/templates/react-app/files/src/routes/auth/forgot-password.tsx +93 -0
  301. package/templates/react-app/files/src/routes/auth/login.tsx +87 -0
  302. package/templates/react-app/files/src/routes/auth/reset-password.tsx +83 -0
  303. package/templates/react-app/files/src/routes/auth/signup.tsx +117 -0
  304. package/templates/react-app/files/src/routes/auth/verified.tsx +31 -0
  305. package/templates/react-app/files/src/routes/auth/verify-email.tsx +97 -0
  306. package/templates/react-app/files/src/routes/home.tsx +17 -0
  307. package/templates/react-app/files/src/routes/legal/privacy.tsx +26 -0
  308. package/templates/react-app/files/src/routes/legal/terms.tsx +28 -0
  309. package/templates/react-app/files/src/routes/marketing/home.tsx +18 -0
  310. package/templates/react-app/files/src/routes/settings.tsx +10 -0
  311. package/templates/react-app/files/src/shared/api/base-api.ts +24 -0
  312. package/templates/react-app/files/src/shared/api/base-query.ts +29 -0
  313. package/templates/react-app/files/src/shared/api/config.ts +21 -0
  314. package/templates/react-app/files/src/shared/api/index.ts +15 -0
  315. package/templates/react-app/files/src/shared/api/realtime-events.ts +34 -0
  316. package/templates/react-app/files/src/shared/api/socket.ts +41 -0
  317. package/templates/react-app/files/src/shared/api/store.ts +39 -0
  318. package/templates/react-app/files/src/shared/api/upload-query.ts +115 -0
  319. package/templates/react-app/files/src/shared/auth/client.ts +27 -0
  320. package/templates/react-app/files/src/shared/auth/config.ts +28 -0
  321. package/templates/react-app/files/src/shared/auth/guards.tsx +75 -0
  322. package/templates/react-app/files/src/shared/auth/hooks.ts +13 -0
  323. package/templates/react-app/files/src/shared/auth/index.ts +20 -0
  324. package/templates/react-app/files/src/shared/auth/logout.ts +23 -0
  325. package/templates/react-app/files/src/shared/auth/provider.tsx +52 -0
  326. package/templates/react-app/files/src/shared/auth/redirect.ts +65 -0
  327. package/templates/react-app/files/src/shared/auth/slice.ts +54 -0
  328. package/templates/react-app/files/src/shared/hooks/index.ts +6 -0
  329. package/templates/react-app/files/src/shared/layouts/app-shell/app-shell.tsx +225 -0
  330. package/templates/react-app/files/src/shared/layouts/app-shell/user-menu.tsx +74 -0
  331. package/templates/react-app/files/src/shared/layouts/auth-layout.tsx +137 -0
  332. package/templates/react-app/files/src/shared/layouts/error-boundary.tsx +38 -0
  333. package/templates/react-app/files/src/shared/layouts/index.ts +23 -0
  334. package/templates/react-app/files/src/shared/layouts/marketing/marketing-layout.tsx +29 -0
  335. package/templates/react-app/files/src/shared/layouts/marketing/section-heading.tsx +38 -0
  336. package/templates/react-app/files/src/shared/layouts/marketing/section.tsx +30 -0
  337. package/templates/react-app/files/src/shared/layouts/states/app-shell-skeleton.tsx +47 -0
  338. package/templates/react-app/files/src/shared/layouts/states/empty.tsx +22 -0
  339. package/templates/react-app/files/src/shared/layouts/states/forbidden.tsx +14 -0
  340. package/templates/react-app/files/src/shared/layouts/states/loading.tsx +11 -0
  341. package/templates/react-app/files/src/shared/layouts/states/not-found.tsx +21 -0
  342. package/templates/react-app/files/src/shared/layouts/states/page-skeleton.tsx +39 -0
  343. package/templates/react-app/files/src/shared/layouts/states/route-fallback.tsx +26 -0
  344. package/templates/react-app/files/src/shared/layouts/states/state-screen.tsx +22 -0
  345. package/templates/react-app/files/src/shared/types/README.md +28 -0
  346. package/templates/react-app/files/src/shared/types/api/index.ts +9 -0
  347. package/templates/react-app/files/src/shared/types/api/zod.gen.ts +5 -0
  348. package/templates/react-app/files/src/shared/types/index.ts +4 -0
  349. package/templates/react-app/files/src/shared/ui/components/brand/logo.tsx +51 -0
  350. package/templates/react-app/files/src/shared/ui/components/brand/social-icons.tsx +37 -0
  351. package/templates/react-app/files/src/shared/ui/components/form/form.tsx +120 -0
  352. package/templates/react-app/files/src/shared/ui/components/ui/alert.tsx +25 -0
  353. package/templates/react-app/files/src/shared/ui/components/ui/button.tsx +43 -0
  354. package/templates/react-app/files/src/shared/ui/components/ui/calendar.tsx +78 -0
  355. package/templates/react-app/files/src/shared/ui/components/ui/card.tsx +44 -0
  356. package/templates/react-app/files/src/shared/ui/components/ui/checkbox.tsx +16 -0
  357. package/templates/react-app/files/src/shared/ui/components/ui/date-picker.tsx +76 -0
  358. package/templates/react-app/files/src/shared/ui/components/ui/input.tsx +22 -0
  359. package/templates/react-app/files/src/shared/ui/components/ui/label.tsx +19 -0
  360. package/templates/react-app/files/src/shared/ui/components/ui/modal.tsx +94 -0
  361. package/templates/react-app/files/src/shared/ui/components/ui/popover.tsx +31 -0
  362. package/templates/react-app/files/src/shared/ui/components/ui/progress.tsx +33 -0
  363. package/templates/react-app/files/src/shared/ui/components/ui/search-input.tsx +69 -0
  364. package/templates/react-app/files/src/shared/ui/components/ui/select.tsx +80 -0
  365. package/templates/react-app/files/src/shared/ui/components/ui/skeleton.tsx +12 -0
  366. package/templates/react-app/files/src/shared/ui/components/ui/sonner.tsx +23 -0
  367. package/templates/react-app/files/src/shared/ui/components/ui/spinner.tsx +8 -0
  368. package/templates/react-app/files/src/shared/ui/components/ui/textarea.tsx +22 -0
  369. package/templates/react-app/files/src/shared/ui/index.ts +45 -0
  370. package/templates/react-app/files/src/shared/ui/lib/utils.ts +7 -0
  371. package/templates/react-app/files/src/shared/ui/lib/zod-setup.ts +28 -0
  372. package/templates/react-app/files/src/shared/ui/meta/brand.ts +18 -0
  373. package/templates/react-app/files/src/shared/ui/meta/meta-context.ts +30 -0
  374. package/templates/react-app/files/src/shared/ui/meta/meta-provider.tsx +24 -0
  375. package/templates/react-app/files/src/shared/ui/meta/page-meta.tsx +69 -0
  376. package/templates/react-app/files/src/shared/ui/meta/use-meta-config.ts +11 -0
  377. package/templates/react-app/files/src/shared/ui/styles/globals.css +285 -0
  378. package/templates/react-app/files/src/shared/ui/styles/theme.css +48 -0
  379. package/templates/react-app/files/src/shared/ui/theme/init-script.ts +23 -0
  380. package/templates/react-app/files/src/shared/ui/theme/theme-colors.ts +14 -0
  381. package/templates/react-app/files/src/shared/ui/theme/theme-context.ts +60 -0
  382. package/templates/react-app/files/src/shared/ui/theme/theme-provider.tsx +101 -0
  383. package/templates/react-app/files/src/shared/ui/theme/theme-toggle.tsx +40 -0
  384. package/templates/react-app/files/src/shared/ui/theme/use-theme.ts +11 -0
  385. package/templates/react-app/files/src/vite-env.d.ts +13 -0
  386. package/templates/react-app/files/tsconfig.json +26 -0
  387. package/templates/react-app/files/tsconfig.node.json +25 -0
  388. package/templates/react-app/files/vite.config.ts +344 -0
  389. package/templates/react-app/overrides/src/routes/auth/forgot-password.tsx +93 -0
  390. package/templates/react-app/overrides/src/routes/auth/login.tsx +87 -0
  391. package/templates/react-app/overrides/src/routes/auth/signup.tsx +117 -0
  392. package/templates/react-app/overrides/src/routes/auth/verified.tsx +31 -0
  393. package/templates/react-app/overrides/src/routes/auth/verify-email.tsx +97 -0
  394. package/templates/react-app/overrides/src/shared/auth/config.ts +28 -0
  395. package/templates/react-app/overrides/src/shared/auth/guards.tsx +75 -0
  396. package/templates/react-app/overrides/src/shared/auth/index.ts +20 -0
  397. package/templates/react-app/overrides/src/shared/auth/redirect.ts +65 -0
  398. package/templates/react-app/overrides/src/shared/hooks/index.ts +6 -0
  399. package/templates/react-app/overrides/src/shared/types/README.md +28 -0
  400. package/templates/react-app/template.json +222 -0
  401. package/templates/react-monorepo/files/.dockerignore +19 -0
  402. package/templates/react-monorepo/files/.editorconfig +12 -0
  403. package/templates/react-monorepo/files/.forgejo/workflows/build-and-push.yml +98 -0
  404. package/templates/react-monorepo/files/.forgejo/workflows/ci.yml +35 -0
  405. package/templates/react-monorepo/files/.husky/pre-commit +1 -0
  406. package/templates/react-monorepo/files/.nvmrc +1 -0
  407. package/templates/react-monorepo/files/.prettierignore +6 -0
  408. package/templates/react-monorepo/files/.prettierrc +9 -0
  409. package/templates/react-monorepo/files/.yarnrc.yml +2 -0
  410. package/templates/react-monorepo/files/Dockerfile +90 -0
  411. package/templates/react-monorepo/files/_gitignore +35 -0
  412. package/templates/react-monorepo/files/apps/admin/.bin/secrets.js +57 -0
  413. package/templates/react-monorepo/files/apps/admin/.env.example +16 -0
  414. package/templates/react-monorepo/files/apps/admin/eslint.config.mjs +3 -0
  415. package/templates/react-monorepo/files/apps/admin/index.html +57 -0
  416. package/templates/react-monorepo/files/apps/admin/package.json +33 -0
  417. package/templates/react-monorepo/files/apps/admin/src/App.tsx +3 -0
  418. package/templates/react-monorepo/files/apps/admin/src/app/nav.tsx +14 -0
  419. package/templates/react-monorepo/files/apps/admin/src/app/providers.tsx +42 -0
  420. package/templates/react-monorepo/files/apps/admin/src/app/router.tsx +50 -0
  421. package/templates/react-monorepo/files/apps/admin/src/app/store.ts +15 -0
  422. package/templates/react-monorepo/files/apps/admin/src/lib/env.ts +12 -0
  423. package/templates/react-monorepo/files/apps/admin/src/main.tsx +14 -0
  424. package/templates/react-monorepo/files/apps/admin/src/routes/home.tsx +17 -0
  425. package/templates/react-monorepo/files/apps/admin/src/routes/settings.tsx +10 -0
  426. package/templates/react-monorepo/files/apps/admin/src/vite-env.d.ts +14 -0
  427. package/templates/react-monorepo/files/apps/admin/tsconfig.json +10 -0
  428. package/templates/react-monorepo/files/apps/admin/vite.config.ts +13 -0
  429. package/templates/react-monorepo/files/apps/auth/.bin/secrets.js +57 -0
  430. package/templates/react-monorepo/files/apps/auth/.env.example +16 -0
  431. package/templates/react-monorepo/files/apps/auth/eslint.config.mjs +3 -0
  432. package/templates/react-monorepo/files/apps/auth/index.html +57 -0
  433. package/templates/react-monorepo/files/apps/auth/package.json +32 -0
  434. package/templates/react-monorepo/files/apps/auth/src/App.tsx +3 -0
  435. package/templates/react-monorepo/files/apps/auth/src/app/providers.tsx +42 -0
  436. package/templates/react-monorepo/files/apps/auth/src/app/router.tsx +19 -0
  437. package/templates/react-monorepo/files/apps/auth/src/app/store.ts +15 -0
  438. package/templates/react-monorepo/files/apps/auth/src/components/auth-card.tsx +23 -0
  439. package/templates/react-monorepo/files/apps/auth/src/components/checkbox-field.tsx +32 -0
  440. package/templates/react-monorepo/files/apps/auth/src/components/google-button.tsx +41 -0
  441. package/templates/react-monorepo/files/apps/auth/src/components/or-divider.tsx +9 -0
  442. package/templates/react-monorepo/files/apps/auth/src/components/password-field.tsx +70 -0
  443. package/templates/react-monorepo/files/apps/auth/src/components/submit-button.tsx +16 -0
  444. package/templates/react-monorepo/files/apps/auth/src/lib/auth-actions.ts +68 -0
  445. package/templates/react-monorepo/files/apps/auth/src/lib/env.ts +8 -0
  446. package/templates/react-monorepo/files/apps/auth/src/lib/password-strength.ts +20 -0
  447. package/templates/react-monorepo/files/apps/auth/src/lib/redirect.ts +6 -0
  448. package/templates/react-monorepo/files/apps/auth/src/lib/schemas.ts +37 -0
  449. package/templates/react-monorepo/files/apps/auth/src/main.tsx +14 -0
  450. package/templates/react-monorepo/files/apps/auth/src/routes/forgot-password.tsx +91 -0
  451. package/templates/react-monorepo/files/apps/auth/src/routes/login.tsx +82 -0
  452. package/templates/react-monorepo/files/apps/auth/src/routes/reset-password.tsx +83 -0
  453. package/templates/react-monorepo/files/apps/auth/src/routes/signup.tsx +117 -0
  454. package/templates/react-monorepo/files/apps/auth/src/routes/verified.tsx +30 -0
  455. package/templates/react-monorepo/files/apps/auth/src/routes/verify-email.tsx +96 -0
  456. package/templates/react-monorepo/files/apps/auth/src/vite-env.d.ts +14 -0
  457. package/templates/react-monorepo/files/apps/auth/tsconfig.json +10 -0
  458. package/templates/react-monorepo/files/apps/auth/vite.config.ts +13 -0
  459. package/templates/react-monorepo/files/apps/client/.bin/secrets.js +57 -0
  460. package/templates/react-monorepo/files/apps/client/.env.example +16 -0
  461. package/templates/react-monorepo/files/apps/client/eslint.config.mjs +3 -0
  462. package/templates/react-monorepo/files/apps/client/index.html +57 -0
  463. package/templates/react-monorepo/files/apps/client/package.json +35 -0
  464. package/templates/react-monorepo/files/apps/client/src/App.tsx +3 -0
  465. package/templates/react-monorepo/files/apps/client/src/app/nav.tsx +14 -0
  466. package/templates/react-monorepo/files/apps/client/src/app/providers.tsx +42 -0
  467. package/templates/react-monorepo/files/apps/client/src/app/router.tsx +50 -0
  468. package/templates/react-monorepo/files/apps/client/src/app/store.ts +15 -0
  469. package/templates/react-monorepo/files/apps/client/src/lib/env.ts +12 -0
  470. package/templates/react-monorepo/files/apps/client/src/main.tsx +19 -0
  471. package/templates/react-monorepo/files/apps/client/src/routes/home.tsx +17 -0
  472. package/templates/react-monorepo/files/apps/client/src/routes/settings.tsx +10 -0
  473. package/templates/react-monorepo/files/apps/client/src/vite-env.d.ts +15 -0
  474. package/templates/react-monorepo/files/apps/client/tsconfig.json +10 -0
  475. package/templates/react-monorepo/files/apps/client/vite.config.ts +120 -0
  476. package/templates/react-monorepo/files/apps/landing/.bin/secrets.js +57 -0
  477. package/templates/react-monorepo/files/apps/landing/.env.example +20 -0
  478. package/templates/react-monorepo/files/apps/landing/eslint.config.mjs +3 -0
  479. package/templates/react-monorepo/files/apps/landing/index.html +51 -0
  480. package/templates/react-monorepo/files/apps/landing/package.json +33 -0
  481. package/templates/react-monorepo/files/apps/landing/src/App.tsx +3 -0
  482. package/templates/react-monorepo/files/apps/landing/src/app/providers.tsx +42 -0
  483. package/templates/react-monorepo/files/apps/landing/src/app/router.tsx +21 -0
  484. package/templates/react-monorepo/files/apps/landing/src/app/store.ts +18 -0
  485. package/templates/react-monorepo/files/apps/landing/src/features/seo/routes.ts +65 -0
  486. package/templates/react-monorepo/files/apps/landing/src/lib/env.ts +10 -0
  487. package/templates/react-monorepo/files/apps/landing/src/main.tsx +14 -0
  488. package/templates/react-monorepo/files/apps/landing/src/routes/home.tsx +18 -0
  489. package/templates/react-monorepo/files/apps/landing/src/vite-env.d.ts +15 -0
  490. package/templates/react-monorepo/files/apps/landing/tsconfig.json +10 -0
  491. package/templates/react-monorepo/files/apps/landing/vite.config.ts +169 -0
  492. package/templates/react-monorepo/files/build.sh +61 -0
  493. package/templates/react-monorepo/files/docker/nginx.conf +136 -0
  494. package/templates/react-monorepo/files/package.json +37 -0
  495. package/templates/react-monorepo/files/packages/.gitkeep +0 -0
  496. package/templates/react-monorepo/files/packages/api/eslint.config.mjs +3 -0
  497. package/templates/react-monorepo/files/packages/api/package.json +30 -0
  498. package/templates/react-monorepo/files/packages/api/src/base-api.ts +24 -0
  499. package/templates/react-monorepo/files/packages/api/src/base-query.ts +29 -0
  500. package/templates/react-monorepo/files/packages/api/src/config.ts +21 -0
  501. package/templates/react-monorepo/files/packages/api/src/index.ts +15 -0
  502. package/templates/react-monorepo/files/packages/api/src/realtime-events.ts +34 -0
  503. package/templates/react-monorepo/files/packages/api/src/socket.ts +41 -0
  504. package/templates/react-monorepo/files/packages/api/src/store.ts +39 -0
  505. package/templates/react-monorepo/files/packages/api/src/upload-query.ts +115 -0
  506. package/templates/react-monorepo/files/packages/api/tsconfig.json +4 -0
  507. package/templates/react-monorepo/files/packages/auth/eslint.config.mjs +3 -0
  508. package/templates/react-monorepo/files/packages/auth/package.json +33 -0
  509. package/templates/react-monorepo/files/packages/auth/src/client.ts +27 -0
  510. package/templates/react-monorepo/files/packages/auth/src/config.ts +22 -0
  511. package/templates/react-monorepo/files/packages/auth/src/guards.tsx +61 -0
  512. package/templates/react-monorepo/files/packages/auth/src/hooks.ts +13 -0
  513. package/templates/react-monorepo/files/packages/auth/src/index.ts +20 -0
  514. package/templates/react-monorepo/files/packages/auth/src/logout.ts +23 -0
  515. package/templates/react-monorepo/files/packages/auth/src/provider.tsx +52 -0
  516. package/templates/react-monorepo/files/packages/auth/src/redirect.ts +37 -0
  517. package/templates/react-monorepo/files/packages/auth/src/slice.ts +54 -0
  518. package/templates/react-monorepo/files/packages/auth/tsconfig.json +4 -0
  519. package/templates/react-monorepo/files/packages/config/README.md +47 -0
  520. package/templates/react-monorepo/files/packages/config/eslint/base.mjs +83 -0
  521. package/templates/react-monorepo/files/packages/config/package.json +37 -0
  522. package/templates/react-monorepo/files/packages/config/tailwind/theme.css +48 -0
  523. package/templates/react-monorepo/files/packages/config/tsconfig/base.json +22 -0
  524. package/templates/react-monorepo/files/packages/config/tsconfig/node.json +9 -0
  525. package/templates/react-monorepo/files/packages/config/tsconfig/react.json +9 -0
  526. package/templates/react-monorepo/files/packages/config/vite/index.d.ts +18 -0
  527. package/templates/react-monorepo/files/packages/config/vite/index.mjs +129 -0
  528. package/templates/react-monorepo/files/packages/hooks/eslint.config.mjs +3 -0
  529. package/templates/react-monorepo/files/packages/hooks/package.json +16 -0
  530. package/templates/react-monorepo/files/packages/hooks/src/index.ts +3 -0
  531. package/templates/react-monorepo/files/packages/hooks/tsconfig.json +4 -0
  532. package/templates/react-monorepo/files/packages/layouts/eslint.config.mjs +3 -0
  533. package/templates/react-monorepo/files/packages/layouts/package.json +30 -0
  534. package/templates/react-monorepo/files/packages/layouts/src/app-shell/app-shell.tsx +225 -0
  535. package/templates/react-monorepo/files/packages/layouts/src/app-shell/user-menu.tsx +74 -0
  536. package/templates/react-monorepo/files/packages/layouts/src/auth-layout.tsx +137 -0
  537. package/templates/react-monorepo/files/packages/layouts/src/error-boundary.tsx +38 -0
  538. package/templates/react-monorepo/files/packages/layouts/src/index.ts +23 -0
  539. package/templates/react-monorepo/files/packages/layouts/src/marketing/marketing-layout.tsx +29 -0
  540. package/templates/react-monorepo/files/packages/layouts/src/marketing/section-heading.tsx +38 -0
  541. package/templates/react-monorepo/files/packages/layouts/src/marketing/section.tsx +30 -0
  542. package/templates/react-monorepo/files/packages/layouts/src/states/app-shell-skeleton.tsx +47 -0
  543. package/templates/react-monorepo/files/packages/layouts/src/states/empty.tsx +22 -0
  544. package/templates/react-monorepo/files/packages/layouts/src/states/forbidden.tsx +14 -0
  545. package/templates/react-monorepo/files/packages/layouts/src/states/loading.tsx +11 -0
  546. package/templates/react-monorepo/files/packages/layouts/src/states/not-found.tsx +21 -0
  547. package/templates/react-monorepo/files/packages/layouts/src/states/page-skeleton.tsx +39 -0
  548. package/templates/react-monorepo/files/packages/layouts/src/states/route-fallback.tsx +26 -0
  549. package/templates/react-monorepo/files/packages/layouts/src/states/state-screen.tsx +22 -0
  550. package/templates/react-monorepo/files/packages/layouts/tsconfig.json +4 -0
  551. package/templates/react-monorepo/files/packages/types/.bin/openapi.js +32 -0
  552. package/templates/react-monorepo/files/packages/types/.bin/secrets.js +57 -0
  553. package/templates/react-monorepo/files/packages/types/README.md +28 -0
  554. package/templates/react-monorepo/files/packages/types/eslint.config.mjs +3 -0
  555. package/templates/react-monorepo/files/packages/types/openapi-ts.config.ts +22 -0
  556. package/templates/react-monorepo/files/packages/types/package.json +29 -0
  557. package/templates/react-monorepo/files/packages/types/src/index.ts +4 -0
  558. package/templates/react-monorepo/files/packages/types/src/types/api/index.ts +9 -0
  559. package/templates/react-monorepo/files/packages/types/src/types/api/zod.gen.ts +5 -0
  560. package/templates/react-monorepo/files/packages/types/tsconfig.json +7 -0
  561. package/templates/react-monorepo/files/packages/ui/components.json +21 -0
  562. package/templates/react-monorepo/files/packages/ui/eslint.config.mjs +13 -0
  563. package/templates/react-monorepo/files/packages/ui/package.json +44 -0
  564. package/templates/react-monorepo/files/packages/ui/src/components/brand/logo.tsx +51 -0
  565. package/templates/react-monorepo/files/packages/ui/src/components/brand/social-icons.tsx +37 -0
  566. package/templates/react-monorepo/files/packages/ui/src/components/form/form.tsx +120 -0
  567. package/templates/react-monorepo/files/packages/ui/src/components/ui/alert.tsx +25 -0
  568. package/templates/react-monorepo/files/packages/ui/src/components/ui/button.tsx +43 -0
  569. package/templates/react-monorepo/files/packages/ui/src/components/ui/calendar.tsx +78 -0
  570. package/templates/react-monorepo/files/packages/ui/src/components/ui/card.tsx +44 -0
  571. package/templates/react-monorepo/files/packages/ui/src/components/ui/checkbox.tsx +16 -0
  572. package/templates/react-monorepo/files/packages/ui/src/components/ui/date-picker.tsx +76 -0
  573. package/templates/react-monorepo/files/packages/ui/src/components/ui/input.tsx +22 -0
  574. package/templates/react-monorepo/files/packages/ui/src/components/ui/label.tsx +19 -0
  575. package/templates/react-monorepo/files/packages/ui/src/components/ui/modal.tsx +94 -0
  576. package/templates/react-monorepo/files/packages/ui/src/components/ui/popover.tsx +31 -0
  577. package/templates/react-monorepo/files/packages/ui/src/components/ui/progress.tsx +33 -0
  578. package/templates/react-monorepo/files/packages/ui/src/components/ui/search-input.tsx +69 -0
  579. package/templates/react-monorepo/files/packages/ui/src/components/ui/select.tsx +80 -0
  580. package/templates/react-monorepo/files/packages/ui/src/components/ui/skeleton.tsx +12 -0
  581. package/templates/react-monorepo/files/packages/ui/src/components/ui/sonner.tsx +23 -0
  582. package/templates/react-monorepo/files/packages/ui/src/components/ui/spinner.tsx +8 -0
  583. package/templates/react-monorepo/files/packages/ui/src/components/ui/textarea.tsx +22 -0
  584. package/templates/react-monorepo/files/packages/ui/src/index.ts +45 -0
  585. package/templates/react-monorepo/files/packages/ui/src/lib/utils.ts +7 -0
  586. package/templates/react-monorepo/files/packages/ui/src/lib/zod-setup.ts +28 -0
  587. package/templates/react-monorepo/files/packages/ui/src/meta/brand.ts +18 -0
  588. package/templates/react-monorepo/files/packages/ui/src/meta/meta-context.ts +30 -0
  589. package/templates/react-monorepo/files/packages/ui/src/meta/meta-provider.tsx +24 -0
  590. package/templates/react-monorepo/files/packages/ui/src/meta/page-meta.tsx +69 -0
  591. package/templates/react-monorepo/files/packages/ui/src/meta/use-meta-config.ts +11 -0
  592. package/templates/react-monorepo/files/packages/ui/src/styles/globals.css +285 -0
  593. package/templates/react-monorepo/files/packages/ui/src/theme/init-script.ts +23 -0
  594. package/templates/react-monorepo/files/packages/ui/src/theme/theme-colors.ts +14 -0
  595. package/templates/react-monorepo/files/packages/ui/src/theme/theme-context.ts +60 -0
  596. package/templates/react-monorepo/files/packages/ui/src/theme/theme-provider.tsx +101 -0
  597. package/templates/react-monorepo/files/packages/ui/src/theme/theme-toggle.tsx +40 -0
  598. package/templates/react-monorepo/files/packages/ui/src/theme/use-theme.ts +11 -0
  599. package/templates/react-monorepo/files/packages/ui/tsconfig.json +9 -0
  600. package/templates/react-monorepo/files/turbo.json +24 -0
  601. package/templates/react-monorepo/template.json +230 -0
@@ -0,0 +1,26 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "compilerOptions": {
4
+ "target": "es2023",
5
+ "module": "esnext",
6
+ "moduleResolution": "bundler",
7
+ "lib": ["ES2023", "DOM", "DOM.Iterable"],
8
+ "jsx": "react-jsx",
9
+ "types": ["vite/client"],
10
+ "skipLibCheck": true,
11
+ "allowImportingTsExtensions": true,
12
+ "verbatimModuleSyntax": true,
13
+ "moduleDetection": "force",
14
+ "isolatedModules": true,
15
+ "noEmit": true,
16
+ "strict": true,
17
+ "noUnusedLocals": true,
18
+ "noUnusedParameters": true,
19
+ "noFallthroughCasesInSwitch": true,
20
+ "erasableSyntaxOnly": true,
21
+ "paths": {
22
+ "@/*": ["./src/*"]
23
+ }
24
+ },
25
+ "include": ["src"]
26
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "compilerOptions": {
4
+ "target": "es2023",
5
+ "module": "esnext",
6
+ "moduleResolution": "bundler",
7
+ // No DOM here, deliberately. This project covers code that runs in Node
8
+ // during the build; if `document` or `window` typechecks in a Vite plugin,
9
+ // the error only shows up when the build runs.
10
+ "lib": ["ES2023"],
11
+ "types": ["node"],
12
+ "skipLibCheck": true,
13
+ "allowImportingTsExtensions": true,
14
+ "verbatimModuleSyntax": true,
15
+ "moduleDetection": "force",
16
+ "isolatedModules": true,
17
+ "noEmit": true,
18
+ "strict": true,
19
+ "noUnusedLocals": true,
20
+ "noUnusedParameters": true,
21
+ "noFallthroughCasesInSwitch": true,
22
+ "erasableSyntaxOnly": true
23
+ },
24
+ "include": ["vite.config.ts", "openapi-ts.config.ts"]
25
+ }
@@ -0,0 +1,344 @@
1
+ import { defineConfig, loadEnv, type Plugin } from 'vite';
2
+ import react from '@vitejs/plugin-react';
3
+ import tailwindcss from '@tailwindcss/vite';
4
+ import path from 'node:path';
5
+ import { VitePWA } from 'vite-plugin-pwa'; // @feature pwa
6
+ import { BRAND } from './src/shared/ui/meta/brand';
7
+ import { THEME_COLORS } from './src/shared/ui/theme/theme-colors';
8
+ // @feature:start marketing
9
+ import { PRODUCTION_ORIGIN, SEO_ROUTES, absoluteUrl, normalizeOrigin } from './src/features/seo/routes';
10
+ // @feature:end
11
+
12
+ /**
13
+ * Opens the connection to the API origin while the HTML is still parsing.
14
+ *
15
+ * The app's first act is a Better Auth session request, and the API is a
16
+ * different origin, so that request pays DNS + TCP + TLS before it can even be
17
+ * sent. Measured against a deployed API: ~420 ms of an ~880 ms `get-session` was
18
+ * connection setup. Preconnecting overlaps it with the bundle download instead
19
+ * of paying it afterwards.
20
+ *
21
+ * `crossorigin` is load-bearing, not decoration. Better Auth and RTK Query both
22
+ * send the session cookie (`credentials: 'include'`), and a credentialed request
23
+ * will not reuse an anonymous socket — omit it and the browser opens a second
24
+ * connection, making the preconnect pure waste. It must also stay a *preconnect*
25
+ * and never become a `preload`: the session response is user-specific and must
26
+ * not be speculatively fetched.
27
+ *
28
+ * Injected here rather than in `index.html` because `VITE_APP_API_URL` is only
29
+ * known to the build, and HTML can't read env.
30
+ */
31
+ function apiPreconnect(apiUrl: string): Plugin {
32
+ let origin = '';
33
+ try {
34
+ origin = apiUrl ? new URL(apiUrl).origin : '';
35
+ } catch {
36
+ /* malformed VITE_APP_API_URL — skip rather than emit a broken tag */
37
+ }
38
+ return {
39
+ name: 'app:api-preconnect',
40
+ transformIndexHtml: {
41
+ order: 'pre',
42
+ handler: () =>
43
+ origin
44
+ ? [
45
+ {
46
+ tag: 'link',
47
+ attrs: { rel: 'preconnect', href: origin, crossorigin: true },
48
+ injectTo: 'head-prepend' as const
49
+ }
50
+ ]
51
+ : []
52
+ }
53
+ };
54
+ }
55
+
56
+ /**
57
+ * Substitutes `%THEME_LIGHT%` / `%THEME_DARK%` / `%APP_TITLE%` in `index.html`.
58
+ *
59
+ * The `<head>` needs the theme background twice over — the pre-paint script that
60
+ * sets the `dark` class before first paint, and the `html` background that stops
61
+ * a white flash on a dark load — and HTML cannot import. The static `<title>` is
62
+ * the same story: it must match the suffix `MetaProvider` appends at runtime, so
63
+ * it comes from `BRAND` rather than being typed out a second time.
64
+ *
65
+ * Runs for `vite dev` as well as the build.
66
+ */
67
+ function injectHtmlConstants(): Plugin {
68
+ return {
69
+ name: 'app:inject-html-constants',
70
+ transformIndexHtml: (html) =>
71
+ html
72
+ .replaceAll('%THEME_LIGHT%', THEME_COLORS.light)
73
+ .replaceAll('%THEME_DARK%', THEME_COLORS.dark)
74
+ .replaceAll('%APP_TITLE%', BRAND.name)
75
+ };
76
+ }
77
+
78
+ // @feature:start marketing
79
+ /**
80
+ * Emits `robots.txt` and `sitemap.xml` at build time from `SEO_ROUTES`.
81
+ *
82
+ * Generated rather than committed to `public/` so the sitemap cannot drift from
83
+ * the routes that actually exist. A sitemap advertising a 404, or missing a real
84
+ * page, is the usual failure here and it stays invisible until a crawler finds
85
+ * it.
86
+ *
87
+ * `apply: 'build'` — `public/` isn't written in dev and the dev server has no
88
+ * use for either file.
89
+ */
90
+ function seoFiles(origin: string, indexable: boolean): Plugin {
91
+ return {
92
+ name: 'app:seo-files',
93
+ apply: 'build',
94
+ generateBundle() {
95
+ // Non-production gets the same file inverted: serving production's copy
96
+ // from a preview host is duplicate content, and it must not advertise a
97
+ // sitemap it doesn't want crawled.
98
+ const robots = (
99
+ indexable
100
+ ? [
101
+ '# Public pages — crawling is welcome.',
102
+ '# The authenticated app and the auth screens are noindex; see index.html.',
103
+ 'User-agent: *',
104
+ 'Allow: /',
105
+ ...(origin ? ['', `Sitemap: ${origin}/sitemap.xml`] : []),
106
+ ''
107
+ ]
108
+ : [
109
+ `# Not production (origin: ${origin || 'unset'}). Only ${PRODUCTION_ORIGIN} should be indexed.`,
110
+ '# Paired with the noindex meta tag below — robots.txt alone does not deindex.',
111
+ 'User-agent: *',
112
+ 'Disallow: /',
113
+ ''
114
+ ]
115
+ ).join('\n');
116
+ this.emitFile({ type: 'asset', fileName: 'robots.txt', source: robots });
117
+
118
+ // Every <loc> must be absolute per the sitemap spec, so without an origin
119
+ // emit nothing rather than something invalid. robots.txt above then also
120
+ // omits its Sitemap line, keeping the two consistent.
121
+ if (!origin) {
122
+ this.warn('VITE_APP_SITE_URL is not set — skipping sitemap.xml, which requires absolute URLs.');
123
+ return;
124
+ }
125
+
126
+ const urls = SEO_ROUTES.map(
127
+ (route) =>
128
+ '\t<url>\n' +
129
+ `\t\t<loc>${absoluteUrl(route.path, origin)}</loc>\n` +
130
+ `\t\t<changefreq>${route.changefreq}</changefreq>\n` +
131
+ `\t\t<priority>${route.priority}</priority>\n` +
132
+ '\t</url>'
133
+ ).join('\n');
134
+
135
+ this.emitFile({
136
+ type: 'asset',
137
+ fileName: 'sitemap.xml',
138
+ source:
139
+ '<?xml version="1.0" encoding="UTF-8"?>\n' +
140
+ '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n' +
141
+ `${urls}\n` +
142
+ '</urlset>\n'
143
+ });
144
+ }
145
+ };
146
+ }
147
+
148
+ /**
149
+ * When the security policy expires, as an RFC 9116 `Expires:` field must. A date
150
+ * in the past makes the whole file invalid to the tools that read it, so this
151
+ * needs bumping — along with a review of the policy itself — before it lapses.
152
+ */
153
+ const SECURITY_TXT_EXPIRES = '2027-09-01T00:00:00.000Z';
154
+
155
+ /**
156
+ * Emits `/.well-known/security.txt` (RFC 9116).
157
+ *
158
+ * Researchers and automated scanners look for this file, not for a footer link.
159
+ * Production-only, unlike `robots.txt`: `Canonical:` must be the URL the file is
160
+ * actually served from, so a preview environment publishing one that claims the
161
+ * production origin would be advertising a false record rather than a harmless
162
+ * duplicate. An unset support address skips the file entirely — a security.txt
163
+ * pointing at an unmonitored mailbox is worse than none.
164
+ *
165
+ * `docker/nginx.conf` needs its `^~ /.well-known/` block for this to be
166
+ * reachable at all; the dotfile deny would otherwise 403 it.
167
+ */
168
+ function securityTxt(origin: string, indexable: boolean, securityEmail: string): Plugin {
169
+ return {
170
+ name: 'app:security-txt',
171
+ apply: 'build',
172
+ generateBundle() {
173
+ if (!indexable || !origin || !securityEmail) return;
174
+ this.emitFile({
175
+ type: 'asset',
176
+ fileName: '.well-known/security.txt',
177
+ source: [
178
+ `# ${BRAND.name} — Security & Responsible Disclosure`,
179
+ '',
180
+ `Contact: mailto:${securityEmail}`,
181
+ `Expires: ${SECURITY_TXT_EXPIRES}`,
182
+ 'Preferred-Languages: en',
183
+ `Canonical: ${origin}/.well-known/security.txt`,
184
+ ''
185
+ ].join('\n')
186
+ });
187
+ }
188
+ };
189
+ }
190
+
191
+ /**
192
+ * Injects `noindex, nofollow` into `index.html` on every non-production build.
193
+ *
194
+ * The meta tag is the half that actually deindexes — `robots.txt` only asks a
195
+ * crawler not to fetch, and a URL it already knows can still be listed without
196
+ * ever being fetched. Both halves are emitted together, from the same flag.
197
+ */
198
+ function noindexOffProduction(indexable: boolean): Plugin {
199
+ return {
200
+ name: 'app:noindex-off-production',
201
+ apply: 'build',
202
+ transformIndexHtml() {
203
+ if (indexable) return;
204
+ return [{ tag: 'meta', attrs: { name: 'robots', content: 'noindex, nofollow' }, injectTo: 'head' as const }];
205
+ }
206
+ };
207
+ }
208
+ // @feature:end
209
+
210
+ // `loadEnv` rather than `process.env`: VITE_APP_* live in `.env`, not the shell,
211
+ // so the build would otherwise never see them.
212
+ export default defineConfig(({ mode }) => {
213
+ const env = loadEnv(mode, import.meta.dirname, '');
214
+ const hosts = env.VITE_APP_ALLOWED_HOSTS;
215
+ // @feature:start marketing
216
+ const siteOrigin = normalizeOrigin(env.VITE_APP_SITE_URL ?? '');
217
+ // An unset or unrecognised origin counts as non-production — see PRODUCTION_ORIGIN.
218
+ const indexable = siteOrigin === PRODUCTION_ORIGIN;
219
+ // @feature:end
220
+
221
+ return {
222
+ plugins: [
223
+ react(),
224
+ tailwindcss(),
225
+ apiPreconnect(env.VITE_APP_API_URL),
226
+ injectHtmlConstants(),
227
+ // @feature:start marketing
228
+ seoFiles(siteOrigin, indexable),
229
+ securityTxt(siteOrigin, indexable, env.VITE_APP_SUPPORT_EMAIL ?? ''),
230
+ noindexOffProduction(indexable),
231
+ // @feature:end
232
+ // @feature:start pwa
233
+ VitePWA({
234
+ // 'prompt', not 'autoUpdate': a new build waits until the user accepts
235
+ // it. Taking over mid-session swaps the asset manifest under a running
236
+ // app, so the next lazy route resolves to a chunk that no longer exists.
237
+ registerType: 'prompt',
238
+ injectRegister: 'auto',
239
+ // No `includeAssets`. It adds files to the precache manifest that the
240
+ // icon globs already matched, which is how icons end up listed twice.
241
+ //
242
+ // `includeManifestIcons: false` for the same reason: install icons are
243
+ // fetched by the OS at install time and play no part in rendering the
244
+ // shell offline, so precaching them just re-downloads them per deploy.
245
+ includeManifestIcons: false,
246
+ devOptions: {
247
+ enabled: true,
248
+ type: 'module',
249
+ suppressWarnings: true
250
+ },
251
+ manifest: {
252
+ id: '/',
253
+ name: BRAND.name,
254
+ // short_name is what shows under the home-screen icon.
255
+ short_name: BRAND.name,
256
+ description: 'Acme Corp.',
257
+ start_url: '/',
258
+ scope: '/',
259
+ display: 'standalone',
260
+ theme_color: THEME_COLORS.light,
261
+ background_color: THEME_COLORS.light,
262
+ icons: [
263
+ { src: '/android-chrome-192x192.png', sizes: '192x192', type: 'image/png', purpose: 'any' },
264
+ { src: '/android-chrome-512x512.png', sizes: '512x512', type: 'image/png', purpose: 'any' },
265
+ { src: '/maskable-icon-192x192.png', sizes: '192x192', type: 'image/png', purpose: 'maskable' },
266
+ { src: '/maskable-icon-512x512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' }
267
+ ]
268
+ },
269
+ workbox: {
270
+ /*
271
+ * Precache = what's needed to boot the shell offline, and nothing
272
+ * else. Every entry is re-downloaded whenever its hash changes, so
273
+ * this list is a recurring cost on every deploy, not a one-off.
274
+ *
275
+ * `png`/`ico` are deliberately excluded: the only images in the build
276
+ * are launch/app icons, which the OS and browser fetch themselves and
277
+ * keep in the HTTP cache. `svg` stays — anything that reaches
278
+ * `assets/` came from `src` and is therefore shell code.
279
+ *
280
+ * Big lazy-loaded vendor chunks (a charting library, an editor) do not
281
+ * belong here either; the runtime rule below covers them, so they work
282
+ * offline from second use rather than before first use.
283
+ */
284
+ globPatterns: ['**/*.{js,css,html,svg,woff,woff2}'],
285
+ navigateFallback: '/index.html',
286
+ cleanupOutdatedCaches: true,
287
+ runtimeCaching: [
288
+ {
289
+ /*
290
+ * Anything hashed that isn't precached. Safe as CacheFirst
291
+ * precisely because the filenames are content-hashed: a changed
292
+ * file is a new URL, so a stale entry is unreachable rather
293
+ * than wrong.
294
+ */
295
+ urlPattern: ({ sameOrigin, url }) => sameOrigin && url.pathname.startsWith('/assets/'),
296
+ handler: 'CacheFirst',
297
+ options: {
298
+ cacheName: 'acme-assets',
299
+ expiration: { maxEntries: 60, maxAgeSeconds: 60 * 60 * 24 * 30 },
300
+ cacheableResponse: { statuses: [0, 200] }
301
+ }
302
+ },
303
+ {
304
+ /*
305
+ * Remote images — user-uploaded avatars and the like. Matched by
306
+ * request destination rather than hostname so it doesn't hardcode
307
+ * a media origin, and bounded so an opaque cross-origin response
308
+ * (which counts fully against quota) can't grow without limit.
309
+ */
310
+ urlPattern: ({ request, sameOrigin }) => !sameOrigin && request.destination === 'image',
311
+ handler: 'StaleWhileRevalidate',
312
+ options: {
313
+ cacheName: 'acme-remote-images',
314
+ expiration: { maxEntries: 80, maxAgeSeconds: 60 * 60 * 24 * 7 },
315
+ cacheableResponse: { statuses: [0, 200] }
316
+ }
317
+ }
318
+ /*
319
+ * No rule for the API, on purpose. Decide deliberately before
320
+ * adding one: a stale response is worse than no response for
321
+ * anything the user acts on, and offline degrading to "no data" is
322
+ * usually the correct behaviour.
323
+ *
324
+ * Fonts need no rule either: they're self-hosted and same-origin,
325
+ * so they're precached above, which is strictly better.
326
+ */
327
+ ]
328
+ }
329
+ })
330
+ // @feature:end
331
+ ],
332
+ server: {
333
+ host: true,
334
+ port: env.PORT ? Number(env.PORT) : undefined,
335
+ strictPort: true,
336
+ allowedHosts: hosts ? hosts.split(',').map((h) => h.trim()) : []
337
+ },
338
+ resolve: {
339
+ alias: {
340
+ '@': path.resolve(import.meta.dirname, './src')
341
+ }
342
+ }
343
+ };
344
+ });
@@ -0,0 +1,93 @@
1
+ import { useState } from 'react';
2
+ import { Form, Formik } from 'formik';
3
+ import { Link, useNavigate } from 'react-router';
4
+ import { toFormikValidationSchema } from 'zod-formik-adapter';
5
+ import { AuthLayout } from '@/shared/layouts';
6
+ import { Alert, Button, FormField } from '@/shared/ui';
7
+ import { AuthCard } from '@/features/auth/components/auth-card';
8
+ import { SubmitButton } from '@/features/auth/components/submit-button';
9
+ import { requestPasswordReset } from '@/features/auth/lib/auth-actions';
10
+ import { forgotSchema } from '@/features/auth/lib/schemas';
11
+ import { APP_ORIGIN } from '@/lib/env';
12
+
13
+ export function ForgotPasswordRoute() {
14
+ const navigate = useNavigate();
15
+ const [error, setError] = useState<string | null>(null);
16
+ const [sentTo, setSentTo] = useState<string | null>(null);
17
+
18
+ return (
19
+ <AuthLayout>
20
+ <AuthCard
21
+ title="Reset your password"
22
+ footer={
23
+ <Link to="/login" className="font-semibold text-ink-deep">
24
+ ← Back to log in
25
+ </Link>
26
+ }
27
+ >
28
+ {sentTo ? (
29
+ <div className="flex flex-col gap-4">
30
+ <div className="flex items-start gap-3 rounded-2xl bg-accent p-4">
31
+ <span className="flex size-6 shrink-0 items-center justify-center rounded-full bg-primary text-sm font-bold text-primary-foreground">
32
+ ✓
33
+ </span>
34
+ <div>
35
+ <p className="text-sm font-semibold text-foreground">Reset link sent</p>
36
+ <p className="mt-0.5 text-sm text-body">
37
+ If <strong className="font-semibold">{sentTo}</strong> has an account, a link is on its way. It
38
+ expires in 30 minutes.
39
+ </p>
40
+ </div>
41
+ </div>
42
+ <Button variant="outline" className="w-full" onClick={() => navigate('/reset-password')}>
43
+ I have the link — set a new password
44
+ </Button>
45
+ </div>
46
+ ) : (
47
+ <>
48
+ {error ? (
49
+ <Alert variant="destructive" className="mb-4">
50
+ {error}
51
+ </Alert>
52
+ ) : null}
53
+ <p className="mb-4 text-sm text-body">
54
+ Enter the email you signed up with and we'll send you a reset link.
55
+ </p>
56
+ <Formik
57
+ initialValues={{ email: '' }}
58
+ validationSchema={toFormikValidationSchema(forgotSchema)}
59
+ onSubmit={async (values, helpers) => {
60
+ setError(null);
61
+ const { error: err } = await requestPasswordReset({
62
+ email: values.email,
63
+ // Absolute: this lands in an email, where a path has nothing
64
+ // to resolve against.
65
+ redirectTo: `${APP_ORIGIN}/reset-password`
66
+ });
67
+ helpers.setSubmitting(false);
68
+ if (err) {
69
+ setError(err);
70
+ return;
71
+ }
72
+ setSentTo(values.email);
73
+ }}
74
+ >
75
+ {({ isSubmitting }) => (
76
+ <Form className="flex flex-col gap-4">
77
+ <FormField
78
+ name="email"
79
+ label="Email"
80
+ type="email"
81
+ placeholder="you@example.com"
82
+ autoComplete="email"
83
+ />
84
+ <SubmitButton loading={isSubmitting}>Send reset link</SubmitButton>
85
+ </Form>
86
+ )}
87
+ </Formik>
88
+ </>
89
+ )}
90
+ </AuthCard>
91
+ </AuthLayout>
92
+ );
93
+ }
@@ -0,0 +1,87 @@
1
+ import { useState } from 'react';
2
+ import { Form, Formik } from 'formik';
3
+ import { Link, useSearchParams } from 'react-router';
4
+ import { toFormikValidationSchema } from 'zod-formik-adapter';
5
+ import { getSafeRedirect } from '@/shared/auth';
6
+ import { AuthLayout } from '@/shared/layouts';
7
+ import { Alert, FormField } from '@/shared/ui';
8
+ import { AuthCard } from '@/features/auth/components/auth-card';
9
+ import { CheckboxField } from '@/features/auth/components/checkbox-field';
10
+ import { GoogleButton } from '@/features/auth/components/google-button';
11
+ import { OrDivider } from '@/features/auth/components/or-divider';
12
+ import { PasswordField } from '@/features/auth/components/password-field';
13
+ import { SubmitButton } from '@/features/auth/components/submit-button';
14
+ import { loginWithEmail, signInWithGoogle } from '@/features/auth/lib/auth-actions';
15
+ import { withRedirect } from '@/features/auth/lib/redirect';
16
+ import { loginSchema } from '@/features/auth/lib/schemas';
17
+
18
+ export function LoginRoute() {
19
+ const [params] = useSearchParams();
20
+ const redirect = params.get('redirect');
21
+ const [error, setError] = useState<string | null>(null);
22
+ // No explicit fallback: `configureAuth({ defaultRedirect })` in app/providers
23
+ // already knows where the app lives, and duplicating it here is how the two
24
+ // drift when the app moves under a different base path.
25
+ const target = () => getSafeRedirect(redirect);
26
+
27
+ return (
28
+ <AuthLayout>
29
+ <AuthCard
30
+ title="Welcome back"
31
+ description="Log in to pick up where you left off."
32
+ footer={
33
+ <>
34
+ New here?{' '}
35
+ <Link to={withRedirect('/signup', redirect)} className="font-semibold text-ink-deep">
36
+ Create a free account
37
+ </Link>
38
+ </>
39
+ }
40
+ >
41
+ {error ? (
42
+ <Alert variant="destructive" className="mb-4">
43
+ {error}
44
+ </Alert>
45
+ ) : null}
46
+ <Formik
47
+ initialValues={{ email: '', password: '', remember: true }}
48
+ validationSchema={toFormikValidationSchema(loginSchema)}
49
+ onSubmit={async (values, helpers) => {
50
+ setError(null);
51
+ const { error: err } = await loginWithEmail(values);
52
+ helpers.setSubmitting(false);
53
+ if (err) {
54
+ setError(err);
55
+ return;
56
+ }
57
+ // A full load rather than `navigate()`: `getSafeRedirect` returns an
58
+ // absolute URL (it has to, to be checked against an origin
59
+ // allowlist), and it also re-bootstraps the session cleanly.
60
+ window.location.assign(target());
61
+ }}
62
+ >
63
+ {({ isSubmitting }) => (
64
+ <Form className="flex flex-col gap-4">
65
+ <FormField name="email" label="Email" type="email" placeholder="you@example.com" autoComplete="email" />
66
+ <PasswordField
67
+ name="password"
68
+ label="Password"
69
+ placeholder="Your password"
70
+ autoComplete="current-password"
71
+ action={
72
+ <Link to="/forgot-password" className="text-xs font-semibold text-ink-deep">
73
+ Forgot password?
74
+ </Link>
75
+ }
76
+ />
77
+ <CheckboxField name="remember" label="Remember me on this device" />
78
+ <SubmitButton loading={isSubmitting}>Log in</SubmitButton>
79
+ <OrDivider />
80
+ <GoogleButton onClick={() => void signInWithGoogle({ callbackURL: target() })} disabled={isSubmitting} />
81
+ </Form>
82
+ )}
83
+ </Formik>
84
+ </AuthCard>
85
+ </AuthLayout>
86
+ );
87
+ }