create-blitzpack 0.1.0 → 0.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 (259) hide show
  1. package/dist/index.js +35 -77
  2. package/package.json +5 -6
  3. package/template/.dockerignore +0 -59
  4. package/template/.github/workflows/ci.yml +0 -157
  5. package/template/.husky/pre-commit +0 -1
  6. package/template/.husky/pre-push +0 -1
  7. package/template/.lintstagedrc.cjs +0 -4
  8. package/template/.nvmrc +0 -1
  9. package/template/.prettierrc +0 -9
  10. package/template/.vscode/settings.json +0 -13
  11. package/template/CLAUDE.md +0 -175
  12. package/template/CONTRIBUTING.md +0 -32
  13. package/template/Dockerfile +0 -90
  14. package/template/GETTING_STARTED.md +0 -35
  15. package/template/LICENSE +0 -21
  16. package/template/README.md +0 -116
  17. package/template/apps/api/.dockerignore +0 -51
  18. package/template/apps/api/.env.local.example +0 -62
  19. package/template/apps/api/emails/account-deleted-email.tsx +0 -69
  20. package/template/apps/api/emails/components/email-layout.tsx +0 -154
  21. package/template/apps/api/emails/config.ts +0 -22
  22. package/template/apps/api/emails/password-changed-email.tsx +0 -88
  23. package/template/apps/api/emails/password-reset-email.tsx +0 -86
  24. package/template/apps/api/emails/verification-email.tsx +0 -85
  25. package/template/apps/api/emails/welcome-email.tsx +0 -70
  26. package/template/apps/api/package.json +0 -84
  27. package/template/apps/api/prisma/migrations/20251012111439_init/migration.sql +0 -13
  28. package/template/apps/api/prisma/migrations/20251018162629_add_better_auth_fields/migration.sql +0 -67
  29. package/template/apps/api/prisma/migrations/20251019142208_add_user_role_enum/migration.sql +0 -5
  30. package/template/apps/api/prisma/migrations/20251019182151_user_auth/migration.sql +0 -7
  31. package/template/apps/api/prisma/migrations/20251019211416_faster_session_lookup/migration.sql +0 -2
  32. package/template/apps/api/prisma/migrations/20251119124337_add_upload_model/migration.sql +0 -26
  33. package/template/apps/api/prisma/migrations/20251120071241_add_scope_to_account/migration.sql +0 -2
  34. package/template/apps/api/prisma/migrations/20251120072608_add_oauth_token_expiration_fields/migration.sql +0 -10
  35. package/template/apps/api/prisma/migrations/20251120144705_add_audit_logs/migration.sql +0 -29
  36. package/template/apps/api/prisma/migrations/20251127123614_remove_impersonated_by/migration.sql +0 -8
  37. package/template/apps/api/prisma/migrations/20251127125630_remove_audit_logs/migration.sql +0 -11
  38. package/template/apps/api/prisma/migrations/migration_lock.toml +0 -3
  39. package/template/apps/api/prisma/schema.prisma +0 -116
  40. package/template/apps/api/prisma/seed.ts +0 -159
  41. package/template/apps/api/prisma.config.ts +0 -14
  42. package/template/apps/api/src/app.ts +0 -377
  43. package/template/apps/api/src/common/logger.service.ts +0 -227
  44. package/template/apps/api/src/config/env.ts +0 -60
  45. package/template/apps/api/src/config/rate-limit.ts +0 -29
  46. package/template/apps/api/src/hooks/auth.ts +0 -122
  47. package/template/apps/api/src/plugins/auth.ts +0 -198
  48. package/template/apps/api/src/plugins/database.ts +0 -45
  49. package/template/apps/api/src/plugins/logger.ts +0 -33
  50. package/template/apps/api/src/plugins/multipart.ts +0 -16
  51. package/template/apps/api/src/plugins/scalar.ts +0 -20
  52. package/template/apps/api/src/plugins/schedule.ts +0 -52
  53. package/template/apps/api/src/plugins/services.ts +0 -66
  54. package/template/apps/api/src/plugins/swagger.ts +0 -56
  55. package/template/apps/api/src/routes/accounts.ts +0 -91
  56. package/template/apps/api/src/routes/admin-sessions.ts +0 -92
  57. package/template/apps/api/src/routes/metrics.ts +0 -71
  58. package/template/apps/api/src/routes/password.ts +0 -46
  59. package/template/apps/api/src/routes/sessions.ts +0 -53
  60. package/template/apps/api/src/routes/stats.ts +0 -38
  61. package/template/apps/api/src/routes/uploads-serve.ts +0 -27
  62. package/template/apps/api/src/routes/uploads.ts +0 -154
  63. package/template/apps/api/src/routes/users.ts +0 -114
  64. package/template/apps/api/src/routes/verification.ts +0 -90
  65. package/template/apps/api/src/server.ts +0 -34
  66. package/template/apps/api/src/services/accounts.service.ts +0 -125
  67. package/template/apps/api/src/services/authorization.service.ts +0 -162
  68. package/template/apps/api/src/services/email.service.ts +0 -170
  69. package/template/apps/api/src/services/file-storage.service.ts +0 -267
  70. package/template/apps/api/src/services/metrics.service.ts +0 -175
  71. package/template/apps/api/src/services/password.service.ts +0 -56
  72. package/template/apps/api/src/services/sessions.service.spec.ts +0 -134
  73. package/template/apps/api/src/services/sessions.service.ts +0 -276
  74. package/template/apps/api/src/services/stats.service.ts +0 -273
  75. package/template/apps/api/src/services/uploads.service.ts +0 -163
  76. package/template/apps/api/src/services/users.service.spec.ts +0 -249
  77. package/template/apps/api/src/services/users.service.ts +0 -198
  78. package/template/apps/api/src/utils/file-validation.ts +0 -108
  79. package/template/apps/api/start.sh +0 -33
  80. package/template/apps/api/test/helpers/fastify-app.ts +0 -24
  81. package/template/apps/api/test/helpers/mock-authorization.ts +0 -16
  82. package/template/apps/api/test/helpers/mock-logger.ts +0 -28
  83. package/template/apps/api/test/helpers/mock-prisma.ts +0 -30
  84. package/template/apps/api/test/helpers/test-db.ts +0 -125
  85. package/template/apps/api/test/integration/auth-flow.integration.spec.ts +0 -449
  86. package/template/apps/api/test/integration/password.integration.spec.ts +0 -427
  87. package/template/apps/api/test/integration/rate-limit.integration.spec.ts +0 -51
  88. package/template/apps/api/test/integration/sessions.integration.spec.ts +0 -445
  89. package/template/apps/api/test/integration/users.integration.spec.ts +0 -211
  90. package/template/apps/api/test/setup.ts +0 -31
  91. package/template/apps/api/tsconfig.json +0 -26
  92. package/template/apps/api/vitest.config.ts +0 -35
  93. package/template/apps/web/.env.local.example +0 -11
  94. package/template/apps/web/components.json +0 -24
  95. package/template/apps/web/next.config.ts +0 -22
  96. package/template/apps/web/package.json +0 -56
  97. package/template/apps/web/postcss.config.js +0 -5
  98. package/template/apps/web/public/apple-icon.png +0 -0
  99. package/template/apps/web/public/icon.png +0 -0
  100. package/template/apps/web/public/robots.txt +0 -3
  101. package/template/apps/web/src/app/(admin)/admin/layout.tsx +0 -222
  102. package/template/apps/web/src/app/(admin)/admin/page.tsx +0 -157
  103. package/template/apps/web/src/app/(admin)/admin/sessions/page.tsx +0 -18
  104. package/template/apps/web/src/app/(admin)/admin/users/page.tsx +0 -20
  105. package/template/apps/web/src/app/(auth)/forgot-password/page.tsx +0 -177
  106. package/template/apps/web/src/app/(auth)/login/page.tsx +0 -159
  107. package/template/apps/web/src/app/(auth)/reset-password/page.tsx +0 -245
  108. package/template/apps/web/src/app/(auth)/signup/page.tsx +0 -153
  109. package/template/apps/web/src/app/dashboard/change-password/page.tsx +0 -255
  110. package/template/apps/web/src/app/dashboard/page.tsx +0 -296
  111. package/template/apps/web/src/app/error.tsx +0 -32
  112. package/template/apps/web/src/app/examples/file-upload/page.tsx +0 -200
  113. package/template/apps/web/src/app/favicon.ico +0 -0
  114. package/template/apps/web/src/app/global-error.tsx +0 -96
  115. package/template/apps/web/src/app/globals.css +0 -22
  116. package/template/apps/web/src/app/icon.png +0 -0
  117. package/template/apps/web/src/app/layout.tsx +0 -34
  118. package/template/apps/web/src/app/not-found.tsx +0 -28
  119. package/template/apps/web/src/app/page.tsx +0 -192
  120. package/template/apps/web/src/components/admin/activity-feed.tsx +0 -101
  121. package/template/apps/web/src/components/admin/charts/auth-breakdown-chart.tsx +0 -114
  122. package/template/apps/web/src/components/admin/charts/chart-tooltip.tsx +0 -124
  123. package/template/apps/web/src/components/admin/charts/realtime-metrics-chart.tsx +0 -511
  124. package/template/apps/web/src/components/admin/charts/role-distribution-chart.tsx +0 -102
  125. package/template/apps/web/src/components/admin/charts/session-activity-chart.tsx +0 -90
  126. package/template/apps/web/src/components/admin/charts/user-growth-chart.tsx +0 -108
  127. package/template/apps/web/src/components/admin/health-indicator.tsx +0 -175
  128. package/template/apps/web/src/components/admin/refresh-control.tsx +0 -90
  129. package/template/apps/web/src/components/admin/session-revoke-all-dialog.tsx +0 -79
  130. package/template/apps/web/src/components/admin/session-revoke-dialog.tsx +0 -74
  131. package/template/apps/web/src/components/admin/sessions-management-table.tsx +0 -372
  132. package/template/apps/web/src/components/admin/stat-card.tsx +0 -137
  133. package/template/apps/web/src/components/admin/user-create-dialog.tsx +0 -152
  134. package/template/apps/web/src/components/admin/user-delete-dialog.tsx +0 -73
  135. package/template/apps/web/src/components/admin/user-edit-dialog.tsx +0 -170
  136. package/template/apps/web/src/components/admin/users-management-table.tsx +0 -285
  137. package/template/apps/web/src/components/auth/email-verification-banner.tsx +0 -85
  138. package/template/apps/web/src/components/auth/github-button.tsx +0 -40
  139. package/template/apps/web/src/components/auth/google-button.tsx +0 -54
  140. package/template/apps/web/src/components/auth/protected-route.tsx +0 -66
  141. package/template/apps/web/src/components/auth/redirect-if-authenticated.tsx +0 -31
  142. package/template/apps/web/src/components/auth/with-auth.tsx +0 -30
  143. package/template/apps/web/src/components/error/error-card.tsx +0 -47
  144. package/template/apps/web/src/components/error/forbidden.tsx +0 -25
  145. package/template/apps/web/src/components/landing/command-block.tsx +0 -64
  146. package/template/apps/web/src/components/landing/feature-card.tsx +0 -60
  147. package/template/apps/web/src/components/landing/included-feature-card.tsx +0 -63
  148. package/template/apps/web/src/components/landing/logo.tsx +0 -41
  149. package/template/apps/web/src/components/landing/tech-badge.tsx +0 -11
  150. package/template/apps/web/src/components/layout/auth-nav.tsx +0 -58
  151. package/template/apps/web/src/components/layout/footer.tsx +0 -3
  152. package/template/apps/web/src/config/landing-data.ts +0 -152
  153. package/template/apps/web/src/config/site.ts +0 -5
  154. package/template/apps/web/src/hooks/api/__tests__/use-users.test.tsx +0 -181
  155. package/template/apps/web/src/hooks/api/use-admin-sessions.ts +0 -75
  156. package/template/apps/web/src/hooks/api/use-admin-stats.ts +0 -33
  157. package/template/apps/web/src/hooks/api/use-sessions.ts +0 -52
  158. package/template/apps/web/src/hooks/api/use-uploads.ts +0 -156
  159. package/template/apps/web/src/hooks/api/use-users.ts +0 -149
  160. package/template/apps/web/src/hooks/use-mobile.ts +0 -21
  161. package/template/apps/web/src/hooks/use-realtime-metrics.ts +0 -120
  162. package/template/apps/web/src/lib/__tests__/utils.test.ts +0 -29
  163. package/template/apps/web/src/lib/api.ts +0 -151
  164. package/template/apps/web/src/lib/auth.ts +0 -13
  165. package/template/apps/web/src/lib/env.ts +0 -52
  166. package/template/apps/web/src/lib/form-utils.ts +0 -11
  167. package/template/apps/web/src/lib/utils.ts +0 -1
  168. package/template/apps/web/src/providers.tsx +0 -34
  169. package/template/apps/web/src/store/atoms.ts +0 -15
  170. package/template/apps/web/src/test/helpers/test-utils.tsx +0 -44
  171. package/template/apps/web/src/test/setup.ts +0 -8
  172. package/template/apps/web/tailwind.config.ts +0 -5
  173. package/template/apps/web/tsconfig.json +0 -26
  174. package/template/apps/web/vitest.config.ts +0 -32
  175. package/template/assets/logo-512.png +0 -0
  176. package/template/assets/logo.svg +0 -4
  177. package/template/docker-compose.prod.yml +0 -66
  178. package/template/docker-compose.yml +0 -36
  179. package/template/eslint.config.ts +0 -119
  180. package/template/package.json +0 -77
  181. package/template/packages/tailwind-config/package.json +0 -9
  182. package/template/packages/tailwind-config/theme.css +0 -179
  183. package/template/packages/types/package.json +0 -29
  184. package/template/packages/types/src/__tests__/schemas.test.ts +0 -255
  185. package/template/packages/types/src/api-response.ts +0 -53
  186. package/template/packages/types/src/health-check.ts +0 -11
  187. package/template/packages/types/src/pagination.ts +0 -41
  188. package/template/packages/types/src/role.ts +0 -5
  189. package/template/packages/types/src/session.ts +0 -48
  190. package/template/packages/types/src/stats.ts +0 -113
  191. package/template/packages/types/src/upload.ts +0 -51
  192. package/template/packages/types/src/user.ts +0 -36
  193. package/template/packages/types/tsconfig.json +0 -5
  194. package/template/packages/types/vitest.config.ts +0 -21
  195. package/template/packages/ui/components.json +0 -21
  196. package/template/packages/ui/package.json +0 -108
  197. package/template/packages/ui/src/__tests__/button.test.tsx +0 -70
  198. package/template/packages/ui/src/alert-dialog.tsx +0 -141
  199. package/template/packages/ui/src/alert.tsx +0 -66
  200. package/template/packages/ui/src/animated-theme-toggler.tsx +0 -167
  201. package/template/packages/ui/src/avatar.tsx +0 -53
  202. package/template/packages/ui/src/badge.tsx +0 -36
  203. package/template/packages/ui/src/button.tsx +0 -84
  204. package/template/packages/ui/src/card.tsx +0 -92
  205. package/template/packages/ui/src/checkbox.tsx +0 -32
  206. package/template/packages/ui/src/data-table/data-table-column-header.tsx +0 -68
  207. package/template/packages/ui/src/data-table/data-table-pagination.tsx +0 -99
  208. package/template/packages/ui/src/data-table/data-table-toolbar.tsx +0 -55
  209. package/template/packages/ui/src/data-table/data-table-view-options.tsx +0 -63
  210. package/template/packages/ui/src/data-table/data-table.tsx +0 -167
  211. package/template/packages/ui/src/dialog.tsx +0 -143
  212. package/template/packages/ui/src/dropdown-menu.tsx +0 -257
  213. package/template/packages/ui/src/empty-state.tsx +0 -52
  214. package/template/packages/ui/src/file-upload-input.tsx +0 -202
  215. package/template/packages/ui/src/form.tsx +0 -168
  216. package/template/packages/ui/src/hooks/use-mobile.ts +0 -19
  217. package/template/packages/ui/src/icons/brand-icons.tsx +0 -16
  218. package/template/packages/ui/src/input.tsx +0 -21
  219. package/template/packages/ui/src/label.tsx +0 -24
  220. package/template/packages/ui/src/lib/utils.ts +0 -6
  221. package/template/packages/ui/src/password-input.tsx +0 -102
  222. package/template/packages/ui/src/popover.tsx +0 -48
  223. package/template/packages/ui/src/radio-group.tsx +0 -45
  224. package/template/packages/ui/src/scroll-area.tsx +0 -58
  225. package/template/packages/ui/src/select.tsx +0 -187
  226. package/template/packages/ui/src/separator.tsx +0 -28
  227. package/template/packages/ui/src/sheet.tsx +0 -139
  228. package/template/packages/ui/src/sidebar.tsx +0 -726
  229. package/template/packages/ui/src/skeleton-variants.tsx +0 -87
  230. package/template/packages/ui/src/skeleton.tsx +0 -13
  231. package/template/packages/ui/src/slider.tsx +0 -63
  232. package/template/packages/ui/src/sonner.tsx +0 -25
  233. package/template/packages/ui/src/spinner.tsx +0 -16
  234. package/template/packages/ui/src/switch.tsx +0 -31
  235. package/template/packages/ui/src/table.tsx +0 -116
  236. package/template/packages/ui/src/tabs.tsx +0 -66
  237. package/template/packages/ui/src/textarea.tsx +0 -18
  238. package/template/packages/ui/src/tooltip.tsx +0 -61
  239. package/template/packages/ui/src/user-avatar.tsx +0 -97
  240. package/template/packages/ui/test-config.js +0 -3
  241. package/template/packages/ui/tsconfig.json +0 -12
  242. package/template/packages/ui/turbo.json +0 -18
  243. package/template/packages/ui/vitest.config.ts +0 -17
  244. package/template/packages/ui/vitest.setup.ts +0 -1
  245. package/template/packages/utils/package.json +0 -23
  246. package/template/packages/utils/src/__tests__/utils.test.ts +0 -223
  247. package/template/packages/utils/src/array.ts +0 -18
  248. package/template/packages/utils/src/async.ts +0 -3
  249. package/template/packages/utils/src/date.ts +0 -77
  250. package/template/packages/utils/src/errors.ts +0 -73
  251. package/template/packages/utils/src/number.ts +0 -11
  252. package/template/packages/utils/src/string.ts +0 -13
  253. package/template/packages/utils/tsconfig.json +0 -5
  254. package/template/packages/utils/vitest.config.ts +0 -21
  255. package/template/pnpm-workspace.yaml +0 -4
  256. package/template/tsconfig.base.json +0 -32
  257. package/template/turbo.json +0 -133
  258. package/template/vitest.shared.ts +0 -26
  259. package/template/vitest.workspace.ts +0 -9
