ar-saas 0.2.0 → 0.3.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 (41) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +133 -25
  3. package/dist/cli.js +33 -1
  4. package/dist/generator.js +12 -3
  5. package/package.json +7 -3
  6. package/templates/frontend/package.json +21 -13
  7. package/templates/frontend/pnpm-lock.yaml +5012 -0
  8. package/templates/frontend/pnpm-workspace.yaml +3 -0
  9. package/templates/frontend/src/app/(auth)/register/page.tsx +49 -7
  10. package/templates/frontend/src/app/(dashboard)/billing/page.tsx +111 -0
  11. package/templates/frontend/src/app/(dashboard)/dashboard/page.tsx +81 -12
  12. package/templates/frontend/src/app/(dashboard)/layout.tsx +11 -32
  13. package/templates/frontend/src/app/(dashboard)/profile/page.tsx +226 -0
  14. package/templates/frontend/src/app/(dashboard)/settings/page.tsx +156 -0
  15. package/templates/frontend/src/app/(dashboard)/team/page.tsx +178 -0
  16. package/templates/frontend/src/app/(legal)/privacy/page.tsx +127 -0
  17. package/templates/frontend/src/app/(legal)/terms/page.tsx +118 -0
  18. package/templates/frontend/src/app/page.tsx +43 -3
  19. package/templates/frontend/src/app/setup/page.tsx +1 -4
  20. package/templates/frontend/src/components/dashboard/header.tsx +89 -0
  21. package/templates/frontend/src/components/dashboard/sidebar.tsx +71 -0
  22. package/templates/frontend/src/components/dashboard/stat-card.tsx +34 -0
  23. package/templates/frontend/src/components/landing/faq.tsx +39 -0
  24. package/templates/frontend/src/components/landing/features.tsx +54 -0
  25. package/templates/frontend/src/components/landing/footer.tsx +76 -0
  26. package/templates/frontend/src/components/landing/hero.tsx +72 -0
  27. package/templates/frontend/src/components/landing/navbar.tsx +78 -0
  28. package/templates/frontend/src/components/landing/pricing.tsx +90 -0
  29. package/templates/frontend/src/components/ui/accordion.tsx +52 -0
  30. package/templates/frontend/src/components/ui/avatar.tsx +46 -0
  31. package/templates/frontend/src/components/ui/badge.tsx +30 -0
  32. package/templates/frontend/src/components/ui/checkbox.tsx +27 -0
  33. package/templates/frontend/src/components/ui/dialog.tsx +100 -0
  34. package/templates/frontend/src/components/ui/dropdown-menu.tsx +173 -0
  35. package/templates/frontend/src/components/ui/separator.tsx +25 -0
  36. package/templates/frontend/src/components/ui/skeleton.tsx +7 -0
  37. package/templates/frontend/src/components/ui/switch.tsx +28 -0
  38. package/templates/frontend/src/components/ui/tabs.tsx +54 -0
  39. package/templates/frontend/src/components/ui/textarea.tsx +20 -0
  40. package/templates/frontend/src/config/site.ts +197 -0
  41. package/dist/license.js +0 -71
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ignacio Becher
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,13 +1,16 @@
1
1
  # ar-saas
2
2
 
3
+ <p align="center">
4
+ <img src="assets/logo.png" alt="ar-saas" width="400" />
5
+ </p>
6
+
3
7
  <p align="center">
4
8
  <strong>Generador de proyectos SaaS multi-tenant para startups argentinas</strong><br/>
5
- Backend NestJS + Frontend Next.js listos para producción en minutos.
9
+ Backend NestJS + Frontend Next.js completo — landing, auth, dashboard y legal listos para producción.
6
10
  </p>
7
11
 
8
12
  <p align="center">
9
13
  <a href="https://www.npmjs.com/package/ar-saas"><img src="https://img.shields.io/npm/v/ar-saas.svg" alt="npm version" /></a>
10
- <a href="https://www.npmjs.com/package/ar-saas"><img src="https://img.shields.io/npm/dm/ar-saas.svg" alt="npm downloads" /></a>
11
14
  <a href="https://github.com/ignaciobecher/ar-saas/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="license" /></a>
12
15
  <img src="https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen" alt="node version" />
13
16
  </p>
@@ -20,7 +23,7 @@
20
23
  npx ar-saas mi-proyecto
