Saltar al contenido principal

Estructura frontend - NextJS

Notas sobre la estructura​

OrganizaciΓ³n por dominio​

  • Cada feature en /features es autΓ³noma con sus propios componentes, hooks, servicios, store, types y utils
  • Facilita la escalabilidad y el mantenimiento por equipos

Componentes​

  • /components/ui: Componentes puros sin lΓ³gica de negocio
  • /components/shared: Componentes con algo de lΓ³gica pero reutilizables
  • /features/[dominio]/components: Componentes especΓ­ficos del dominio

Estado​

  • Estado global mΓ­nimo en /store
  • Estado de dominio en /features/[dominio]/store
  • Uso de Zustand o Redux Toolkit segΓΊn complejidad

Servicios​

  • /services/api: ComunicaciΓ³n con el backend
  • /services/external: Integraciones con terceros
  • /features/[dominio]/services: LΓ³gica de negocio del dominio

Hooks​

  • /hooks: Hooks utilitarios globales
  • /features/[dominio]/hooks: Hooks especΓ­ficos del dominio

Tipos TypeScript​

  • /types: Tipos globales y compartidos
  • /features/[dominio]/types: Tipos del dominio

Testing​

  • Tests unitarios junto al cΓ³digo o en carpeta __tests__
  • Tests de integraciΓ³n y E2E en /tests

Barrel exports​

  • Cada carpeta tiene un index.ts para exportaciones limpias
  • Facilita imports: import { Button } from '@/components/ui'
