| title | Quiniela FIFA 2026 |
|---|---|
| emoji | ⚽ |
| colorFrom | green |
| colorTo | blue |
| sdk | docker |
| app_port | 7860 |
| pinned | false |
Implementacion inicial MVP.
- Registro por correo + password con captcha matematico local.
- Verificacion por codigo de 6 digitos enviado por correo.
- Estado de usuario pendiente/aprobado (sin rechazo definitivo).
- Predicciones por partido con bloqueo de edicion 5 minutos antes del kickoff (UTC).
- Leaderboard con puntaje 3/1/0 y desempate por:
- mas aciertos exactos
- orden alfabetico
- Panel admin para:
- aprobar usuarios
- crear/editar grupos
- crear/editar equipos
- crear/editar partidos
- Leaderboard global y leaderboard por grupo.
- Comando para crear admin inicial.
- PHP 8.4+
- Composer
- PostgreSQL en localhost:5432
- DB: quiniela2026
- Usuario DB: ver
.env.local(ej.postgres) - SMTP dev recomendado: Mailpit o Mailhog (ejemplo: 127.0.0.1:1025)
- Orden de carga de variables Symfony:
.env.env.local.env.$APP_ENV.env.$APP_ENV.local
- En local usa
.env.localpara secretos y overrides de tu maquina. - No guardes secretos reales de produccion en archivos versionados.
- En produccion define secretos como variables del servidor (o Symfony secrets).
- Copia
.env.local.examplea.env.localy ajusta variables:- MAILER_FROM_EMAIL
- MAILER_FROM_NAME
- Instala dependencias:
composer install- Ejecuta migraciones:
php bin/console doctrine:migrations:migrate --no-interaction- Crea admin inicial:
php bin/console app:create-admin "Admin" "admin@quiniela.local" "Admin2026!Strong"- Arranca servidor local:
symfony serve -d- Crear grupos A-L de fase de grupos:
php bin/console app:seed-group-stage- Importar equipos oficiales por grupo desde CSV:
php bin/console app:import-group-teams data/group_teams_template.csv- Importar partidos de fase de grupos desde CSV:
php bin/console app:import-group-fixtures data/worldcup2026_group_fixtures.csv- Sincronizar horarios UTC oficiales de FIFA (actualiza existentes de forma idempotente):
php bin/console app:sync-official-group-fixturesFormato CSV:
group_code,kickoff_at_utc,home_code,away_code
A,2026-06-11 19:00,MEX,RSA
A,2026-06-12 02:00,KOR,CZE- Registro correo: /register
- Login: /login
- Validar codigo: /verify/code
- Predicciones: /predictions
- Leaderboard: /leaderboard
- Admin: /admin
Actualmente solo están cargados los partidos de la fase de grupos. A medida que se definan los partidos de las fases eliminatorias (round of 32, round of 16, cuartos, semifinal, tercer puesto y final) se irán agregando.
- Equipos por grupo: data/worldcup2026_group_teams.csv
- Partidos fase de grupos: data/worldcup2026_group_fixtures.csv
Fuente utilizada para construir el dataset:
- CSRF activo en login, aprobacion admin y guardado de predicciones.
- Regla de tiempo se valida en backend (no solo UI).
- En prod usa
APP_ENV=prodyAPP_DEBUG=0. - En prod usa usuario DB dedicado (no
root). - La app ahora redirige a HTTPS en
prodcomo fallback. Aun asi, el redirect principal debe vivir en Apache/Nginx para cubrir assets y requests antes de PHP.
- Para Gmail personal usa App Password (2FA obligatorio).
MAILER_FROM_EMAILnormalmente debe coincidir con la cuenta autenticada en Gmail para evitar rechazos o reescritura del remitente.- Ejemplo DSN para produccion:
MAILER_DSN="smtp://tu_cuenta@gmail.com:TU_APP_PASSWORD@smtp.gmail.com:587?encryption=tls&auth_mode=login"
MAILER_FROM_EMAIL=tu_cuenta@gmail.com
MAILER_FROM_NAME="Quiniela 2026"- Prueba tecnica de envio:
php bin/console mailer:test tu_correo@dominio.com- Prueba funcional:
- Registrar usuario nuevo en
/register - Confirmar recepcion de codigo
- Validar en
/verify/code
- Registrar usuario nuevo en
DocumentRootdebe apuntar apublic/, no a raiz proyecto.- Activa
mod_rewritey TLS antes de exponer sitio. - Define variables de prod en servidor, no en archivos versionados.
- Usa mismo correo en
MAILER_FROM_EMAILy cuenta SMTP autenticada si sales por Gmail. - Si app corre detras de proxy o balanceador, define
SYMFONY_TRUSTED_PROXIESySYMFONY_TRUSTED_HOSTSpara que Symfony detecte bien HTTPS y host real. - Tienes plantillas base listas en
deploy/apache/quiniela2026.confydeploy/prod.env.example.
Ejemplo minimo de variables de entorno para prod:
APP_ENV=prod
APP_DEBUG=0
APP_SECRET=pon_aqui_un_secreto_largo_y_random
DATABASE_URL="postgresql://app_user:STRONG_PASSWORD@127.0.0.1:5432/quiniela2026?serverVersion=16&charset=utf8"
MAILER_DSN="smtp://tu_cuenta@gmail.com:TU_APP_PASSWORD@smtp.gmail.com:587?encryption=tls&auth_mode=login"
MAILER_FROM_EMAIL=tu_cuenta@gmail.com
MAILER_FROM_NAME="Quiniela 2026"
# Solo si hay proxy inverso / load balancer:
# SYMFONY_TRUSTED_PROXIES=127.0.0.1,REMOTE_ADDR
# SYMFONY_TRUSTED_HOSTS='^(quiniela2026\.com|www\.quiniela2026\.com)$'Ejemplo base de VirtualHost Apache:
<VirtualHost *:80>
ServerName quiniela2026.com
ServerAlias www.quiniela2026.com
Redirect permanent / https://quiniela2026.com/
</VirtualHost>
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName quiniela2026.com
ServerAlias www.quiniela2026.com
DocumentRoot /var/www/quiniela2026/public
<Directory /var/www/quiniela2026/public>
AllowOverride All
Require all granted
FallbackResource /index.php
</Directory>
SSLEngine on
SSLCertificateFile /ruta/fullchain.pem
SSLCertificateKeyFile /ruta/privkey.pem
SetEnv APP_ENV prod
SetEnv APP_DEBUG 0
ErrorLog ${APACHE_LOG_DIR}/quiniela2026_error.log
CustomLog ${APACHE_LOG_DIR}/quiniela2026_access.log combined
</VirtualHost>
</IfModule>Checklist rapido post-deploy:
php bin/console about --env=prodphp bin/console doctrine:migrations:migrate --no-interaction --env=prodphp bin/console cache:clear --env=prodphp bin/console cache:warmup --env=prodphp bin/console mailer:test tu_correo@dominio.com --env=prod- Abrir sitio por
https://...y confirmar quehttp://...redirige a HTTPS. - Verificar registro, llegada de correo y login.
La app corre como Docker Space (sdk: docker, puerto 7860). El repo incluye Dockerfile y .dockerignore.
Cada push a master en GitHub dispara .github/workflows/huggingface.yml, que sincroniza el codigo al Space racsovzla/quiniela2026.
Requisito: secret HF_TOKEN en GitHub con permiso de escritura al Space.
Define en Settings → Variables and secrets del Space (ver tambien deploy/prod.env.example):
APP_ENV=prodAPP_DEBUG=0APP_SECRET(random largo)DATABASE_URL(Postgres externo, ej. Neon/Supabase)MAILER_DSN,MAILER_FROM_EMAIL,MAILER_FROM_NAMECALLMEBOT_PHONE,CALLMEBOT_APIKEY(WhatsApp desde el panel admin)MESSENGER_TRANSPORT_DSN=sync://
Estas variables alimentan la app web (incluido el boton Probar WhatsApp en /admin).
Los cron jobs no corren dentro del Space; se ejecutan via GitHub Actions + cron-job.org:
send-prediction-emails.yml— correos y WhatsApp 5 min antes de cada partidosync-live-fixture-scores.yml— sincroniza marcadores en vivo
Los mismos secrets deben existir en GitHub (repo → Settings → Secrets), incluyendo CALLMEBOT_PHONE y CALLMEBOT_APIKEY, y el workflow correspondiente debe estar en master.
php bin/console doctrine:migrations:migrate --no-interaction --env=prod
php bin/console app:seed-group-stage --env=prod
php bin/console app:import-group-teams data/worldcup2026_group_teams.csv --env=prod
php bin/console app:import-group-fixtures data/worldcup2026_group_fixtures.csv --env=prod
php bin/console app:create-admin "Admin" "admin@tu-dominio.com" "PasswordSegura2026!"- Registro por correo completo.
- Crear y bloquear predicciones segun ventana de tiempo.
- Leaderboard responde.
- Boton Probar WhatsApp en admin llega al telefono.
- Tras el proximo partido, revisar log de GitHub Actions para confirmar envio de correos/WhatsApp.
- Auditoria de cambios de predicciones (historial por usuario/partido).
- Notificaciones (recordatorio previo al cierre de ventana).
- Premios de temporada (insignias persistentes por hitos).
- Mejoras adicionales de accesibilidad (navegacion con teclado y foco en modales).
- Verificacion por codigo reforzada con:
- CSRF en validar y reenvio
- rate limit de intentos de validacion
- rate limit de reenvio de codigo
- flujo de reenvio para evitar bloqueo por codigo expirado
- Login reforzado con
login_throttling. - Predicciones con estado por partido (abierta/cerrada) y countdown de cierre en UI.
- Leaderboard actualizado:
- ranking semanal (ultimos 7 dias)
- insignias por desempeno
- racha activa por usuario
- tarjeta de "Pick del dia"
- Tests agregados para auth verify, scoring y ventana de prediccion.