BikeControl (SwiftControl)
使用 Zwift Click、Zwift Play、Shimano Di2 或任何藍牙控制器,搭配 MyWhoosh、Rouvy、Zwift 等。iOS、Android、Windows、macOS 均可免費試用。
AI 翻译
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
⚽ Club 90 Minutos — Polla Liga BetPlay Club 90 Minutos es una aplicación web de pronósticos deportivos (quiniela/polla) para la Liga BetPlay colombiana. Los participantes pronostican resultados de partidos, goleadores, campeón, finalistas y clasificados a cuadrangulares, y acumulan puntos según la precisión de sus predicciones. • Node.js ≥ 18 • npm ≥ 9 • PostgreSQL (o cuenta en Neon para BD en la nube) La app estará disponible en http://localhost:3001. Crear un archivo .env basado en .env.example:查看完整 README ↗
Club 90 Minutos es una aplicación web de pronósticos deportivos (quiniela/polla) para la Liga BetPlay colombiana. Los participantes pronostican resultados de partidos, goleadores, campeón, finalistas y clasificados a cuadrangulares, y acumulan puntos según la precisión de sus predicciones.
🌐 Producción: club90minutos.com
| Capa | Tecnología |
|---|---|
| Framework | Next.js 15 (App Router) |
| UI | React 19 |
| Lenguaje | TypeScript 5 |
| Base de Datos | PostgreSQL (Neon) |
| ORM | Prisma 6 |
| IA | Google Gemini (trivia, oráculo, crónicas) |
| Resend | |
| Gráficos | Recharts |
| Iconos | Lucide React |
| Datos en vivo | ESPN API (pública, sin autenticación) |
| Hosting | Hostinger (Node.js hosting) |
# 1. Clonar el repositorio
git clone https://github.com/tu-usuario/Club90minutos.git
cd Club90minutos
# 2. Instalar dependencias
npm install
# 3. Configurar variables de entorno
cp .env.example .env
# Editar .env con tus credenciales (ver sección siguiente)
# 4. Generar el cliente de Prisma
npx prisma generate
# 5. Aplicar el esquema a la base de datos (primera vez)
npx prisma db push
# 6. Levantar en modo desarrollo
npm run dev
La app estará disponible en http://localhost:3001.
Crear un archivo .env basado en .env.example:
| Variable | Descripción | Ejemplo |
|---|---|---|
DATABASE_URL | URL de conexión a PostgreSQL (pooled/connection pooler) | postgresql://user:pass@host:5432/dbname?sslmode=require |
DIRECT_URL | URL directa a PostgreSQL (para migraciones Prisma) | postgresql://user:pass@host:5432/dbname?sslmode=require |
NEXT_PUBLIC_APP_URL | URL pública de la app (para links en emails) | https://club90minutos.com |
RESEND_API_KEY | API Key de Resend para envío de emails | re_xxxxxxx |
SYNC_LIVE_SECRET | Secreto para proteger el endpoint /api/sync-live | Generar con: node -e "console.log(require('crypto').randomBytes(24).toString('hex'))" |
Club90minutos/
├── prisma/
│ └── schema.prisma # Esquema de base de datos (14 modelos)
├── public/
│ ├── images/ # Imágenes generales
│ ├── marca/ # Logos y branding
│ └── robots.txt
├── docs/
│ ├── api/ # Documentación de endpoints
│ ├── guias/ # Guías operativas (pgAdmin, etc.)
│ ├── internal/ # Notas técnicas de desarrollo
│ └── reglas-puntuacion.md # Reglas del juego documentadas
├── scripts/
│ ├── mantenimiento/ # Scripts recurrentes (sync maestro, reliquidar)
│ └── hotfixes/ # Correcciones puntuales ya ejecutadas
├── src/
│ ├── middleware.ts # Basic Auth para Vercel (staging)
│ ├── lib/
│ │ ├── db.ts # Singleton de Prisma Client
│ │ ├── calculadorPuntos.ts # ⭐ Motor de cálculo de puntos
│ │ ├── syncLive.ts # Sincronización en vivo con ESPN
│ │ └── tablaFija.ts # Datos fijos de tabla de posiciones
│ └── app/
│ ├── globals.css # Estilos globales
│ ├── layout.tsx # Layout raíz (metadata, fuentes, Toaster)
│ ├── page.tsx # Landing pública (/)
│ ├── error.tsx # Error boundary de ruta
│ ├── global-error.tsx # Error boundary global
│ ├── not-found.tsx # Página 404
│ ├── dashboard/
│ │ └── page.tsx # ⭐ App principal (login + dashboard completo)
│ ├── components/
│ │ ├── TablaPosicionesAfiche.tsx
│ │ ├── PronosticosPartidoAfiche.tsx
│ │ ├── PronosticosTorneoAfiche.tsx
│ │ ├── CentralDatosView.tsx
│ │ ├── TriviaModal.tsx
│ │ └── TerminosCompletos.tsx
│ ├── api/ # 24 endpoints (ver docs/api/)
│ │ ├── admin/ # Cargar/quitar resultados, reliquidar
│ │ ├── auth/ # Registro, login, reset password
│ │ ├── ai/ # Trivia, oráculo, crónica, noticias
│ │ ├── consolidados/ # Datos consolidados + export Excel
│ │ ├── cron/ # Sincronización automática ESPN
│ │ ├── datos-maestros/ # Equipos, partidos, jugadores
│ │ ├── guardar-pronosticos/
│ │ ├── sync-live/ # Marcadores en tiempo real
│ │ └── validar-usuario/ # Autenticación por sesión
│ ├── construccion/ # Página "en construcción"
│ ├── recuperar-password/
│ ├── restablecer-password/
│ └── terminos/ # Términos y condiciones
├── .env.example
├── .gitignore
├── next.config.mjs
├── package.json
└── tsconfig.json
erDiagram
Rol ||--o{ Usuario : tiene
Usuario ||--o| PrediccionInicial : crea
Usuario ||--o{ PrediccionPartido : envía
Usuario ||--o{ Puntaje : acumula
Usuario ||--o{ ResultadoOficial : ingresa
Equipo ||--o{ Jugador : tiene
Equipo ||--o{ Partido : "juega como local"
Equipo ||--o{ Partido : "juega como visitante"
Partido ||--o| ResultadoOficial : tiene
Partido ||--o{ PrediccionPartido : recibe
Partido ||--o{ Puntaje : genera
ResultadoOficial ||--o{ ResultadoGoleador : registra
Jugador ||--o{ ResultadoGoleador : anotó
PrediccionInicial ||--o{ PrediccionClasificado : incluye
| Modelo | Descripción |
|---|---|
Usuario | Participantes y administradores (con sesión por token) |
Equipo | 20 equipos de la Liga BetPlay |
Jugador | Jugadores por equipo (para predicción de goleador) |
Partido | Calendario completo con estados (programado → puntaje_calculado) |
PrediccionInicial | Predicciones de torneo (campeón, finalistas, clasificados, goleador) |
PrediccionPartido | Marcador predicho + goleador por partido |
ResultadoOficial | Marcador real + goleadores reales |
Puntaje | Puntos otorgados por categoría por partido |
| Categoría | Puntos | Condición |
|---|---|---|
| Ganador / Empate | 3 | Acertar quién gana (o empate) |
| Marcador Exacto | 5 | Acertar el marcador exacto (adicional al ganador) |
| Goleador | 2 | Acertar a uno de los goleadores del partido |
| Clasificados a Cuadrangulares | 3 c/u | Por cada equipo acertado de los 8 clasificados |
| Finalistas | 5 c/u | Acertar los 2 finalistas |
| Campeón | 10 | Acertar el campeón del torneo |
| Goleador del Torneo | 5 | Acertar al máximo goleador |
ℹ️ Ver documentación detallada en
docs/reglas-puntuacion.md.
| Comando | Descripción |
|---|---|
npm run dev | Servidor de desarrollo (puerto 3001) |
npm run build | Build de producción (prisma generate + next build) |
npm run start | Servidor de producción (puerto 3001) |
npm run db:generate | Regenerar Prisma Client |
npm run db:studio | Abrir Prisma Studio (GUI de BD) |
El repositorio está conectado a Hostinger con deploy automático vía GitHub:
npm run build automáticamente⚠️ Importante: El build de Hostinger puede fallar silenciosamente. Después de cada push, verificar que el sitio cargue correctamente en club90minutos.com.
Configurar las mismas variables del .env en el panel de hPanel → Node.js → Variables de entorno.
La app se conecta a la API pública de ESPN para:
/api/sync-live): Actualiza los marcadores de partidos en curso automáticamente.STATUS_FULL_TIME, el sistema calcula los puntos de todos los participantes automáticamente./api/cron/espn): Endpoint diseñado para ser llamado por un cron job externo cada N minutos durante la jornada.localStorage (sin JWT).next.config.mjs.bcryptjs.participante y administrador — el panel de admin solo es visible para rol administrador.Proyecto privado. Todos los derechos reservados.