Skip to content

Repository files navigation

🇵🇪 Sin Floros — Plataforma de Transparencia Electoral Perú 2026

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


🏗 Arquitectura

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 pg Pool, sin ORM)
  • Runtime / Package Manager: Bun
  • Estilo visual: Neo-brutalist sticker design (bordes gruesos, colores peruanos, tipografía Frogie)

📁 Estructura del Proyecto

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

🛠️ Stack Tecnológico

Frontend

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

Backend

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

Base de Datos

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

Herramientas de Desarrollo

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)

🎨 Funcionalidades Principales

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

⚡ Optimizaciones de Rendimiento

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

🛡️ Seguridad

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

🚀 Quick Start

Requisitos

  • Bun ≥ 1.0 instalado
  • PostgreSQL corriendo
  • Variables de entorno: DATABASE_URL, NEXTAUTH_SECRET, NEXTAUTH_URL
  • (Opcional) GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET para OAuth
  • (Opcional) GOOGLE_GENERATIVE_AI_API_KEY para el Asistente IA (obtener key)

Desarrollo Local

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 dev

Producción

bun run build
bun run start

Docker

docker compose -f infra/docker/docker-compose.yml up

🤖 Asistente IA

Chat 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.

Arquitectura

Usuario (UI) → useChat (AI SDK v3) → POST /api/ai/chat → streamText (Gemini) → SSE stream → UI
  1. El usuario escribe en el chat (React, hook useChat de Vercel AI SDK v3)
  2. El frontend envía messages[] via POST a /api/ai/chat (Next.js Route Handler)
  3. El route handler usa streamText() con el provider de Google (Gemini) para generar una respuesta en streaming
  4. La respuesta se envía como stream (SSE) y se renderiza en tiempo real

Decisiones técnicas

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

Archivos

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 de entorno

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)

Roadmap Asistente IA

  • 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)

Renderizado de Markdown

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.

Notas de compatibilidad

  • 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, status en lugar de isLoading

📝 Licencia

MIT

About

Main web platform for Sin Floros

Resources

Stars

1 star

Watchers

0 watching

Forks

Contributors

Languages