prompts-frontend/
β”œβ”€β”€ .cursorrules # (Opcional - especΓ­fico para Cursor IDE)
β”œβ”€β”€ .env.local # Variables de entorno locales
β”œβ”€β”€ .env.example # Plantilla de variables de entorno
β”œβ”€β”€ .eslintrc.json # ConfiguraciΓ³n ESLint
β”œβ”€β”€ .gitignore # Archivos ignorados por Git
β”œβ”€β”€ .prettierrc # ConfiguraciΓ³n Prettier
β”œβ”€β”€ next.config.js # ConfiguraciΓ³n NextJS
β”œβ”€β”€ package.json # Dependencias y scripts
β”œβ”€β”€ tsconfig.json # ConfiguraciΓ³n TypeScript
β”œβ”€β”€ tailwind.config.ts # ConfiguraciΓ³n Tailwind CSS
β”œβ”€β”€ postcss.config.js # ConfiguraciΓ³n PostCSS
β”œβ”€β”€ docker/
β”‚ β”œβ”€β”€ Dockerfile # Dockerfile para producciΓ³n
β”‚ └── Dockerfile.dev # Dockerfile para desarrollo
β”œβ”€β”€ public/
β”‚ β”œβ”€β”€ favicon.ico
β”‚ β”œβ”€β”€ images/
β”‚ β”‚ β”œβ”€β”€ logo.svg
β”‚ β”‚ └── placeholders/
β”‚ └── locales/ # Archivos de traducciΓ³n (i18n)
β”‚ β”œβ”€β”€ es/
β”‚ β”‚ └── common.json
β”‚ └── en/
β”‚ └── common.json
β”œβ”€β”€ src/
β”‚ β”œβ”€β”€ app/ # App Router de Next.js 15
β”‚ β”‚ β”œβ”€β”€ layout.tsx # Layout principal
β”‚ β”‚ β”œβ”€β”€ page.tsx # PΓ‘gina principal
β”‚ β”‚ β”œβ”€β”€ loading.tsx # Estado de carga global
β”‚ β”‚ β”œβ”€β”€ error.tsx # Manejo de errores global
β”‚ β”‚ β”œβ”€β”€ not-found.tsx # PΓ‘gina 404
β”‚ β”‚ β”œβ”€β”€ globals.css # Estilos globales con Tailwind
β”‚ β”‚ β”œβ”€β”€ (authenticated)/ # Grupo de rutas autenticadas
β”‚ β”‚ β”‚ β”œβ”€β”€ layout.tsx # Layout para rutas autenticadas
β”‚ β”‚ β”‚ β”œβ”€β”€ dashboard/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ page.tsx
β”‚ β”‚ β”‚ β”‚ └── loading.tsx
β”‚ β”‚ β”‚ β”œβ”€β”€ prompts/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ page.tsx
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ new/
β”‚ β”‚ β”‚ β”‚ β”‚ └── page.tsx
β”‚ β”‚ β”‚ β”‚ └── [id]/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ page.tsx
β”‚ β”‚ β”‚ β”‚ └── edit/
β”‚ β”‚ β”‚ β”‚ └── page.tsx
β”‚ β”‚ β”‚ β”œβ”€β”€ flows/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ page.tsx
β”‚ β”‚ β”‚ β”‚ └── builder/
β”‚ β”‚ β”‚ β”‚ └── page.tsx
β”‚ β”‚ β”‚ β”œβ”€β”€ api-keys/
β”‚ β”‚ β”‚ β”‚ └── page.tsx
β”‚ β”‚ β”‚ └── settings/
β”‚ β”‚ β”‚ β”œβ”€β”€ page.tsx
β”‚ β”‚ β”‚ β”œβ”€β”€ profile/
β”‚ β”‚ β”‚ β”‚ └── page.tsx
β”‚ β”‚ β”‚ └── billing/
β”‚ β”‚ β”‚ └── page.tsx
β”‚ β”‚ β”œβ”€β”€ (public)/ # Grupo de rutas pΓΊblicas
β”‚ β”‚ β”‚ β”œβ”€β”€ layout.tsx # Layout para rutas pΓΊblicas
β”‚ β”‚ β”‚ β”œβ”€β”€ login/
β”‚ β”‚ β”‚ β”‚ └── page.tsx
β”‚ β”‚ β”‚ β”œβ”€β”€ register/
β”‚ β”‚ β”‚ β”‚ └── page.tsx
β”‚ β”‚ β”‚ └── pricing/
β”‚ β”‚ β”‚ └── page.tsx
β”‚ β”‚ └── api/ # API Routes (si se necesitan)
β”‚ β”‚ └── webhooks/
β”‚ β”‚ └── stripe/
β”‚ β”‚ └── route.ts
β”‚ β”œβ”€β”€ components/ # Componentes UI reutilizables
β”‚ β”‚ β”œβ”€β”€ ui/ # Componentes base sin lΓ³gica de negocio
β”‚ β”‚ β”‚ β”œβ”€β”€ button/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ button.tsx
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ button.styles.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ input/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ input.tsx
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ card/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ card.tsx
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ dialog/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ dialog.tsx
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ toast/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ toast.tsx
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ toast-provider.tsx
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ └── index.ts # Barrel export
β”‚ β”‚ β”œβ”€β”€ layout/ # Componentes de layout compartidos
β”‚ β”‚ β”‚ β”œβ”€β”€ header/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ header.tsx
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ header.styles.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ sidebar/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ sidebar.tsx
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ sidebar-item.tsx
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ footer/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ footer.tsx
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ └── mobile-nav/
β”‚ β”‚ β”‚ β”œβ”€β”€ mobile-nav.tsx
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ └── shared/ # Componentes compartidos con algo de lΓ³gica
β”‚ β”‚ β”œβ”€β”€ loading-spinner/
β”‚ β”‚ β”‚ β”œβ”€β”€ loading-spinner.tsx
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ error-boundary/
β”‚ β”‚ β”‚ β”œβ”€β”€ error-boundary.tsx
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ confirmation-dialog/
β”‚ β”‚ β”‚ β”œβ”€β”€ confirmation-dialog.tsx
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ └── file-upload/
β”‚ β”‚ β”œβ”€β”€ file-upload.tsx
β”‚ β”‚ β”œβ”€β”€ file-upload.utils.ts
β”‚ β”‚ └── index.ts
β”‚ β”œβ”€β”€ features/ # LΓ³gica de negocio organizada por dominio
β”‚ β”‚ β”œβ”€β”€ authentication/
β”‚ β”‚ β”‚ β”œβ”€β”€ components/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ login-form/
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ login-form.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ login-form.validation.ts
β”‚ β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ register-form/
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ register-form.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ register-form.validation.ts
β”‚ β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”‚ └── auth-guard/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ auth-guard.tsx
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ hooks/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ use-auth.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ use-login.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ use-register.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ services/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ auth.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ token.service.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ store/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ auth.store.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ types/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ auth.types.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ utils/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ auth.utils.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ prompt-management/
β”‚ β”‚ β”‚ β”œβ”€β”€ components/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt-editor/
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt-editor.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt-editor.styles.ts
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ editor-toolbar.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt-list/
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt-list.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt-card.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt-filters.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ optimization-assistant/
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ optimization-assistant.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ suggestion-card.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ optimization.utils.ts
β”‚ β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”‚ └── parameter-panel/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ parameter-panel.tsx
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ parameter-input.tsx
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ hooks/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ use-prompts.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ use-prompt-optimization.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ use-prompt-execution.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ services/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ optimization.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ template.service.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ store/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt.store.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ types/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt.types.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ optimization.types.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ utils/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt.utils.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ validation.utils.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ flow-builder/
β”‚ β”‚ β”‚ β”œβ”€β”€ components/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ canvas/
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ flow-canvas.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ canvas-controls.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ canvas.utils.ts
β”‚ β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ blocks/
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ base-block/
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ base-block.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ └── base-block.types.ts
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt-block/
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt-block.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ conditional-block/
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ conditional-block.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ loop-block/
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ loop-block.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ input-block/
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ input-block.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ output-block/
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ output-block.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ connections/
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ connection-line.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ connection-points.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ toolbar/
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ flow-toolbar.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ block-palette.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”‚ └── sidebar/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ properties-panel.tsx
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ flow-validation.tsx
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ hooks/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ use-flow-builder.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ use-canvas.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ use-blocks.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ use-connections.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ services/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ flow-engine.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ flow-validator.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ flow-executor.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ block-factory.service.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ store/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ flow.store.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ canvas.store.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ types/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ flow.types.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ block.types.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ connection.types.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ utils/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ flow.utils.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ canvas.utils.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ geometry.utils.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ credit-management/
β”‚ β”‚ β”‚ β”œβ”€β”€ components/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ credit-balance/
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ credit-balance.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ balance-indicator.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ usage-dashboard/
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ usage-dashboard.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ usage-chart.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ usage-table.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”‚ └── purchase-modal/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ purchase-modal.tsx
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ payment-form.tsx
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ hooks/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ use-credits.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ use-usage-stats.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ services/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ credit.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ usage.service.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ store/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ credit.store.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ types/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ credit.types.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ api-key-management/
β”‚ β”‚ β”‚ β”œβ”€β”€ components/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ key-generator/
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ key-generator.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ key-form.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ key-list/
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ key-list.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ key-card.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”‚ └── usage-analytics/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ usage-analytics.tsx
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ analytics-chart.tsx
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ hooks/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ use-api-keys.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ use-key-analytics.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ services/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ api-key.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ analytics.service.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ store/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ api-key.store.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ types/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ api-key.types.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ multimodal/
β”‚ β”‚ β”‚ β”œβ”€β”€ components/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ input-handlers/
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ text-input.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ image-input.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ audio-input.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ file-input.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ output-renderers/
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ text-output.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ image-output.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ audio-output.tsx
β”‚ β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”‚ └── media-preview/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ media-preview.tsx
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ hooks/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ use-media-upload.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ use-media-processing.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ services/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ media.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ upload.service.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ types/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ media.types.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ utils/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ file.utils.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ media.utils.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ └── user-management/
β”‚ β”‚ β”œβ”€β”€ components/
β”‚ β”‚ β”‚ β”œβ”€β”€ profile/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ profile-form.tsx
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ avatar-upload.tsx
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ billing/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ billing-dashboard.tsx
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ subscription-card.tsx
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ invoice-list.tsx
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ └── settings/
β”‚ β”‚ β”‚ β”œβ”€β”€ settings-panel.tsx
β”‚ β”‚ β”‚ β”œβ”€β”€ preference-form.tsx
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ hooks/
β”‚ β”‚ β”‚ β”œβ”€β”€ use-user.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ use-subscription.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ services/
β”‚ β”‚ β”‚ β”œβ”€β”€ user.service.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ subscription.service.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ store/
β”‚ β”‚ β”‚ β”œβ”€β”€ user.store.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ types/
β”‚ β”‚ β”‚ β”œβ”€β”€ user.types.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ subscription.types.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ └── index.ts
β”‚ β”œβ”€β”€ hooks/ # Hooks compartidos globalmente
β”‚ β”‚ β”œβ”€β”€ use-debounce.ts
β”‚ β”‚ β”œβ”€β”€ use-local-storage.ts
β”‚ β”‚ β”œβ”€β”€ use-media-query.ts
β”‚ β”‚ β”œβ”€β”€ use-click-outside.ts
β”‚ β”‚ β”œβ”€β”€ use-keyboard-shortcut.ts
β”‚ β”‚ └── index.ts
β”‚ β”œβ”€β”€ lib/ # LibrerΓ­as y configuraciones
β”‚ β”‚ β”œβ”€β”€ api/ # Cliente API y configuraciΓ³n
β”‚ β”‚ β”‚ β”œβ”€β”€ client.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ endpoints.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ interceptors.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ firebase/ # ConfiguraciΓ³n Firebase
β”‚ β”‚ β”‚ β”œβ”€β”€ config.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ auth.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ firestore.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ └── utils/ # Utilidades generales
β”‚ β”‚ β”œβ”€β”€ formatters.ts
β”‚ β”‚ β”œβ”€β”€ validators.ts
β”‚ β”‚ β”œβ”€β”€ constants.ts
β”‚ β”‚ β”œβ”€β”€ helpers.ts
β”‚ β”‚ └── index.ts
β”‚ β”œβ”€β”€ services/ # Servicios externos y APIs
β”‚ β”‚ β”œβ”€β”€ api/
β”‚ β”‚ β”‚ β”œβ”€β”€ auth-api.service.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ prompt-api.service.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ flow-api.service.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ external/
β”‚ β”‚ β”‚ β”œβ”€β”€ stripe.service.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ analytics.service.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ └── index.ts
β”‚ β”œβ”€β”€ store/ # Estado global de la aplicaciΓ³n
β”‚ β”‚ β”œβ”€β”€ index.ts # ConfiguraciΓ³n del store
β”‚ β”‚ β”œβ”€β”€ provider.tsx # Provider del store
β”‚ β”‚ β”œβ”€β”€ slices/ # Slices para Redux Toolkit
β”‚ β”‚ β”‚ β”œβ”€β”€ app.slice.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ ui.slice.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ └── middleware/
β”‚ β”‚ β”œβ”€β”€ logger.middleware.ts
β”‚ β”‚ └── index.ts
β”‚ β”œβ”€β”€ styles/ # Estilos globales adicionales
β”‚ β”‚ β”œβ”€β”€ animations.css
β”‚ β”‚ β”œβ”€β”€ overrides.css
β”‚ β”‚ └── variables.css
β”‚ └── types/ # Tipos TypeScript globales
β”‚ β”œβ”€β”€ global.d.ts
β”‚ β”œβ”€β”€ api.types.ts
β”‚ β”œβ”€β”€ common.types.ts
β”‚ └── index.ts
β”œβ”€β”€ tests/ # Tests organizados por tipo
β”‚ β”œβ”€β”€ unit/
β”‚ β”‚ β”œβ”€β”€ components/
β”‚ β”‚ β”œβ”€β”€ hooks/
β”‚ β”‚ └── services/
β”‚ β”œβ”€β”€ integration/
β”‚ β”‚ └── features/
β”‚ └── e2e/
β”‚ β”œβ”€β”€ auth.spec.ts
β”‚ β”œβ”€β”€ prompts.spec.ts
β”‚ └── flows.spec.ts
└── scripts/ # Scripts de utilidad
β”œβ”€β”€ generate-types.js
β”œβ”€β”€ analyze-bundle.js
└── check-dependencies.js