← Volver al Portal

Stack Tecnológico

Arquitectura y decisiones técnicas

Arquitectura General

CLIENTE

Web App
Mobile App
WhatsApp

API

Express.js
REST API
JWT Auth

SERVICIOS

PostgreSQL
Redis
OpenAI

Voice Processing Pipeline

🎤 Audio Input
Whisper API
GPT-4 NLP
Intent Router
Action Executor

Stack en Detalle

⚙️

Backend

Node.js Node.js 20 LTS
Runtime
TypeScript TypeScript 5.x
Language
Express Express.js
Framework
Prisma ORM
Database ORM
🔐 JWT + Refresh Tokens
Auth
🎨

Frontend

🚀 Astro 4.x
Framework
Tailwind Tailwind CSS
Styling
React React (islands)
Interactivity
📱 React Native (Q2)
Mobile App
🎙️ Web Audio API
Voice Recording
🗄️

Base de Datos

PostgreSQL PostgreSQL 15
Primary DB
Redis Redis
Cache & Sessions
📦 S3 / R2
File Storage
🤖

IA & Integraciones

🎤 OpenAI Whisper
Speech-to-Text
🧠 GPT-4
NLP & Intent
💳 Stripe
Payments
📧 SendGrid
Email
💬 WhatsApp Business API
Messaging

Infraestructura

Hosting

Railway

Backend API & Database

Vercel

Landing & Admin Portal

Cloudflare R2

File Storage & CDN

DevOps

GitHub Actions

CI/CD Pipeline

Docker

Containerization

Sentry

Error Tracking

Monitoring

Railway Metrics

Server Monitoring

PostHog

Product Analytics

Uptime Robot

Uptime Monitoring

Esquema de Base de Datos

// Core Models (Prisma Schema)

model User {
  id            String   @id @default(uuid())
  email         String   @unique
  passwordHash  String
  name          String
  businessName  String?
  plan          Plan     @default(FREE)

  clients       Client[]
  quotes        Quote[]
  invoices      Invoice[]
  voiceNotes    VoiceNote[]
  events        CalendarEvent[]

  createdAt     DateTime @default(now())
  updatedAt     DateTime @updatedAt
}

model Client {
  id          String   @id @default(uuid())
  userId      String
  name        String
  email       String?
  phone       String?
  company     String?

  quotes      Quote[]
  invoices    Invoice[]

  user        User     @relation(fields: [userId])
}

model Quote {
  id          String      @id @default(uuid())
  userId      String
  clientId    String
  number      String      @unique
  status      QuoteStatus @default(DRAFT)
  items       Json
  subtotal    Decimal
  tax         Decimal
  total       Decimal
  validUntil  DateTime

  user        User        @relation(fields: [userId])
  client      Client      @relation(fields: [clientId])
  invoice     Invoice?
}

model VoiceNote {
  id            String   @id @default(uuid())
  userId        String
  audioUrl      String
  transcription String?
  intent        String?
  processed     Boolean  @default(false)
  result        Json?

  user          User     @relation(fields: [userId])
  createdAt     DateTime @default(now())
}

enum Plan { FREE, PRO, BUSINESS }
enum QuoteStatus { DRAFT, SENT, ACCEPTED, REJECTED, EXPIRED }

Estructura de API

Endpoints Principales

POST /api/auth/login
POST /api/voice/voice-to-action
GET /api/quotes
POST /api/quotes
POST /api/quotes/:id/send
GET /api/analytics/dashboard
POST /api/payments/create-link

Voice Intent Actions

CREATE_QUOTE

Genera presupuesto desde transcripción

CREATE_INVOICE

Crea factura y envía al cliente

SCHEDULE_EVENT

Añade evento al calendario

ADD_CLIENT

Registra nuevo cliente en CRM

SEND_REMINDER

Envía recordatorio de cobro

Seguridad

🔐

Autenticación

  • • JWT con refresh tokens
  • • bcrypt password hashing
  • • Rate limiting por IP/user
  • • 2FA opcional (TOTP)
🛡️

Datos

  • • HTTPS everywhere
  • • Encryption at rest
  • • GDPR compliant
  • • Backups automáticos
🔒

API

  • • Input validation (Zod)
  • • CORS configurado
  • • Helmet.js headers
  • • SQL injection protected

Escalabilidad

10K

Usuarios concurrentes

100K

Requests/día

<200ms

API response time

99.9%

Uptime SLA

Estrategia de Escalado

Horizontal Scaling

Railway auto-scales según demanda

Database Pooling

PgBouncer para connection management

CDN Caching

Cloudflare para assets estáticos