Plataforma ciudadana de transparencia electoral para las elecciones generales de Perú 2026. PreCenso simulado, fichas detalladas de 38+ partidos y sus candidatos (presidenciales, diputados, senadores), foro ciudadano, quiz político, verificador de promesas, chat en tiempo real, mapa interactivo por departamento, ranking nacional y estadísticas en vivo.
Diseñado para alto tráfico (100K–1M+ usuarios concurrentes).
Última actualización: 4 de marzo de 2026
Monorepo con:
- Frontend: Next.js 14.2 (App Router, React 18, TypeScript 5)
- Backend: Next.js API Routes (REST), NextAuth.js (Credentials + Google OAuth, JWT)
- Base de datos: PostgreSQL (via
pgPool, sin ORM) - Runtime / Package Manager: Bun
- Estilo visual: Neo-brutalist sticker design (bordes gruesos, colores peruanos, tipografía Frogie)
proyecto-politica-2026/
├── apps/
│ └── my-app/ # Next.js 14.2 (App Router)
│ ├── src/
│ │ ├── app/ # Páginas y API Routes
│ │ │ ├── api/
│ │ │ │ ├── ai/ # Asistente IA (chat con Gemini)
│ │ │ │ ├── auth/ # Login, registro, NextAuth
│ │ │ │ ├── censo/ # Votación
│ │ │ │ ├── chat/ # Chat global + presencia + reacciones
│ │ │ │ ├── estadisticas/ # Stats agregadas
│ │ │ │ ├── forum/ # Foro (threads, votes)
│ │ │ │ ├── mapa/ # Datos geográficos
│ │ │ │ ├── quiz/ # Quiz político
│ │ │ │ ├── ranking/ # Ranking nacional
│ │ │ │ └── user/ # Perfil, foto, customización
│ │ │ ├── asistente-ia/ # Asistente IA (página de chat)
│ │ │ ├── candidatos/ # 38 partidos + diputados + senadores
│ │ │ ├── censo/ # Wizard de votación
│ │ │ ├── chat/ # Chat embebido + Foro
│ │ │ ├── descubre/ # Quiz, comparador, simulador
│ │ │ ├── estadisticas/ # Dashboard de estadísticas
│ │ │ ├── perfil/ # Perfil (propio y público)
│ │ │ └── verificador/ # Verificador de promesas
│ │ ├── components/
│ │ │ ├── ai-assistant/ # Asistente IA (header, mensajes, input, acciones)
│ │ │ ├── animations/ # FloatingDoodles, HeroBanner, PlayfulUI, ScrollFlow
│ │ │ ├── auth/ # AuthModal (login/registro)
│ │ │ ├── candidatos/ # CandidatoPageTemplate, CongresistaPageTemplate
│ │ │ ├── carousels/ # Carruseles de candidatos
│ │ │ ├── censo/ # CensoWizard, Steps
│ │ │ ├── chat/ # GlobalChat, ForumView
│ │ │ ├── icons/ # Iconos SVG custom (Apple, Premium)
│ │ │ ├── layout/ # PremiumLayout (navbar, footer, dark mode)
│ │ │ ├── map/ # Mapa interactivo del Perú (SVG)
│ │ │ ├── profile/ # ProfileCustomizer (SpaceHey-style)
│ │ │ ├── providers/ # ThemeProvider, SessionProvider
│ │ │ ├── ruixen/ # CardStack, ShareButton, SlidingPagination
│ │ │ └── ui/ # AnimatedThemeToggle
│ │ ├── data/
│ │ │ └── parties.ts # Data de congresistas por partido
│ │ ├── stores/
│ │ │ └── ai-chat-store.ts # Zustand store para el Asistente IA
│ │ └── lib/
│ │ ├── auth.ts # NextAuth config + user ops + Google OAuth
│ │ ├── cache.ts # In-memory TTL cache
│ │ ├── candidates.ts # Data estática de 38 partidos
│ │ ├── db.ts # Queries (votos, chat, stats)
│ │ ├── forum.ts # Queries del foro
│ │ ├── pool.ts # PostgreSQL connection pool
│ │ ├── rate-limit.ts # Rate limiter (sliding window)
│ │ └── utils.ts # Utilidades generales
│ └── next.config.js # Config + security headers
├── database/ # Migraciones SQL (000–017)
├── services/ # Microservicios (scaffolded)
│ ├── autoscaler/ # Auto-scaling service
│ ├── core-api/ # API core (Node.js)
│ ├── rag-service/ # RAG con AI
│ ├── realtime-service/ # WebSocket / tiempo real
│ └── scraping-service/ # Scraping de datos JNE
├── peru-map-component/ # Componente SVG del mapa de Perú
├── SEGURIDAD.md # Documentación de seguridad
├── NUEVAS_FUNCIONALIDADES.md # Roadmap y estado de features
└── README.md
| Tecnología | Versión | Uso |
|---|---|---|
| React | 18.2 | UI library |
| Next.js | 14.2.0 | Framework fullstack (App Router, API Routes, SSR/CSR) |
| TypeScript | 5.x | Tipado estático |
| TailwindCSS | 3.4 | Estilos utility-first + CSS variables peruanas |
| tailwindcss-animate | 1.0.7 | Animaciones con clases Tailwind |
| Framer Motion | 12.31+ | Animaciones declarativas (transitions, hover, modales, layout) |
| GSAP | 3.14 + ScrollTrigger | Parallax, scroll reveals, animaciones avanzadas |
| Swiper | 12.1 | Carrusel de candidatos (coverflow, autoplay) |
| Recharts | 2.12 | Gráficos (barras, pie, área) en Estadísticas |
| Lucide React | 0.575 | Iconos SVG |
| Radix UI | Dialog, Dropdown, Tabs | Componentes headless accesibles |
| Lenis | 1.0.42 | Smooth scrolling |
| next-themes | 0.4.6 | Dark mode / Light mode toggle |
| Sileo | 0.1.1 | Notificaciones toast |
| Vercel AI SDK | 3.4.33 | Chat streaming con LLM (useChat + streamText) |
| @ai-sdk/google | 0.0.55 | Provider para Google Gemini 2.0 Flash |
| react-markdown | 10.x | Renderizado de Markdown en respuestas del Asistente IA |
| remark-gfm | 4.x | Soporte GFM (tablas, strikethrough, autolinks) |
| Zustand | 4.5 | State management global |
| React Hook Form | 7.51 | Formularios |
| Zod | 3.22 | Validación de esquemas |
| clsx + tailwind-merge + CVA | — | Utilidades de clase CSS |
| sharp | 0.34.5 | Optimización de imágenes en build |
| Tecnología | Versión | Uso |
|---|---|---|
| Next.js API Routes | 14.2 | REST endpoints (/api/chat, /api/forum, /api/quiz, etc.) |
| NextAuth.js | 4.24 | Auth (Credentials + Google OAuth, JWT sessions) |
PostgreSQL (via pg) |
8.18 | Base de datos relacional |
| bcryptjs | 3.0 | Hash de contraseñas (factor 12) |
| Zod | 3.22 | Validación de datos en API (.strict()) |
| socket.io-client | 4.7 | Cliente WebSocket (preparado para realtime-service) |
| In-memory TTL cache | Custom | Cache server-side (30s TTL) |
| Rate Limiter | Custom | Sliding window para auth, chat y foro |
| Componente | Detalle |
|---|---|
| Motor | PostgreSQL |
| Tablas principales | users, census_votes, chat_messages, forum_threads, forum_votes, profile_customization |
| Migraciones | SQL files (000–017): users, candidatos, votos, chat, foro, customización, Google OAuth |
| Índices | Parciales, compuestos, funcionales para alto tráfico |
| Pool | pg.Pool con max 20 conexiones, timeout 5s |
| Herramienta | Uso |
|---|---|
| Bun | Runtime y package manager (bun run dev) |
| ESLint | Linting (eslint-config-next) |
| PostCSS + Autoprefixer | Procesamiento CSS |
| Docker | Containerización (Dockerfile + docker-compose + docker-stack) |
| Feature | Estado | Descripción |
|---|---|---|
| Fichas de 38 partidos | ✅ | Candidato presidencial, plan de gobierno, documentos JNE |
| Fichas de congresistas | ✅ | Diputados y senadores con fotos, trayectoria, patrimonio |
| PreCenso (votación) | ✅ | Wizard multi-step con selección de candidato |
| Ranking nacional | ✅ | Ranking en tiempo real con filtros por departamento |
| Estadísticas | ✅ | Dashboard con gráficos (barras, pie, área) |
| Mapa interactivo | ✅ | SVG del Perú coloreado por partido ganador por departamento |
| Chat global | ✅ | Mensajes, edición, eliminación, reacciones, presencia |
| Foro ciudadano | ✅ | Threads con votación, bloqueo, cierre de hilos |
| Quiz político | ✅ | Descubre tu afinidad política por dimensiones |
| Verificador de promesas | ✅ | Historial, financiamiento, reportes ciudadanos |
| Perfil de usuario | ✅ | Avatar, biografía, historial de votos |
| Customización SpaceHey | ✅ | Colores, fondos, tipografía, CSS custom, 10 presets |
| Dark mode | ✅ | Toggle claro/oscuro con persistencia |
| Auth completo | ✅ | Registro, login, Google OAuth, JWT sessions |
| Contador de votos animado | ✅ | Odómetro estilo flip con animación por dígito |
| Asistente IA | ✅ | Chat con Gemini para consultar candidatos, comparar propuestas y resolver dudas electorales |
Diseñadas para soportar 100K–1M+ usuarios concurrentes:
| Capa | Técnica |
|---|---|
| Backend | Promise.all() para queries paralelas en ranking (8), estadísticas (11) y mapa (4) |
| Backend | Cache TTL 30s en ranking, estadísticas y mapa/stats |
| API | Cache 5s en chat GET con invalidación por mutación (send/edit/delete) |
| Frontend | Optimistic UI en chat (send, react, edit, delete aparecen instantáneamente) |
| Frontend | localStorage stale-while-revalidate en todas las páginas de datos |
| Frontend | router.prefetch() de las 5 rutas principales en navbar mount |
| Frontend | Foto de perfil desde JWT session (0 API calls extra) |
| Frontend | Skeleton loading en Ranking, Estadísticas y Mapa (sin pantalla en blanco) |
| DB | loadChat() con subquery DESC + LIMIT 50 optimizada para índice |
| DB | Partial indexes para mensajes activos, spam check, votos por departamento |
| DB | Pool de 20 conexiones con fail-fast timeout de 5s |
24+ protecciones implementadas a nivel de código (ver SEGURIDAD.md para detalles completos):
| Categoría | Estado |
|---|---|
| XSS (Cross-Site Scripting) | ✅ Protegido |
| Clickjacking (Security Headers) | ✅ Protegido |
| Variables de Entorno | ✅ Protegido |
| Validación Cliente/Servidor | ✅ Protegido |
| Inyección SQL (SQLi) | ✅ Protegido |
| IDOR (Object Reference) | ✅ Protegido |
| Mass Assignment | ✅ Protegido |
| CSRF | ✅ Protegido |
| Rate Limiting | ✅ Protegido |
| Data Leakage | ✅ Protegido |
| SSRF | ✅ Protegido |
| Timing Attacks | ✅ Protegido |
| CSS Injection (customCSS) | ✅ Sanitizado |
- Bun ≥ 1.0 instalado
- PostgreSQL corriendo
- Variables de entorno:
DATABASE_URL,NEXTAUTH_SECRET,NEXTAUTH_URL - (Opcional)
GOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRETpara OAuth - (Opcional)
GOOGLE_GENERATIVE_AI_API_KEYpara el Asistente IA (obtener key)
cd apps/my-app
# Instalar dependencias
bun install
# Ejecutar migraciones de base de datos
psql $DATABASE_URL -f database/000_run_all.sql
# O una por una: 001_create_users.sql ... 017_profile_customization.sql
# Levantar frontend
bun run devbun run build
bun run startdocker compose -f infra/docker/docker-compose.yml upChat con inteligencia artificial integrado en /asistente-ia. Permite a los usuarios consultar información sobre candidatos, comparar propuestas de gobierno y resolver dudas sobre las elecciones de Perú 2026 usando Google Gemini 2.0 Flash.
Usuario (UI) → useChat (AI SDK v3) → POST /api/ai/chat → streamText (Gemini) → SSE stream → UI
- El usuario escribe en el chat (React, hook
useChatde Vercel AI SDK v3) - El frontend envía
messages[]via POST a/api/ai/chat(Next.js Route Handler) - El route handler usa
streamText()con el provider de Google (Gemini) para generar una respuesta en streaming - La respuesta se envía como stream (SSE) y se renderiza en tiempo real
| Decisión | Razón |
|---|---|
AI SDK v3 (ai@3.4.33) |
Compatibilidad con Next.js 14.2.0 — la v6 requiere Next.js 15+ |
| Llamada directa al LLM | El rag-service (FastAPI + Qdrant) se conectará en fase posterior para RAG |
| Estado en memoria del cliente | No persiste en base de datos por ahora |
| UI 100% custom | Usa la identidad visual de Sin Floros (paleta forest/perú), no clona la plantilla vercel/chatbot |
| Sistema independiente del chat humano | No interfiere con GlobalChat.tsx |
| Archivo | Propósito |
|---|---|
src/app/api/ai/chat/route.ts |
Route handler POST — bridge entre useChat y Gemini con streaming |
src/stores/ai-chat-store.ts |
Store Zustand — pageContext, selectedCandidates, selectedTopic |
src/app/asistente-ia/page.tsx |
Página principal — layout 2 columnas (sidebar controles + chat) |
src/components/ai-assistant/AIChatHeader.tsx |
Header de la sección con ícono y badge del modelo |
src/components/ai-assistant/AIMessageBubble.tsx |
Componente de mensaje (user/assistant) estilo fila |
src/components/ai-assistant/AIChatInput.tsx |
Textarea auto-resize con Enter para enviar |
src/components/ai-assistant/AIQuickActions.tsx |
Chips de acciones rápidas (educación, salud, economía, seguridad) |
src/components/ai-assistant/AICandidateCompare.tsx |
Selector de candidatos para comparación |
| Variable | Descripción | Requerida |
|---|---|---|
GOOGLE_GENERATIVE_AI_API_KEY |
API key de Google AI Studio para Gemini | Sí, para que funcione el chat |
Obtener key: https://aistudio.google.com/apikey (free tier disponible)
- Conectar FastAPI rag-service para respuestas con contexto real (RAG con Qdrant)
- Pipeline de ingesta: vectorizar JSONs de candidatos en
public/data/congresistas/ - Persistencia de conversaciones en base de datos
- Fallback multi-proveedor: Gemini → Groq → Cerebras
- Streaming desde FastAPI cuando se active el RAG
- Historial de conversaciones por usuario (requiere auth)
Las respuestas de Gemini incluyen formato Markdown (headers, listas, negritas, código, tablas). El componente AIMessageBubble.tsx usa react-markdown + remark-gfm para renderizarlas correctamente.
| Dependencia | Versión | Uso |
|---|---|---|
react-markdown |
10.x | Renderizado de Markdown a React |
remark-gfm |
4.x | Soporte para tablas, strikethrough, autolinks (GitHub Flavored Markdown) |
Elementos soportados con estilos custom (sin @tailwindcss/typography):
| Elemento | Estilo |
|---|---|
| Headings (h1–h3) | Tamaños escalonados, font-bold, color --chat-text-normal |
| Listas (ul/ol) | list-disc / list-decimal con marker color --peru-rojo |
| Código inline | Fondo --chat-bg-primary, color --peru-rojo, font-mono |
| Bloques de código | Fondo oscuro #1e1e1e, texto verde, overflow-x-auto |
| Blockquotes | Borde izquierdo --peru-rojo, texto --chat-text-muted, itálica |
| Tablas | Bordes --chat-border, header con fondo --chat-bg-primary |
| Links | Color --peru-rojo, hover:underline, target="_blank" |
Solo los mensajes del assistant usan ReactMarkdown. Los mensajes del usuario se renderizan como texto plano.
- AI SDK v3 es necesario mientras el proyecto use Next.js 14.x
- Si se actualiza a Next.js 15+, migrar a AI SDK v6:
toUIMessageStreamResponse(),DefaultChatTransport,sendMessage({text}),message.parts,statusen lugar deisLoading
MIT