@@ -1,28 +0,0 @@
1
- 'use client';
2
-
3
- import { Button } from '@repo/packages-ui/button';
4
- import { FileQuestion } from 'lucide-react';
5
- import Link from 'next/link';
6
- import React from 'react';
7
-
8
- import { ErrorCard } from '@/components/error/error-card';
9
-
10
- export default function NotFound() {
11
- return (
12
- <ErrorCard
13
- icon={FileQuestion}
14
- title="Page not found"
15
- description="The page you're looking for doesn't exist or has been moved."
16
- actions={
17
- <>
18
- <Button variant="outline" onClick={() => window.history.back()}>
19
- Go back
20
- </Button>
21
- <Button asChild>
22
- <Link href="/">Go home</Link>
23
- </Button>
24
- </>
25
- }
26
- />
27
- );
28
- }
@@ -1,192 +0,0 @@
1
- import { AnimatedThemeToggler } from '@repo/packages-ui/animated-theme-toggler';
2
- import { Button } from '@repo/packages-ui/button';
3
- import { GitHubIcon } from '@repo/packages-ui/icons/brand-icons';
4
- import { ArrowRight, Boxes, PackageCheck, Terminal } from 'lucide-react';
5
- import Link from 'next/link';
6
- import React from 'react';
7
-
8
- import { CommandBlock } from '@/components/landing/command-block';
9
- import { FeatureCard } from '@/components/landing/feature-card';
10
- import { IncludedFeatureCard } from '@/components/landing/included-feature-card';
11
- import { Logo } from '@/components/landing/logo';
12
- import { TechBadge } from '@/components/landing/tech-badge';
13
- import {
14
- features,
15
- includedFeatures,
16
- quickStartCommands,
17
- techStack,
18
- } from '@/config/landing-data';
19
- import { siteConfig } from '@/config/site';
20
-
21
- export default async function Home(): Promise<React.ReactElement> {
22
- const apiUrl = process.env.NEXT_PUBLIC_API_URL || '';
23
- const isLocalDev =
24
- apiUrl.includes('localhost') || apiUrl.includes('127.0.0.1');
25
-
26
- const backendPort = new URL(apiUrl).port || '8080';
27
-
28
- return (
29
- <main className="bg-background relative flex flex-1 flex-col items-center justify-center p-8 pb-0">
30
- <div className="absolute right-8 top-8 flex items-center gap-2">
31
- <Button asChild variant="default">
32
- <Link href="/login">Sign In</Link>
33
- </Button>
34
- <AnimatedThemeToggler />
35
- </div>
36
- <div className="w-full max-w-5xl space-y-12">
37
- <div className="space-y-6 text-center">
38
- <div className="flex justify-center">
39
- <Logo className="h-20 w-auto" />
40
- </div>
41
- <div className="space-y-3">
42
- <h1 className="text-foreground text-5xl font-semibold tracking-tight">
43
- Ship production apps faster
44
- </h1>
45
- <p className="text-muted-foreground mx-auto max-w-2xl text-lg">
46
- Production-ready full-stack TypeScript monorepo with Next.js,
47
- Fastify, Turborepo and other modern technologies.
48
- </p>
49
- </div>
50
- <div className="flex flex-wrap items-center justify-center gap-3 pt-2">
51
- <Button
52
- asChild
53
- size="lg"
54
- className="group shadow-lg transition-all hover:scale-105 hover:shadow-xl"
55
- >
56
- <Link href="#quick-start" className="flex items-center gap-2">
57
- Quick Start
58
- <ArrowRight className="size-4 transition-transform group-hover:translate-x-1" />
59
- </Link>
60
- </Button>
61
- <Button
62
- asChild
63
- size="lg"
64
- variant="outline"
65
- className="group transition-all hover:scale-105"
66
- >
67
- <a
68
- href={siteConfig.github}
69
- target="_blank"
70
- rel="noopener noreferrer"
71
- className="flex items-center gap-2"
72
- >
73
- <GitHubIcon className="size-4" />
74
- GitHub
75
- </a>
76
- </Button>
77
- </div>
78
- </div>
79
-
80
- <div className="grid gap-6 md:grid-cols-3">
81
- {features.map((feature) => (
82
- <FeatureCard
83
- key={feature.title}
84
- iconName={feature.iconName}
85
- title={feature.title}
86
- description={feature.description}
87
- />
88
- ))}
89
- </div>
90
-
91
- <div className="border-border bg-card rounded-lg border p-8">
92
- <h2 className="text-card-foreground mb-8 flex items-center gap-2 text-xl font-medium">
93
- <PackageCheck className="text-foreground h-5 w-5" />
94
- <span>Out of the Box</span>
95
- </h2>
96
- <div className="grid gap-6 md:grid-cols-3">
97
- {includedFeatures.map((feature) => (
98
- <IncludedFeatureCard
99
- key={feature.title}
100
- iconName={feature.iconName}
101
- title={feature.title}
102
- pages={feature.pages}
103
- />
104
- ))}
105
- </div>
106
- </div>
107
-
108
- <div className="border-border bg-card rounded-lg border p-8">
109
- <h2 className="text-card-foreground mb-8 flex items-center gap-2 text-xl font-medium">
110
- <Boxes className="text-foreground h-5 w-5" />
111
- <span>Tech Stack</span>
112
- </h2>
113
- <div className="space-y-8">
114
- {Object.values(techStack).map((stack) => (
115
- <div key={stack.title}>
116
- <h3 className="text-card-foreground mb-4 text-sm font-medium">
117
- {stack.title}
118
- </h3>
119
- <div className="flex flex-wrap gap-2">
120
- {stack.items.map((item) => (
121
- <TechBadge key={item}>{item}</TechBadge>
122
- ))}
123
- </div>
124
- </div>
125
- ))}
126
- </div>
127
- </div>
128
-
129
- <div
130
- id="quick-start"
131
- className="border-border bg-card border-l-primary rounded-lg border border-l-8 p-8"
132
- >
133
- <div className="mb-6 flex items-center gap-3">
134
- <Terminal className="text-foreground h-5 w-5" />
135
- <h2 className="text-foreground text-xl font-medium">Quick Start</h2>
136
- </div>
137
- <div className="space-y-3">
138
- {quickStartCommands.map((cmd) => (
139
- <CommandBlock
140
- key={cmd.command}
141
- command={cmd.command}
142
- tooltipContent={cmd.tooltip}
143
- />
144
- ))}
145
- </div>
146
- {isLocalDev && (
147
- <>
148
- <div className="mt-6 flex flex-wrap items-center justify-center gap-2">
149
- <span className="text-muted-foreground text-xs">Services:</span>
150
- <a
151
- href="http://localhost:3000"
152
- target="_blank"
153
- rel="noopener noreferrer"
154
- className="border-border hover:border-foreground/30 hover:bg-accent bg-background inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-xs font-medium transition-colors"
155
- >
156
- Web <span className="text-muted-foreground">:3000</span>
157
- </a>
158
- <a
159
- href={`http://localhost:${backendPort}`}
160
- target="_blank"
161
- rel="noopener noreferrer"
162
- className="border-border hover:border-foreground/30 hover:bg-accent bg-background inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-xs font-medium transition-colors"
163
- >
164
- API{' '}
165
- <span className="text-muted-foreground">:{backendPort}</span>
166
- </a>
167
- <a
168
- href={`http://localhost:${backendPort}/docs`}
169
- target="_blank"
170
- rel="noopener noreferrer"
171
- className="border-border hover:border-foreground/30 hover:bg-accent bg-background inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-xs font-medium transition-colors"
172
- >
173
- API Docs
174
- <span className="text-muted-foreground">
175
- :{backendPort}/docs
176
- </span>
177
- </a>
178
- </div>
179
- <p className="text-muted-foreground mt-4 text-center text-xs">
180
- See{' '}
181
- <code className="bg-muted rounded px-1.5 py-0.5 font-mono">
182
- GETTING_STARTED.md
183
- </code>
184
- for further optional customization.
185
- </p>
186
- </>
187
- )}
188
- </div>
189
- </div>
190
- </main>
191
- );
192
- }
@@ -1,101 +0,0 @@
1
- 'use client';
2
-
3
- import type { RecentSignup } from '@repo/packages-types/stats';
4
- import { ScrollArea } from '@repo/packages-ui/scroll-area';
5
- import { Skeleton } from '@repo/packages-ui/skeleton';
6
- import { UserAvatar } from '@repo/packages-ui/user-avatar';
7
- import { motion } from 'framer-motion';
8
-
9
- function formatRelativeTime(dateStr: string) {
10
- const date = new Date(dateStr);
11
- const now = new Date();
12
- const diffMs = now.getTime() - date.getTime();
13
- const diffMins = Math.floor(diffMs / 60000);
14
- const diffHours = Math.floor(diffMins / 60);
15
- const diffDays = Math.floor(diffHours / 24);
16
-
17
- if (diffMins < 1) return 'Just now';
18
- if (diffMins < 60) return `${diffMins}m ago`;
19
- if (diffHours < 24) return `${diffHours}h ago`;
20
- if (diffDays === 1) return 'Yesterday';
21
- return `${diffDays}d ago`;
22
- }
23
-
24
- interface RecentSignupsFeedProps {
25
- signups: RecentSignup[];
26
- }
27
-
28
- export function RecentSignupsFeed({ signups }: RecentSignupsFeedProps) {
29
- return (
30
- <div className="bg-card rounded-xl border p-5">
31
- <div className="mb-4">
32
- <h3 className="text-sm font-semibold">Recent Signups</h3>
33
- <p className="text-muted-foreground text-xs">
34
- Latest user registrations
35
- </p>
36
- </div>
37
- <ScrollArea className="h-[280px] pr-3">
38
- <div className="space-y-3">
39
- {signups.map((signup, index) => (
40
- <motion.div
41
- key={signup.id}
42
- initial={{ opacity: 0, x: -10 }}
43
- animate={{ opacity: 1, x: 0 }}
44
- transition={{ delay: index * 0.05 }}
45
- className="flex items-center gap-3 rounded-lg border p-3"
46
- >
47
- <UserAvatar
48
- src={signup.image}
49
- name={signup.name}
50
- email={signup.email}
51
- size="sm"
52
- />
53
- <div className="min-w-0 flex-1">
54
- <p className="truncate text-sm font-medium">
55
- {signup.name || 'No name'}
56
- </p>
57
- <p className="text-muted-foreground truncate text-xs">
58
- {signup.email}
59
- </p>
60
- </div>
61
- <span className="text-muted-foreground shrink-0 text-xs">
62
- {formatRelativeTime(signup.createdAt)}
63
- </span>
64
- </motion.div>
65
- ))}
66
- {signups.length === 0 && (
67
- <p className="text-muted-foreground py-8 text-center text-sm">
68
- No recent signups
69
- </p>
70
- )}
71
- </div>
72
- </ScrollArea>
73
- </div>
74
- );
75
- }
76
-
77
- export function ActivityFeedSkeleton() {
78
- return (
79
- <div className="bg-card rounded-xl border p-5">
80
- <div className="mb-4 space-y-1">
81
- <Skeleton className="h-4 w-28" />
82
- <Skeleton className="h-3 w-36" />
83
- </div>
84
- <div className="space-y-3">
85
- {Array.from({ length: 5 }).map((_, i) => (
86
- <div
87
- key={i}
88
- className="flex items-center gap-3 rounded-lg border p-3"
89
- >
90
- <Skeleton className="size-8 rounded-full" />
91
- <div className="flex-1 space-y-1">
92
- <Skeleton className="h-3 w-24" />
93
- <Skeleton className="h-2 w-32" />
94
- </div>
95
- <Skeleton className="h-3 w-12" />
96
- </div>
97
- ))}
98
- </div>
99
- </div>
100
- );
101
- }
@@ -1,114 +0,0 @@
1
- 'use client';
2
-
3
- import type { AuthBreakdown } from '@repo/packages-types/stats';
4
- import { Skeleton } from '@repo/packages-ui/skeleton';
5
- import {
6
- Bar,
7
- BarChart,
8
- Cell,
9
- ResponsiveContainer,
10
- Tooltip,
11
- XAxis,
12
- YAxis,
13
- } from 'recharts';
14
-
15
- import { SimpleChartTooltip } from './chart-tooltip';
16
-
17
- interface AuthBreakdownChartProps {
18
- data: AuthBreakdown;
19
- }
20
-
21
- const AUTH_CONFIG = [
22
- { key: 'verified', label: 'Verified', color: '#10b981' },
23
- { key: 'unverified', label: 'Unverified', color: '#f59e0b' },
24
- { key: 'banned', label: 'Banned', color: '#ef4444' },
25
- ] as const;
26
-
27
- export function AuthBreakdownChart({ data }: AuthBreakdownChartProps) {
28
- const chartData = AUTH_CONFIG.map((config) => ({
29
- name: config.label,
30
- count: data[config.key],
31
- color: config.color,
32
- }));
33
-
34
- const total = data.verified + data.unverified + data.banned;
35
-
36
- return (
37
- <div className="bg-card rounded-xl border p-5">
38
- <div className="mb-4">
39
- <h3 className="text-sm font-semibold">Auth Status</h3>
40
- <p className="text-muted-foreground text-xs">
41
- Users by verification and ban status
42
- </p>
43
- </div>
44
- <div className="h-[200px]">
45
- <ResponsiveContainer width="100%" height="100%">
46
- <BarChart
47
- data={chartData}
48
- layout="vertical"
49
- margin={{ top: 5, right: 30, left: 0, bottom: 5 }}
50
- >
51
- <XAxis
52
- type="number"
53
- tick={{ fontSize: 11 }}
54
- tickLine={false}
55
- axisLine={false}
56
- allowDecimals={false}
57
- className="text-zinc-500 dark:text-zinc-400"
58
- />
59
- <YAxis
60
- type="category"
61
- dataKey="name"
62
- tick={{ fontSize: 11 }}
63
- tickLine={false}
64
- axisLine={false}
65
- width={75}
66
- className="text-zinc-500 dark:text-zinc-400"
67
- />
68
- <Tooltip
69
- content={
70
- <SimpleChartTooltip
71
- valueFormatter={(value: number) => [
72
- `${value} (${total > 0 ? ((value / total) * 100).toFixed(1) : 0}%)`,
73
- 'Users',
74
- ]}
75
- />
76
- }
77
- cursor={{ fill: 'rgba(99, 102, 241, 0.08)' }}
78
- />
79
- <Bar dataKey="count" radius={[0, 4, 4, 0]} maxBarSize={28}>
80
- {chartData.map((entry, index) => (
81
- <Cell key={`cell-${index}`} fill={entry.color} />
82
- ))}
83
- </Bar>
84
- </BarChart>
85
- </ResponsiveContainer>
86
- </div>
87
- </div>
88
- );
89
- }
90
-
91
- export function AuthBreakdownChartSkeleton() {
92
- return (
93
- <div className="bg-card rounded-xl border p-5">
94
- <div className="mb-4 space-y-1">
95
- <Skeleton className="h-4 w-20" />
96
- <Skeleton className="h-3 w-44" />
97
- </div>
98
- <div className="space-y-3 pt-4">
99
- <div className="flex items-center gap-3">
100
- <Skeleton className="h-3 w-16" />
101
- <Skeleton className="h-6 flex-1" />
102
- </div>
103
- <div className="flex items-center gap-3">
104
- <Skeleton className="h-3 w-16" />
105
- <Skeleton className="h-6 w-2/3" />
106
- </div>
107
- <div className="flex items-center gap-3">
108
- <Skeleton className="h-3 w-16" />
109
- <Skeleton className="h-6 w-1/4" />
110
- </div>
111
- </div>
112
- </div>
113
- );
114
- }
@@ -1,124 +0,0 @@
1
- 'use client';
2
-
3
- import { cn } from '@repo/packages-ui/lib/utils';
4
-
5
- interface TooltipPayload {
6
- value?: number;
7
- name?: string;
8
- color?: string;
9
- payload?: { color?: string };
10
- }
11
-
12
- interface ChartTooltipProps {
13
- active?: boolean;
14
- payload?: TooltipPayload[];
15
- label?: string;
16
- labelFormatter?: (label: string) => string;
17
- }
18
-
19
- export function ChartTooltip({
20
- active,
21
- payload,
22
- label,
23
- labelFormatter,
24
- }: ChartTooltipProps) {
25
- if (!active || !payload?.length) return null;
26
-
27
- const formattedLabel =
28
- labelFormatter && label ? labelFormatter(label) : label;
29
-
30
- return (
31
- <div
32
- className={cn(
33
- 'rounded-lg border px-3 py-2 shadow-lg',
34
- 'bg-white/90 dark:bg-zinc-900/90',
35
- 'backdrop-blur-md',
36
- 'border-zinc-200/50 dark:border-zinc-700/50'
37
- )}
38
- >
39
- {formattedLabel && (
40
- <p className="mb-1.5 text-xs font-semibold text-zinc-900 dark:text-zinc-100">
41
- {formattedLabel}
42
- </p>
43
- )}
44
- <div className="space-y-1">
45
- {payload.map((entry: TooltipPayload, index: number) => (
46
- <div key={index} className="flex items-center gap-2 text-xs">
47
- <span
48
- className="size-2 rounded-full"
49
- style={{ backgroundColor: entry.color }}
50
- />
51
- <span className="text-zinc-600 dark:text-zinc-400">
52
- {entry.name}:
53
- </span>
54
- <span className="font-medium text-zinc-900 dark:text-zinc-100">
55
- {typeof entry.value === 'number'
56
- ? entry.value.toLocaleString()
57
- : entry.value}
58
- </span>
59
- </div>
60
- ))}
61
- </div>
62
- </div>
63
- );
64
- }
65
-
66
- interface SimpleChartTooltipProps {
67
- active?: boolean;
68
- payload?: TooltipPayload[];
69
- label?: string;
70
- labelFormatter?: (label: string) => string;
71
- valueFormatter?: (value: number, name: string) => [string, string];
72
- }
73
-
74
- export function SimpleChartTooltip({
75
- active,
76
- payload,
77
- label,
78
- labelFormatter,
79
- valueFormatter,
80
- }: SimpleChartTooltipProps) {
81
- if (!active || !payload?.length) return null;
82
-
83
- const formattedLabel =
84
- labelFormatter && label ? labelFormatter(label) : label;
85
-
86
- return (
87
- <div
88
- className={cn(
89
- 'rounded-lg border px-3 py-2 shadow-lg',
90
- 'bg-white/90 dark:bg-zinc-900/90',
91
- 'backdrop-blur-md',
92
- 'border-zinc-200/50 dark:border-zinc-700/50'
93
- )}
94
- >
95
- {formattedLabel && (
96
- <p className="mb-1.5 text-xs font-semibold text-zinc-900 dark:text-zinc-100">
97
- {formattedLabel}
98
- </p>
99
- )}
100
- <div className="space-y-1">
101
- {payload.map((entry: TooltipPayload, index: number) => {
102
- const [formattedValue, formattedName] = valueFormatter
103
- ? valueFormatter(entry.value as number, entry.name as string)
104
- : [entry.value?.toLocaleString(), entry.name];
105
-
106
- return (
107
- <div key={index} className="flex items-center gap-2 text-xs">
108
- <span
109
- className="size-2 rounded-full"
110
- style={{ backgroundColor: entry.color || entry.payload?.color }}
111
- />
112
- <span className="text-zinc-600 dark:text-zinc-400">
113
- {formattedName}:
114
- </span>
115
- <span className="font-medium text-zinc-900 dark:text-zinc-100">
116
- {formattedValue}
117
- </span>
118
- </div>
119
- );
120
- })}
121
- </div>
122
- </div>
123
- );
124
- }