Aplicación de competencia de canto compuesta por tres proyectos independientes y una API backend.
hack-a-thon/
├── app/ → Flutter (iOS & Android)
├── backend/ → Express.js + PostgreSQL (API REST)
├── frontend/ → React (Admin Panel)
└── docs/ → Documentos del proyecto
| Herramienta | Versión mínima | Para qué |
|---|---|---|
| Node.js | 20+ | backend + frontend |
| npm | 9+ | backend + frontend |
| Flutter SDK | 3.11+ | app móvil |
| PostgreSQL | 14+ (Railway ya incluido) | base de datos |
cd backend
npm installCopia .env.example a .env y completa los valores:
cp .env.example .envVariables clave:
| Variable | Descripción | Ejemplo |
|---|---|---|
PORT |
Puerto del servidor | 3000 |
DATABASE_URL |
URL de conexión PostgreSQL | postgresql://user:pass@host:port/db |
JWT_SECRET |
Secreto para firmar tokens JWT | cadena aleatoria larga |
CORS_ORIGINS |
Orígenes permitidos (separados por coma) | http://localhost:5173 |
BACKEND_URL |
URL pública del backend (para URLs de archivos) | http://localhost:3000 |
DEMO_MODE |
Acepta cualquier OTP/código de verificación | true |
STORAGE_TYPE |
bucket (S3-compatible) o local (disco) |
bucket |
STORAGE_ENDPOINT |
Endpoint del bucket S3 | https://t3.storageapi.dev |
STORAGE_ACCESS_KEY |
Access key del bucket | — |
STORAGE_SECRET_KEY |
Secret key del bucket | — |
STORAGE_BUCKET |
Nombre del bucket | — |
# Ejecutar todas las migraciones (crear tablas)
npm run migrate
# Ejecutar todos los seeds en orden
npm run seed
# Solo el seed del admin (01)
npm run seed:adminnpm run devEl servidor queda disponible en http://localhost:3000.
npm startGET /health
cd frontend
npm installCrea un archivo .env con:
VITE_API_BASE_URL=http://localhost:3000/apiSi no se define, apunta a
http://localhost:3000/apipor defecto (versrc/services/api.js).
npm run devEl panel queda disponible en http://localhost:5173.
npm run build
# Los archivos estáticos quedan en dist/- Dashboard — Contador del concurso en vivo, métricas de usuarios y submissions, gráficas de área
- User Management — Buscar, ver detalles, archivar y reactivar usuarios
- Reports — Revisar contenido reportado, eliminar submissions, archivar reportes
- Contests — Crear y gestionar concursos con 3 canciones
- Winners — Historial de ganadores
- My Account — Editar perfil del administrador
- Modo oscuro / claro — Toggle en la topbar, persiste en
localStorage
- Android Studio (para Android) o Xcode (para iOS)
- Android SDK / emulador configurado
cd app
flutter pub getEl emulador de Android usa 10.0.2.2 para acceder al localhost del host:
# Ya configurado por defecto en lib/core/api.dart
API_BASE_URL = http://10.0.2.2:3000/api ← Android emulator
API_BASE_URL = http://localhost:3000/api ← iOS simulator
Para cambiar la URL en tiempo de compilación:
flutter run --dart-define=API_BASE_URL=http://TU_IP:3000/api# Verificar dispositivos disponibles
flutter devices
# Ejecutar en el emulador o dispositivo conectado
flutter runflutter run -d iosflutter build apk --release| Sección | Pantallas |
|---|---|
| Auth | Splash/Welcome, Create Account (5 pasos), Phone Verify, Sign In, Forgot Password (5 pasos), Account Created |
| Onboarding | Welcome Slides (Grand Prize), Permissions, Contest Rules, Subscription, Gestures Tutorial |
| Home | Feed TikTok-style con video player real, countdown del concurso, vote API, report API, filtros |
| Contest | Contest Details, Upload Entry, In-App Video, Video Trim, Karaoke Recorder, Audio Trim, Submit Entry, Winner |
| Perfil | Menu Drawer, Account Settings, Artist Profile, Upload Photo, Followers, Vote History, Subscription, Notifications, Terms/Privacy |
| Social Login | Google Sign-In, Apple Sign-In, Facebook Login (Android & iOS) |
Los seeds se ejecutan en orden (01 → 02 → 03) con npm run seed desde el directorio backend/.
Crea el usuario administrador inicial para acceder al panel web.
| Campo | Valor |
|---|---|
admin@wonhitwonder.com |
|
| Password | Admin1234! |
| Rol | admin |
El seed es idempotente: si el usuario ya existe, no lo duplica.
Crea 3 usuarios de prueba para la app móvil con los mismos datos base.
| Nombre | Password | Artist Name | |
|---|---|---|---|
| Sara Johnson | sara.johnson@demo.com |
Demo1234! |
Sara Johnson |
| Mike Rivers | mike.rivers@demo.com |
Demo1234! |
Mike Rivers |
| Luna Star | luna.star@demo.com |
Demo1234! |
Luna Star |
Todos tienen
subscription_tier = "all_access"para poder explorar todas las funcionalidades. El seed es idempotente: no duplica usuarios si ya existen.
Crea el concurso activo y submissions de ejemplo para poblar el feed de la app.
Contest creado:
| Campo | Valor |
|---|---|
| Quarter | Q2 2026 |
| Estado | active |
| Inicio | Fecha actual |
| Fin | 14 días después |
| Canción 1 | Achy Breaky Heart |
| Canción 2 | Rolling in the Deep |
| Canción 3 | Don't Stop Believin' |
Submissions creadas (5 en total):
| Usuario | Canción | Tipo | Votos |
|---|---|---|---|
| Sara Johnson | Song #1 — Achy Breaky Heart | video | 247 |
| Mike Rivers | Song #2 — Rolling in the Deep | video | 89 |
| Luna Star | Song #3 — Don't Stop Believin' | video | 312 |
| Sara Johnson | Song #2 — Rolling in the Deep | video | 55 |
| Mike Rivers | Song #1 — Achy Breaky Heart | audio | 178 |
Los videos usan el CDN público de Google (gtv-videos-bucket) y funcionan directamente en el video_player de Flutter sin configuración adicional.
El seed es idempotente: si el contest o las submissions ya existen, no los duplica.
Con DEMO_MODE=true en el backend (valor por defecto en desarrollo):
- Phone verification: acepta cualquier código de 4 dígitos (la app muestra un banner informativo)
- Forgot password: acepta cualquier código en el paso de reset (la app muestra un banner informativo)
Útil mientras no se integra un proveedor de SMS / correo real. Para desactivarlo en producción, establece DEMO_MODE=false.
Los tres servicios tienen configuración lista para Railway:
railway.toml— configuración de build y start para el backenddocker-compose.yml— para desarrollo local con Docker- Cada proyecto tiene su propio
Dockerfile
Para desplegar, conecta el repositorio en Railway, crea un servicio por directorio (backend/, frontend/) y configura las variables de entorno correspondientes.
| Proyecto | Stack |
|---|---|
| Backend | Node.js, Express 5, Knex, PostgreSQL, JWT, bcrypt, multer, AWS SDK v3 (S3-compatible), helmet, cors |
| Frontend | React 19, Vite, React Router, TanStack Query, Recharts, Lucide Icons |
| App | Flutter 3.11, Riverpod, go_router, Dio, video_player, camera, google_sign_in, sign_in_with_apple, flutter_facebook_auth |