21
24
  ```
22
25
 
23
- Respondés 4 preguntas y en minutos tenés un proyecto completo corriendo localmente.
26
+ Respondés algunas preguntas y en minutos tenés un proyecto completo corriendo localmente.
24
27
 
25
28
  ---
26
29
 
@@ -28,30 +31,86 @@ Respondés 4 preguntas y en minutos tenés un proyecto completo corriendo localm
28
31
 
29
32
  ```
30
33
  mi-proyecto/
31
- ├── backend/ # NestJS 11 + MongoDB
34
+ ├── backend/ # NestJS 11 + MongoDB
32
35
  │ ├── src/
33
36
  │ │ ├── modules/
34
- │ │ │ ├── auth/ # Auth completo (JWT en cookies HttpOnly)
35
- │ │ │ ├── users/ # Usuarios con roles
36
- │ │ │ ├── workspaces/ # Multi-tenancy por workspace
37
- │ │ │ └── mail/ # Emails transaccionales con Resend
38
- │ │ └── common/ # Guards, filtros, decoradores, base repository
39
- │ ├── .env.example
37
+ │ │ │ ├── auth/ # Auth completo (JWT + GitHub OAuth en cookies HttpOnly)
38
+ │ │ │ ├── users/ # Usuarios con roles
39
+ │ │ │ ├── workspaces/ # Multi-tenancy por workspace
40
+ │ │ │ └── mail/ # Emails transaccionales con Resend
41
+ │ │ └── common/ # Guards, filtros, decoradores, base repository
42
+ │ ├── .env # Copiado de .env.example automáticamente
40
43
  │ └── package.json
41
- ├── frontend/ # Next.js 15 + Tailwind CSS 4 + shadcn/ui
44
+
45
+ ├── frontend/ # Next.js 15 + Tailwind CSS 4 + shadcn/ui
42
46
  │ ├── src/
47
+ │ │ ├── config/
48
+ │ │ │ └── site.ts # ← Personalización central del SaaS
43
49
  │ │ ├── app/
44
- │ │ │ ├── (auth)/ # Login, register, verify email, reset password
45
- │ │ │ ├── (dashboard)/ # Rutas protegidas con layout
46
- │ │ │ └── setup/ # Pantalla de onboarding al abrir por primera vez
47
- │ │ ├── providers/ # AuthProvider con estado global
48
- │ │ └── lib/api/ # Cliente axios con refresh automático
50
+ │ │ │ ├── page.tsx # Landing page completa
51
+ │ │ │ ├── (auth)/ # Login, register (+términos), verify, reset
52
+ │ │ │ ├── (dashboard)/ # Rutas protegidas
53
+ │ │ │ │ ├── dashboard/ # Overview con stat cards
54
+ │ │ │ │ ├── profile/ # Perfil de usuario + cambio de contraseña
55
+ │ │ │ │ ├── settings/ # Notificaciones, workspace, zona peligrosa
56
+ │ │ │ │ ├── billing/ # Plan actual, historial, upgrade
57
+ │ │ │ │ └── team/ # Miembros + invitaciones
58
+ │ │ │ ├── (legal)/
59
+ │ │ │ │ ├── terms/ # Términos y condiciones
60
+ │ │ │ │ └── privacy/ # Política de privacidad
61
+ │ │ │ └── setup/ # Onboarding inicial
62
+ │ │ ├── components/
63
+ │ │ │ ├── landing/ # Navbar, Hero, Features, Pricing, FAQ, Footer
64
+ │ │ │ ├── dashboard/ # Sidebar, Header, StatCard
65
+ │ │ │ └── ui/ # 15+ componentes shadcn/ui
66
+ │ │ ├── providers/ # AuthProvider con estado global
67
+ │ │ └── lib/api/ # Cliente axios con refresh automático
68
+ │ ├── .env.local # Copiado de .env.local.example automáticamente
49
69
  │ └── package.json
70
+
50
71
  └── railway.toml / fly.toml / docker-compose.yml
