Equipo RootWave · TINKU Hackathon 2026 · Sitio del evento · Problema · Guía técnica · Rúbrica
Producto listo para correr en local con un solo comando. Esta copia viva del README está enfocada en cómo funciona, qué requiere y cómo ponerla a funcionar. Los créditos del evento y el texto original del template están al final, y quedan versionados en
README.md.bk.
MiTechoRentable unifica la operación de +200 proyectos solares con inversores de múltiples proveedores (Growatt, Huawei, Deye, Hoymiles, SRNE) detrás de una sola consola con cuatro experiencias por rol. El objetivo es cumplir contrato, detectar fallas en menos de 5 minutos y eliminar +130 h/mes de trabajo manual.
| Rol | Landing post-login | Qué resuelve |
|---|---|---|
Cliente residencial (cliente) |
/dashboard |
Ahorro en COP, energía generada, CO₂ evitado, agenda de visitas, reportes PDF on-demand. |
Operaciones TR (operaciones) |
/operaciones/dashboard |
War Room de flota, fallas por zona, agenda de mantenimientos, comparativo multi-planta, analítica regional, gestión de técnicos. |
Cliente corporativo (corporativo) |
/corporativo/dashboard |
ROI solar vs objetivo contractual, registro KPI (Vo, Io, fp, Hz), tickets con SLA, riesgo financiero. |
Técnico de Campo (tecnico) |
/tecnico/ruta |
Ruta del día, telemetría en sitio, checklist de salud eléctrica, cierre con evidencias (buffer local para conectividad intermitente). |
- A · Intelligence Core (FastAPI): ingesta enriquecida con inferencia de magnitud, KPIs, generación de PDF y alertas HTTP/WS.
- B · Mission Control (React SPA): dashboards ejecutivos, War Room y consolas corporativa/residencial.
- C · Field Ops (React móvil / PWA): vistas técnico en sitio con sincronización idempotente.
Detalle de arquitectura, contrato Supabase ↔ FastAPI y flujo end-to-end: docs/ARCHITECTURE.md.
Inversores (Growatt, Huawei, Deye…)
│
▼
Middleware Tinku ──► FastAPI (uvicorn :8000) Mock-hub (tsx :4010)
(polling / APIs • POST /ingest • /stats/*
proveedor) • GET /stats, /alerts • /operations, /corporate, /technician/*
• GET /reports/generate (PDF) • panel override para demo
│ │
▼ │
Supabase (Postgres + Auth + RLS) │
▲ │
│ supabase-js (JWT) │
▼ │
React SPA (Vite :5173) ◄─────────────────────┘
Roles: cliente · operaciones · corporativo · tecnico
- Supabase = identidad + datos + RLS. Login/refresh/JWT/Realtime viven aquí; nunca en FastAPI.
- FastAPI = calculadora aislada. Valida JWT de Supabase, no reimplementa auth.
- Mock-hub = opcional para demo/pitch. Expone stats sintéticos y tiene un panel con sliders para "manipular data en vivo" sin recargar los frontends.
| Herramienta | Versión mínima | Para qué |
|---|---|---|
| Python | 3.13 | Backend FastAPI (uv lo gestiona). |
| uv | 0.5+ | Gestor Python y orquestador manage.py. |
| Node.js | 22 LTS | Frontend Vite y mock-hub. |
| pnpm | 10+ | Gestor de paquetes del frontend y mock-hub. |
| Supabase CLI | 2.0+ | Postgres + Auth locales (supabase start). |
| Docker Desktop / Engine | corriendo | Requerido por Supabase CLI para levantar Postgres local. |
| bash + curl | — | scripts/demo_smoke.sh. |
- Copia la plantilla:
cp .env.example .env(raíz del repo — Vite la lee víaenvDirdesdefrontend/vite.config.ts). - Reemplaza los placeholders
change-mepor passwords reales para los 4 usuarios demo (VITE_*_MOCK_PASSWORD). - Tras
supabase start, corresupabase statusy copiaAPI URLyanon keyaVITE_SUPABASE_URL/VITE_SUPABASE_ANON_KEYySUPABASE_URL/SUPABASE_JWT_SECRET.
Matriz completa de variables, consumidores y defaults: docs/ENVIRONMENT.md.
DATA_SOURCE=mock(default): snapshots locales + mock-hub. Ideal para demo/offline.DATA_SOURCE=live: requiereTINKU_BASE_URL+TINKU_API_KEY(entregados por el staff de la hackathon).
supabase start # una sola vez; levanta Postgres + Auth locales
./scripts/demo_smoke.sh # aplica migraciones + seed + arranca todo + valida loginsEl script:
- Arranca Supabase local si no está corriendo.
supabase db reset→ aplicasupabase/migrations/*ysupabase/seed.sql.- Corre
scripts/seed_demo_users.pyque crea los 4 usuarios demo (idempotente). - Levanta backend (8000) + frontend (5173) + mock-hub (4010) en background con
uv run manage.py runserver --simulate. - Hace
POST /auth/v1/token?grant_type=passwordcon cada rol — exit 0 ⇒ los 4 logins respondieron HTTP 200.
Al terminar, abre http://127.0.0.1:5173 e inicia sesión con cualquiera de los usuarios demo (ver §4.4). Para detener el stack:
kill $(cat /tmp/demo_smoke_runserver.pid)Desde la raíz del repo:
| Objetivo | Comando |
|---|---|
| Stack completo (API + UI) | uv run manage.py runserver |
| Stack completo + mock-hub (recomendado para demo) | uv run manage.py runserver --simulate |
Solo FastAPI (/health, /me, /stats, /reports/generate…) |
uv run manage.py backend → http://127.0.0.1:8000 |
| Solo Vite (React) | uv run manage.py frontend → http://localhost:5173 |
| Mock-hub dedicado | pnpm --dir mock-hub run mock-hub → http://127.0.0.1:4010 |
| Supabase (Auth + DB) | supabase start · estado: supabase status · reset: supabase db reset |
| Puerto custom del mock-hub | uv run manage.py runserver --simulate --mock-hub-port 4510 |
--simulateinyecta automáticamenteVITE_STATS_BASE_URL=http://127.0.0.1:<port>(mock-hub) yVITE_REPORTS_BASE_URL=http://127.0.0.1:8000(PDF backend) al proceso de Vite.
| Servicio | URL | Healthcheck |
|---|---|---|
| Frontend (Vite) | http://localhost:5173 | / |
| Backend (FastAPI) | http://127.0.0.1:8000 | /health |
| Mock-hub | http://127.0.0.1:4010 | /health |
| Supabase (Kong) | http://127.0.0.1:54321 | /auth/v1/health |
| Supabase Studio | http://127.0.0.1:54323 | panel web |
| Rol app | Rol DB (profiles.role) |
Org (slug) |
Email (VITE_*_MOCK_EMAIL) |
Entrada |
|---|---|---|---|---|
cliente |
client |
default |
cliente@solarpulse.local |
/dashboard |
operaciones |
operations |
tr-demo |
ops@techorentable.local |
/operaciones/dashboard |
corporativo |
corporate |
tr-demo |
corp@techorentable.local |
/corporativo/dashboard |
tecnico |
technician |
tr-demo |
tech@techorentable.local |
/tecnico/ruta |
Los passwords viven únicamente en tu
.envlocal (no committeado).scripts/seed_demo_users.pyes idempotente: re-ejecutarlo actualiza hashes, rol y organización sin duplicar filas.
Con el stack arriba, abre http://127.0.0.1:4010/ (preferentemente en modo incógnito). Es un panel HTML con sliders y selects que activa un overrideState server-side: cualquier request al mock-hub adopta los valores del panel en vez de sus query params, y los 4 frontends logueados reflejan los cambios sin recargar.
Scripteable desde terminal:
curl -X POST http://127.0.0.1:4010/sim/params \
-H 'Content-Type: application/json' \
-d '{"enabled":true,"params":{"scenario":"stress","faultMode":"degraded"}}'
curl -X POST http://127.0.0.1:4010/sim/params/reset # volver al baselineMás detalle: mock-hub/README.md.
tinku_team_root_wave/
├── backend/ # FastAPI (Python 3.13) — ingest, stats, reports, mvp
│ ├── main.py # app FastAPI + CORS + routers
│ ├── routers/ # ingest.py · stats.py · mvp.py · reports.py
│ ├── domain/ # inferencia magnitud, stats, plantillas PDF
│ ├── providers/ # Deye/Huawei/Growatt (mock + live Tinku)
│ ├── persistence/ # Supabase REST + stats_repo
│ └── tests/ # unit + integration + snapshots reales
├── frontend/ # React 19 + Vite 8 + TS + Tailwind v4
│ ├── src/pages/ # 28 vistas (cliente/operaciones/corporativo/técnico)
│ ├── src/components/ # AppShell, charts, shared, role-specific
│ ├── src/lib/ # API clients, Chart.js theming, fallbacks
│ └── src/auth/ # ProtectedRoute + ThemeContext
├── mock-hub/ # Node tsx — stats sintéticos + panel override
├── supabase/
│ ├── migrations/ # 4 migraciones P0 (organizations/profiles/RLS/seed roles)
│ └── seed.sql # datos de arranque
├── scripts/
│ ├── demo_smoke.sh # bootstrap + login smoke de los 4 roles
│ └── seed_demo_users.py # crea usuarios demo en Supabase local (idempotente)
├── docs/ # ARCHITECTURE · API_SPEC · ENVIRONMENT · REPORTS_PDF · …
├── manage.py # orquestador (backend + frontend + mock-hub)
├── pyproject.toml # ruff + mypy + bandit + uv workspace
└── .env.example # plantilla de variables (VITE_*, SUPABASE_*, TINKU_*)
Documentación profunda por tema:
docs/ARCHITECTURE.md— monolito modular Supabase-first, flujo end-to-end.docs/API_SPEC.yml— OpenAPI de FastAPI.docs/DATABASE.md— esquema Postgres + RLS.docs/MOCK_DATA.md— contratos del mock-hub.docs/REPORTS_PDF.md— pipeline de generación PDF.docs/USER_FLOWS.md— flujos por rol.docs/TEST.md— estrategia de testing.
cd backend
uv run pytest # 80+ tests (unit + integration + E2E snapshot)
uv run ruff check . # lint
uv run mypy . # type checkcd frontend
pnpm install
pnpm exec tsc --noEmit # type check
pnpm exec eslint . --max-warnings=0 # lint
pnpm test # vitest (58 tests)
pnpm run build # build producción./scripts/demo_smoke.sh # valida login HTTP 200 de los 4 roles- Frontend: estático (
pnpm run build→dist/). Sirve desde cualquier CDN. - FastAPI: un contenedor; requiere
SUPABASE_URL,SUPABASE_SERVICE_ROLE_KEY(solo servidor),SUPABASE_JWT_SECRET,INGEST_API_KEY. - Supabase: proyecto cloud con migraciones de
supabase/migrations/aplicadas. - Ingesta: middleware Tinku (o cron propio) que hace
POST /ingestconX-Ingest-Key.
Detalle en docs/ARCHITECTURE.md#despliegue-mvp.
| Síntoma | Causa probable | Fix |
|---|---|---|
supabase start queda colgado |
Docker no está corriendo | Arrancar Docker Desktop / systemctl start docker. |
Login devuelve invalid_credentials |
Passwords en .env desactualizados |
uv run python scripts/seed_demo_users.py re-siembra in-place. |
| Frontend no ve datos del mock-hub | VITE_STATS_BASE_URL sin definir |
Correr con --simulate o exportar la variable. |
PDF /reports/generate devuelve 404 |
Mock-hub no implementa reports | Backend debe estar arriba en :8000; verificar VITE_REPORTS_BASE_URL. |
| Puerto 4010 ocupado | Mock-hub previo colgado | --mock-hub-port 4510 o kill $(lsof -ti:4010). |
| JWT inválido en FastAPI | SUPABASE_JWT_SECRET no coincide |
Copiar de supabase status al .env y reiniciar backend. |
Distribuido bajo MIT (ver LICENSE). Durante la hackathon el repositorio es privado; al cierre pasa a público para que la comunidad pueda aprender, reutilizar y construir sobre lo que hicimos. 🌱
TINKU Hackathon 2026 · 18 horas · organizada por The Tribu y la Universidad Cooperativa de Colombia (sede Cartago), con Techos Rentables, Celsia Internet, Cursor y MiniMax.
Aliados: Persano · Flavors · La 7 Incluyente · Vinola.
Equipo RootWave: Juan Sebastian Valencia Londoño · Isabel Allssia Palacio Parra · Santiago Vera Loaiza.
El texto completo del template original del hackathon (bienvenida, línea de meta, principios, pasos sugeridos) se preserva en README.md.bk.
Hecho con 💛 por TINKU Hackathon 2026.