NBA Feed
Your teams' news and games, with scores hidden until you reveal them.
Tu app de Pádel
Translation pending
Sports & fitnessTypeScript · PLpgSQLGitHub @amat3OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Loading the full README. The saved excerpt is shown below.
📖 Caso de estudio : el problema, las decisiones técnicas y lo que aprendí construyéndola 🎾 Demo con datos ficticios (jugadores de Los Simpson): pide las cuentas de prueba Inicio · Mixing · Sorteo · Publicar partido (demo con datos ficticios) ▶ Recorrido en vídeo (67 s) · starpoint es una PWA para un grupo de pádel: mixings semanales con sorteo de parejas, partidos publicados para buscar jugadores, ranking ELO y validación de resultados. Construida con Next.js 16, Supabase y Emotion, pensada solo para móvil.Read the full README ↗
starpoint es una PWA para un grupo de pádel: mixings semanales con sorteo de parejas, partidos publicados para buscar jugadores, ranking ELO y validación de resultados. Construida con Next.js 16, Supabase y Emotion, pensada solo para móvil.
pg_cron llama cada 15 minutos a /api/cron/generate-draws, que sortea y publica los mixing abiertos y completos (se queda con el mejor de 10 intentos, con las primeras pistas del club) y avisa a jugadores y admins. Si faltan jugadores no genera nada, avisa a los admins y reintenta hasta el inicio. El admin puede sortear a mano antes, y tras un Rehacer el automático no vuelve a actuar. Se apaga con AUTO_DRAW=false.Cualquier jugador puede publicar un partido (club, fecha, hora y cuántas palas busca, de 1 a 3) para completar sus 4 jugadores y 90 minutos, con un comentario opcional ("necesitamos una chica", "buscamos un revés"…). Se avisa al grupo por notificación push, aparece en "Lo que viene" y los demás se apuntan o se borran. Sin sorteo ni resultados.
La pantalla del partido muestra siempre los 4 puestos: el organizador, los jugadores que ya tiene cerrados fuera de la app (con el nombre que él les ponga), los que se apuntan y las plazas libres. El organizador puede añadir jugadores de fuera del grupo, renombrarlos o quitarlos, editar el partido o cancelarlo; desaparece al terminar.
Publicar escribiéndolo o dictándolo, con IA (solo en la demo). Encima del formulario hay una caja donde se describe el partido con palabras ("busco 2 para el jueves a las 19:00 en Padel Indoor, mejor un revés") o se dicta con el micrófono, y Claude Haiku 4.5 rellena el formulario. Nunca publica: el jugador revisa y publica.
ai_requests.src/lib/config.ts). El cálculo y la actualización de los 4 perfiles, el historial y el estado del partido ocurren en una única transacción de PostgreSQL (confirm_match_atomic).| Rol | Capacidades |
|---|---|
| Jugador | Inscribirse a mixings y partidos, publicar partidos, introducir y confirmar resultados, ver su historial |
| Admin | Todo lo anterior, más: crear y editar eventos, gestionar participantes e invitados, sorteo, partidos pendientes de todo el grupo, exclusiones y jugadores |
Un admin empieza en la vista de jugador y cambia a la de administración desde el menú del avatar (solo los admins tienen ese menú; el resto usa la pestaña Perfil). El registro de usuarios está cerrado: solo existen cuentas creadas por un admin.
Supabase Realtime en eventos, partidos e inscripciones; notificaciones push; instalable en pantalla de inicio. Al abrir la app desde cero se ve una splash animada (una vez por sesión) y los enlaces compartidos llevan una imagen de marca.
| Capa | Tecnología |
|---|---|
| Frontend | Next.js 16 (App Router), React 19 |
| Estilos | Emotion (tema claro y oscuro, con escalas cerradas de espaciado y tipografía, en src/theme.ts) |
| Backend / BD | Supabase (PostgreSQL, Auth, Realtime, RLS) |
| Despliegue | Vercel (cron semanal); pg_cron de Supabase para el cierre y el sorteo automáticos |
| Formularios | React Hook Form + Zod v4 |
| Iconos | Lucide React |
| IA | Claude Haiku 4.5 con el SDK de Anthropic (salidas estructuradas), Web Speech API para el dictado |
src/
├── app/ # Rutas: / · /mixing · /partido · /events/[id] · /history · /profile · /admin/*
│ ├── actions/ # Server Actions (events, matches, mixing-generator, admin-*, users…)
│ └── api/cron/ # create-weekly-event, close-pending-matches, generate-draws
├── components/
│ ├── atoms/ # Button, Input, Avatar, Select, Switch…
│ ├── molecules/ # Header, TabBar, Dialog, PlayerList, CourtCard…
│ └── organisms/ # EventOpenView, EventDrawView, EventGenerator, MatchEventView…
├── lib/ # rating-logic, mixing-algorithm, auto-draw, draw-publish, confirm-match, match-parser…
└── theme.ts # Tokens de diseño
supabase/ # Esquema completo, migraciones y jobs de pg_cron (se aplican a mano)
docs/ # Caso de estudio (es/en) y capturas
Más contexto técnico (reglas de privacidad, base de datos, convenciones y flujo de trabajo) en AGENT.md.
# 1. Clonar
git clone https://github.com/amat3/star-point.git
cd star-point
# 2. Instalar dependencias
npm install
# 3. Variables de entorno: crea .env.local con las claves de abajo
# 4. Desarrollo
npm run dev
NEXT_PUBLIC_SUPABASE_URL=https://xxxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...
SUPABASE_SERVICE_ROLE_KEY=eyJ... # solo servidor: operaciones de admin y cron
CRON_SECRET=... # protege /api/cron/*
NEXT_PUBLIC_VAPID_PUBLIC_KEY=... # notificaciones push
VAPID_PRIVATE_KEY=...
VAPID_SUBJECT=mailto:...
TEST_PUSH_USER_IDS=id1,id2 # opcional: quién recibe los avisos de los eventos de prueba
WEEKLY_EVENT_CREATED_BY=id # opcional: autor del evento semanal (por defecto, el primer admin)
PUSH_DISABLED=true # opcional, solo en local: no se envía ninguna notificación
AUTO_DRAW=false # opcional: apaga el sorteo automático sin redesplegar
NEXT_PUBLIC_DEMO=true # solo en el despliegue de demo: muestra el aviso, no crea eventos ni sortea solo y activa el relleno con IA
ANTHROPIC_API_KEY=sk-ant-... # solo en la demo: el relleno del partido con IA
AI_MATCH_PARSER=false # opcional: apaga el relleno con IA (mock, solo en local: respuestas de ejemplo sin llamar a la API)
El esquema completo está en supabase/supabase_schema_full.sql. Las migraciones y los jobs de pg_cron (cierre automático y sorteo automático) están en la misma carpeta, y se aplican a mano en Supabase. Los jobs llevan el marcador <CRON_SECRET>: el valor real se pone al ejecutarlos y nunca se sube al repositorio. Más detalles en AGENT.md.
La demo (datos ficticios de Los Simpson) es otro proyecto de Supabase y otro despliegue de Vercel con el mismo código y NEXT_PUBLIC_DEMO=true. Se reconstruye desde cero con npx tsx src/scripts/seed-demo.ts --apply --reset: solo lee .env.demo.local y se niega a ejecutarse contra cualquier otro proyecto.
rating-logic.test.ts), algoritmo de sorteo (mixing-algorithm.test.ts), sorteo automático (ventana de 3 horas y elección del mejor sorteo, auto-draw.test.ts), textos de la inscripción (event-capacity.test.ts), validación de lo que devuelve la IA (match-parser.test.ts) y utilidades de fechas y rondas (utils.test.ts).npx -y tsx src/scripts/eval-match-parser.ts (16 frases con los campos esperados, unos 5 céntimos por pasada).npm run test (una vez) / npm run test:watch (modo watch)..github/workflows/ci.yml) ejecuta en cada push a main y en cada PR: tsc --noEmit → eslint → vitest run → next build.e2e/, npm run test:e2e): 33 tests, 18 de ellos de accesibilidad (axe-core, WCAG 2.2 AA, en tema claro y oscuro, sin ningún problema de contraste ni de etiquetas; tutorial de cómo funciona axe), más los flujos reales: portada pública y redirección al login, acceso, la splash, publicar un partido, apuntarse y desapuntarse con otro usuario y cancelarlo. Corren solo contra la demo (una comprobación se niega a ejecutarse contra cualquier otra base de datos), usan selectores por rol y por etiqueta, y borran los partidos que crean aunque un test falle. Se ejecutan a mano en GitHub Actions (e2e.yml), contra la demo (la ejecución semanal está preparada y desactivada hasta que se den de alta sus secretos), y no en cada push para que una respuesta lenta de la base de datos no ponga el repositorio en rojo.Los parámetros del ELO se centralizan en src/lib/config.ts:
K_PROVISIONAL: 0.40 // K para jugadores con < 10 partidos
K_ESTABLISHED: 0.15 // K para jugadores establecidos
PROVISIONAL_LIMIT: 10 // Partidos para considerarse establecido
DISPARITY_FULL: 1.0 // Gap ≤ 1.0 → partido vale 100%
DISPARITY_ZERO: 2.5 // Gap ≥ 2.5 → partido vale 0%
DAMPENING_START: 4.5 // Desde aquí se reduce la volatilidad
DAMPENING_END: 6.5 // Aquí K queda al 60%
MATCH_WEIGHT: 0.70 // Peso del margen del resultado (subido desde 0.40 en jul-2026)
MIN_RATING: 0
MAX_RATING: 7
INITIAL_RATING: 3.5
Un cambio de parámetros puede recalcularse con carácter retroactivo sobre todo el historial con src/scripts/retroactive-match-weight.ts (dry-run por defecto).
Código publicado solo para consulta, como muestra de portfolio. Todos los derechos reservados: no se permite copiarlo, modificarlo ni reutilizarlo sin autorización por escrito. Ver LICENSE.
Creado con ❤️ para la comunidad de pádel.