51
72
  ```
52
73
 
53
74
  ---
54
75
 
76
+ ## Personalización
77
+
78
+ Al generar el proyecto, el CLI pregunta el nombre, tagline, descripción y email de soporte del SaaS. Esos valores se inyectan automáticamente en un único archivo:
79
+
80
+ ```
81
+ frontend/src/config/site.ts
82
+ ```
83
+
84
+ Ese archivo es la **fuente de verdad** para todo el contenido de la app:
85
+
86
+ ```ts
87
+ export const siteConfig = {
88
+ name: 'Mi SaaS',
89
+ tagline: 'La plataforma que tu equipo necesita',
90
+ description: 'Automatizá tu negocio...',
91
+ supportEmail: 'hola@mi-saas.com',
92
+
93
+ // Navegación de la landing
94
+ nav: { links: [...] },
95
+
96
+ // Secciones de la landing
97
+ hero: { headline, description, cta, ctaSecondary },
98
+ features: [...], // Íconos, títulos y descripciones
99
+ pricing: [...], // 3 tiers con features, precios y CTAs
100
+ faq: [...], // Preguntas y respuestas
101
+
102
+ // Footer
103
+ footer: { columns, social, copyright },
104
+
105
+ // Usado en /terms y /privacy
106
+ legal: { companyName, email, lastUpdated },
107
+ }
108
+ ```
109
+
110
+ Editás ese archivo una sola vez y toda la app (landing, footer, páginas legales) queda actualizada.
111
+
112
+ ---
113
+
55
114
  ## Stack
56
115
 
57
116
  ### Backend
@@ -60,6 +119,7 @@ mi-proyecto/
60
119
  | NestJS | 11 | Framework principal |
61
120
  | MongoDB + Mongoose | 9 | Base de datos |
62
121
  | JWT (passport) | — | Autenticación en cookies HttpOnly |
122
+ | passport-github2 | — | OAuth con GitHub |
63
123
  | Resend | — | Emails transaccionales |
64
124
  | Swagger | — | Documentación automática en `/api/docs` |
65
125
 
@@ -68,31 +128,44 @@ mi-proyecto/
68
128
  |---|---|---|
69
129
  | Next.js | 15 | App Router, Server Components |
70
130
  | Tailwind CSS | 4 | Estilos |
71
- | shadcn/ui | — | Componentes UI |
72
- | react-hook-form | — | Formularios |
131
+ | shadcn/ui + Radix UI | — | 15+ componentes listos (button, dialog, dropdown, tabs, accordion, avatar, switch, etc.) |
132
+ | react-hook-form | — | Formularios con validación |
73
133
  | axios | — | HTTP client con interceptor de refresh |
134
+ | lucide-react | — | Íconos |
74
135
 
75
136
  ---
76
137
 
77
138
  ## Módulos incluidos
78
139
 
79
- ### Free (siempre incluidos)
140
+ ### Frontend siempre incluido
141
+
142
+ | Sección | Contenido |
143
+ |---|---|
144
+ | **Landing page** | Navbar sticky, Hero con mockup, Features (6 cards), Pricing (3 tiers), FAQ (acordeón), CTA final, Footer |
145
+ | **Auth** | Login, Register (con checkbox de términos), Verify email, Forgot password, Reset password |
146
+ | **Dashboard** | Overview con stat cards, sidebar con navegación activa, header con avatar + dropdown |
147
+ | **Perfil** | Editar nombre/email, cambiar contraseña (modal), zona de eliminación de cuenta |
148
+ | **Ajustes** | Switches de notificaciones por email, configuración de workspace, zona peligrosa |
149
+ | **Facturación** | Plan actual, método de pago, historial de facturas, botón de upgrade |
150
+ | **Equipo** | Lista de miembros, invitar por email (modal), gestión de roles |
151
+ | **Legal** | Términos y condiciones, Política de privacidad — ambas enlazadas desde el footer y el register |
152
+
153
+ ### Backend — siempre incluido
80
154
 
81
155
  | Módulo | Descripción |
82
156
  |---|---|
83
157
  | **Auth completo** | Registro, login, verificación de email, reset de password |
158
+ | **GitHub OAuth** | Login/registro con GitHub (código de intercambio + cookies HttpOnly) |
84
159
  | **Multi-tenancy** | Aislamiento estricto por `workspaceId` en todas las queries |
85
160
  | **Mail transaccional** | Verificación, bienvenida y reset con Resend. Fail-open si Resend falla |
86
161
 
87
- ### Opcionales
162
+ ### Módulos opcionales
88
163
 
89
164
  | Módulo | Descripción |
90
165
  |---|---|
91
- | **OAuth + 2FA** | Login con GitHub/Google + autenticación de dos factores TOTP |
92
166
  | **Notificaciones** | Notificaciones in-app + Push Web (VAPID) |
93
167
  | **Invoices + Quotes** | Facturación con generación de PDF |
94
168
  | **CRM** | Kanban + Pipeline de ventas |
95
- | **MercadoPago** | Suscripciones recurrentes con webhooks |
96
169
 
97
170
  ---
98
171
 
@@ -111,6 +184,10 @@ Al ejecutar el CLI se copian automáticamente los archivos `.env.example` → `.
111
184
  | `RESEND_FROM_EMAIL` | Email remitente verificado en Resend |
112
185
  | `APP_URL` | URL del frontend (para links en emails) |
113
186
  | `CORS_ORIGINS` | URL del frontend separada por comas |
187
+ | `FRONTEND_URL` | URL del frontend para redirecciones OAuth |
188
+ | `GITHUB_CLIENT_ID` | Client ID de tu GitHub OAuth App |
189
+ | `GITHUB_CLIENT_SECRET` | Client Secret de tu GitHub OAuth App |
190
+ | `GITHUB_CALLBACK_URL` | Callback URL registrada en GitHub |
114
191
 
115
192
  ### Frontend — variables requeridas
116
193
 
@@ -165,10 +242,12 @@ npm run start:dev
165
242
  cd mi-proyecto/frontend
166
243
  npm install
167
244
  npm run dev
168
- # → http://localhost:3001
245
+ # → http://localhost:3001 (landing page)
246
+ # → http://localhost:3001/login
247
+ # → http://localhost:3001/dashboard
169
248
  ```
170
249
 
171
- La primera vez que abrís el frontend aparece una pantalla de onboarding que guía la configuración completa.
250
+ La landing page aparece directo en `/`. El primer setup del backend se hace desde la pantalla de onboarding.
172
251
 
173
252
  ---
174
253
 
@@ -182,6 +261,9 @@ La primera vez que abrís el frontend aparece una pantalla de onboarding que gu
182
261
  - `POST /api/auth/forgot-password` — Solicitud de reset
183
262
  - `POST /api/auth/reset-password` — Reset de contraseña
184
263
  - `GET /api/auth/me` — Datos del usuario autenticado
264
+ - `GET /api/auth/github` — Inicia el flujo OAuth con GitHub
265
+ - `GET /api/auth/github/callback` — Callback de GitHub
266
+ - `POST /api/auth/github/exchange` — Canjea el código por cookies de sesión
185
267
 
186
268
  Los tokens JWT viajan **únicamente en cookies HttpOnly**. Nunca en `localStorage` ni en el body de las respuestas.
187
269
 
@@ -197,7 +279,33 @@ Los tokens JWT viajan **únicamente en cookies HttpOnly**. Nunca en `localStorag
197
279
 
198
280
  ## Licencia
199
281
 
200
- MIT el código generado es completamente tuyo, sin restricciones de uso comercial.
282
+ MIT © 2026 [Ignacio Becher](https://github.com/ignaciobecher)
283
+
284
+ El código generado por esta herramienta es completamente tuyo, sin restricciones de uso comercial. Podés usarlo, modificarlo y distribuirlo libremente.
285
+
286
+ ---
287
+
288
+ ## Legal
289
+
290
+ **Propiedad del código generado**
291
+
292
+ Todo el código que `ar-saas` genera en tu proyecto te pertenece a vos. No reclamamos ningún derecho sobre el código generado ni sobre los productos que construyas con él.
293
+
294
+ **Sin garantías**
295
+
296
+ Esta herramienta se provee "tal cual" (*as is*), sin garantías de ningún tipo. No nos hacemos responsables por:
297
+
298
+ - Vulnerabilidades de seguridad en el código generado si modificás la configuración por defecto
299
+ - Daños directos o indirectos derivados del uso del software
300
+ - Pérdida de datos o interrupciones de servicio en proyectos construidos con esta herramienta
301
+
302
+ **Dependencias de terceros**
303
+
304
+ El código generado incluye dependencias de terceros (NestJS, Next.js, MongoDB, etc.), cada una con su propia licencia. Es tu responsabilidad revisar y cumplir con los términos de cada dependencia en tu proyecto.
305
+
306
+ **Seguridad**
307
+
308
+ Si encontrás una vulnerabilidad de seguridad en esta herramienta, por favor reportala abriendo un issue en el [repositorio de GitHub](https://github.com/ignaciobecher/ar-saas) en lugar de hacerlo público.
201
309
 
202
310
  ---
203
311
 
package/dist/cli.js CHANGED
@@ -13,7 +13,7 @@ async function runCli(defaultName) {
13
13
  {
14
14
  type: 'input',
15
15
  name: 'projectName',
16
- message: 'Nombre del proyecto:',
16
+ message: 'Nombre del proyecto (slug):',
17
17
  default: defaultName ?? 'my-saas',
18
18
  validate: (input) => {
19
19
  if (!/^[a-z0-9][a-z0-9-]{1,}$/.test(input)) {
@@ -22,6 +22,38 @@ async function runCli(defaultName) {
22
22
  return true;
23
23
  },
24
24
  },
25
+ {
26
+ type: 'input',
27
+ name: 'siteTitle',
28
+ message: 'Nombre del SaaS (cómo se muestra a los usuarios):',
29
+ default: (answers) => answers.projectName
30
+ ? answers.projectName
31
+ .split('-')
32
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
33
+ .join(' ')
34
+ : 'Mi SaaS',
35
+ validate: (input) => input.trim().length >= 2 || 'El nombre debe tener al menos 2 caracteres',
36
+ },
37
+ {
38
+ type: 'input',
39
+ name: 'siteTagline',
40
+ message: 'Tagline (frase corta que describe el producto):',
41
+ default: 'La plataforma que tu equipo necesita',
42
+ validate: (input) => input.trim().length >= 5 || 'El tagline debe tener al menos 5 caracteres',
43
+ },
44
+ {
45
+ type: 'input',
46
+ name: 'siteDescription',
47
+ message: 'Descripción (una o dos oraciones para la landing):',
48
+ default: 'Automatizá tu negocio, escalá tu equipo y enfocate en lo que importa. Todo desde una sola plataforma.',
49
+ },
50
+ {
51
+ type: 'input',
52
+ name: 'supportEmail',
53
+ message: 'Email de soporte / contacto:',
54
+ default: (answers) => `hola@${answers.projectName ?? 'mi-saas'}.com`,
55
+ validate: (input) => /\S+@\S+\.\S+/.test(input) || 'Ingresá un email válido',
56
+ },
25
57
  {
26
58
  type: 'list',
27
59
  name: 'stack',
package/dist/generator.js CHANGED
@@ -65,13 +65,16 @@ async function generate(config) {
65
65
  spinner.text = 'Configurando variables de entorno...';
66
66
  setupEnvFiles(projectDir, config);
67
67
  spinner.succeed(chalk_1.default.green(`Proyecto ${chalk_1.default.bold(config.projectName)} creado`));
68
+ console.log();
69
+ console.log(chalk_1.default.cyan(` Sitio: ${chalk_1.default.bold(config.siteTitle)}`));
70
+ console.log(chalk_1.default.gray(` "${config.siteTagline}"`));
68
71
  printNextSteps(config);
69
72
  }
70
73
  function processDir(dir, config) {
71
74
  for (const file of collectTextFiles(dir)) {
72
75
  try {
73
76
  let content = fs_1.default.readFileSync(file, 'utf-8');
74
- content = applyNameReplacements(content, config.projectName);
77
+ content = applyNameReplacements(content, config);
75
78
  fs_1.default.writeFileSync(file, content, 'utf-8');
76
79
  }
77
80
  catch {
@@ -97,11 +100,16 @@ function collectTextFiles(dir) {
97
100
  }
98
101
  return result;
99
102
  }
100
- function applyNameReplacements(content, projectName) {
103
+ function applyNameReplacements(content, config) {
104
+ const { projectName, siteTitle, siteTagline, siteDescription, supportEmail } = config;
101
105
  return content
102
106
  .replace(/ar-saas-backend/g, `${projectName}-backend`)
103
107
  .replace(/ar-saas-frontend/g, `${projectName}-frontend`)
104
- .replace(/ar-saas/g, projectName);
108
+ .replace(/ar-saas/g, projectName)
109
+ .replace(/__SITE_NAME__/g, siteTitle)
110
+ .replace(/__SITE_TAGLINE__/g, siteTagline)
111
+ .replace(/__SITE_DESCRIPTION__/g, siteDescription)
112
+ .replace(/__SUPPORT_EMAIL__/g, supportEmail);
105
113
  }
106
114
  function generateDeployConfig(projectDir, config) {
107
115
  if (config.deployTarget === 'later')
@@ -222,6 +230,7 @@ function printNextSteps(config) {
222
230
  console.log();
223
231
  console.log(chalk_1.default.cyan(` cd ${config.projectName}/frontend`));
224
232
  console.log(chalk_1.default.gray(' # Completar .env.local con la URL del backend'));
233
+ console.log(chalk_1.default.gray(' # Personalizar contenido en src/config/site.ts'));
225
234
  console.log(chalk_1.default.cyan(' npm install'));
226
235
  console.log(chalk_1.default.cyan(' npm run dev'));
227
236
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ar-saas",
3
- "version": "0.2.0",
4
- "description": "Generador de proyectos SaaS multi-tenant para startups argentinas",
3
+ "version": "0.3.0",
4
+ "description": "Generador de proyectos SaaS multi-tenant para startups argentinas. Landing page, auth, dashboard y legal listos para producción.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
7
7
  "ar-saas": "dist/index.js"
@@ -23,7 +23,11 @@
23
23
  "argentina",
24
24
  "cli",
25
25
  "generator",
26
- "multi-tenant"
26
+ "multi-tenant",
27
+ "landing-page",
28
+ "dashboard",
29
+ "boilerplate",
30
+ "starter"
27
31
  ],
28
32
  "author": "ignacio.becher@gmail.com",
29
33
  "license": "MIT",
@@ -9,32 +9,40 @@
9
9
  "lint": "next lint"
10
10
  },
11
11
  "dependencies": {
12
- "next": "^15.3.3",
13
- "react": "^19.1.0",
14
- "react-dom": "^19.1.0",
15
- "axios": "^1.7.9",
16
- "js-cookie": "^3.0.5",
17
- "@radix-ui/react-slot": "^1.1.2",
12
+ "@hookform/resolvers": "^3.9.1",
13
+ "@radix-ui/react-accordion": "^1.2.13",
14
+ "@radix-ui/react-avatar": "^1.1.12",
15
+ "@radix-ui/react-checkbox": "^1.3.4",
16
+ "@radix-ui/react-dialog": "^1.1.16",
17
+ "@radix-ui/react-dropdown-menu": "^2.1.17",
18
18
  "@radix-ui/react-label": "^2.1.2",
19
+ "@radix-ui/react-separator": "^1.1.9",
20
+ "@radix-ui/react-slot": "^1.1.2",
21
+ "@radix-ui/react-switch": "^1.3.0",
22
+ "@radix-ui/react-tabs": "^1.1.14",
19
23
  "@radix-ui/react-toast": "^1.2.6",
24
+ "axios": "^1.7.9",
20
25
  "class-variance-authority": "^0.7.1",
21
26
  "clsx": "^2.1.1",
22
- "tailwind-merge": "^2.6.0",
27
+ "js-cookie": "^3.0.5",
23
28
  "lucide-react": "^0.477.0",
29
+ "next": "^15.3.3",
30
+ "react": "^19.1.0",
31
+ "react-dom": "^19.1.0",
24
32
  "react-hook-form": "^7.54.2",
25
- "@hookform/resolvers": "^3.9.1",
33
+ "tailwind-merge": "^2.6.0",
26
34
  "zod": "^3.24.1"
27
35
  },
28
36
  "devDependencies": {
29
- "typescript": "^5.7.3",
37
+ "@eslint/eslintrc": "^3.2.0",
38
+ "@tailwindcss/postcss": "^4.1.0",
39
+ "@types/js-cookie": "^3.0.6",
30
40
  "@types/node": "^22.10.7",
31
41
  "@types/react": "^19.1.0",
32
42
  "@types/react-dom": "^19.1.0",
33
- "@types/js-cookie": "^3.0.6",
34
- "tailwindcss": "^4.1.0",
35
- "@tailwindcss/postcss": "^4.1.0",
36
43
  "eslint": "^9.18.0",
37
44
  "eslint-config-next": "^15.3.3",
38
- "@eslint/eslintrc": "^3.2.0"
45
+ "tailwindcss": "^4.1.0",
46
+ "typescript": "^5.7.3"
39
47
  }
40
48
  }