BikeControl (SwiftControl)
使用 Zwift Click、Zwift Play、Shimano Di2,或任何藍牙控制器搭配 MyWhoosh、Rouvy、Zwift 等。可於 iOS、Android、Windows 與 macOS 免費試用。
AI 翻譯
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
Racha de gimnasio a escala del universo. PWA en Next.js + Supabase + three.js. La especificación vive en CLAUDE.md (índice) y spec/ (por tema). CLAUDE.md es lo único que se lee siempre.檢視完整 README ↗
Racha de gimnasio a escala del universo. PWA en Next.js + Supabase + three.js.
La especificación vive en CLAUDE.md (índice) y spec/ (por tema). CLAUDE.md es lo único que se lee siempre.
Supabase: crear un proyecto en supabase.com (región sa-east-1, São Paulo, es la más cercana).
En el SQL Editor del proyecto, pegar y ejecutar entero supabase/schema.sql. Eso crea tablas, triggers de racha, RLS y los buckets de storage.
En Authentication → Providers, activar Email y Google (para Google hay que cargar Client ID/Secret de Google Cloud Console).
En Authentication → URL Configuration:
http://localhost:3020 (cambiar a la URL de Vercel al deployar)http://localhost:3020/auth/callback — alta por correo y login con Googlehttp://localhost:3020/auth/recuperar — recuperar contraseñahttps://TU-APP.vercel.app cuando haya deploySi falta el de recuperar, el correo llega pero el enlace rebota al login.
Copiar .env.example a .env.local y completar con la URL y la anon key del proyecto (Settings → API).
npm install y npm run dev → http://localhost:3020
npx vercel link
npx vercel env add NEXT_PUBLIC_SUPABASE_URL
npx vercel env add NEXT_PUBLIC_SUPABASE_ANON_KEY
npx vercel --prod
npm run test:db
Corre supabase/schema.sql contra un Postgres real (PGlite, en WASM) con stubs
de lo que aporta Supabase, y verifica la matemática de racha, rangos, planeta del
día, pérdida (−10), días de descanso, permisos y políticas de RLS. No necesita
cuenta ni red. Correrlo después de tocar el schema.
npm run test:conexion
Chequeo de humo contra el Supabase real: confirma que .env.local está bien,
que el schema está aplicado y que nada queda abierto a usuarios sin sesión.
Solo lee; no crea ni modifica nada.
npm run test:e2e
Flujo completo contra el Supabase real con dos cuentas: alta, onboarding,
registrar días, escalera de rangos, fotos con visibilidad, amistad, reto,
pérdida de racha y el aislamiento del §4. Crea datos y los limpia al final.
Necesita E2E_EMAIL en .env.local y "Confirm email" apagado (ver abajo).
Cuando alguien manda una sugerencia, llega un mail. Usa Resend, el mismo servicio que después sirve de SMTP para Auth: se configura una sola vez.
Lo que hay que crear (todo en el navegador, no hace falta CLI):
[email protected], que solo entrega a tu
propia dirección — alcanza para las sugerencias, no para la beta.sugerencia-mail, y pegar el contenido de
supabase/functions/sugerencia-mail/index.ts.RESEND_API_KEY — la clave del paso 2MAIL_DESTINO — la casilla donde querés recibir las sugerenciasMAIL_REMITENTE — Ascent <[email protected]> (o el del dominio propio)WEBHOOK_SECRET — una cadena larga inventada, la que quierasfeedback, evento InsertPOSThttps://<proyecto>.functions.supabase.co/sugerencia-mail)x-ascent-secreto con el mismo valor del WEBHOOK_SECRETEse header es lo único que impide que cualquiera que descubra la URL nos haga mandar correos, así que no puede faltar.
Nada de esto está en el camino crítico hoy. El plan es terminar la web,
usarla el dueño solo una o dos semanas cazando bugs, pasarla a nativo con Expo,
y recién ahí marketing. Sin usuarios ajenos no hace falta ninguna de las cinco
cosas de abajo: el proyecto se queda en el plan Free, con "Confirm email"
apagado —que es lo que deja correr npm run test:e2e— y con las cuentas de
prueba como están.
Queda escrito acá porque el día que haya gente hay que hacerlo entero, y averiguarlo dos veces sale caro. Las primeras dos bloquean a las demás.
El SMTP de cortesía de Supabase da 2 correos por hora por destinatario y está pensado solo para probar. Con cinco testers se agota entre confirmaciones de alta y recuperaciones de contraseña, y la gente queda sin poder entrar.
Hace falta un dominio propio. Resend exige un dominio verificado para
mandar por SMTP; [email protected] solo entrega a la casilla del dueño de
la cuenta, así que sirve para las sugerencias y no para la beta. No se puede
verificar ascent-blush-seven.vercel.app: hay que tener un dominio y poder
tocarle el DNS. Sale ~10 USD/año y es lo único de toda la lista que cuesta
plata y depende de terceros (la propagación de DNS puede tardar horas).
Comprar el dominio y agregarlo en Resend → Domains → Add Domain.
Cargar en el DNS los registros que Resend muestra (DKIM y SPF, TXT y
MX), y esperar a que la fila quede en Verified.
En Supabase: Authentication → Emails → SMTP Settings → Enable Custom SMTP, y completar:
| Campo | Valor |
|---|---|
| Host | smtp.resend.com |
| Port | 465 |
| Username | resend |
| Password | la misma API key de Resend que usa la Edge Function |
| Sender email | una dirección del dominio verificado, p. ej. [email protected] |
| Sender name | Ascent |
El puerto 465 es TLS directo. Si el proveedor lo bloqueara, 587 también
sirve (ahí el cifrado se negocia con STARTTLS).
Guardar y probar con un "olvidé mi contraseña" a una casilla propia.
Está en Authentication → Sign In / Providers → Email → Confirm email. Se apagó para poder correr los tests.
Al prenderlo se rompe npm run test:e2e: crea cuentas con signUp y sigue
usándolas al toque, y con la confirmación activa esas cuentas no pueden entrar
hasta que alguien abra el correo. npm run capturas y npm run test:conexion
no se rompen: usan cuentas que ya existen y ya están confirmadas.
Orden correcto: primero el SMTP (paso 1), después esto. Al revés, las confirmaciones salen por el SMTP de cortesía y se cortan a los dos correos.
En el plan Free de Supabase NO hay backups automáticos. No es que estén apagados: no existen. Los backups diarios arrancan en el plan Pro (25 USD/mes), con 7 días de retención; el PITR es un add-on aparte y mucho más caro.
Dónde mirar el plan y los backups: Database → Backups en el panel. Si dice que no hay backups disponibles, el proyecto está en Free.
Desde el código no se puede comprobar: en .env.local solo hay la anon key, y
el estado del plan no se expone por PostgREST.
Las dos salidas, y hay que elegir una antes de que haya datos de otra
gente: pasar a Pro, o armar un dump periódico con supabase db dump (necesita
la contraseña de la base, que no está acá).
El JWT secret ya no se puede rotar. Supabase deshabilitó la rotación de las
llaves legacy (anon, service_role, JWT secret); el camino es migrar a las
llaves nuevas y desactivar las viejas, que deja la key expuesta sin efecto
igual. Conviene: es incremental en vez de un corte, y las legacy se deprecan a
fin de 2026 de todos modos.
Orden, en Settings → API Keys:
.env.local: NEXT_PUBLIC_SUPABASE_ANON_KEY pasa a la sb_publishable_….
Correr npm run test:conexion — el chequeo del rol de la clave hay que
ajustarlo, porque la nueva no es un JWT y no tiene role: anon adentro.sb_publishable_…, y
redesplegar. Las NEXT_PUBLIC_* se incrustan al compilar: sin deploy
nuevo, producción sigue con la vieja.sugerencia-mail: si lee SUPABASE_SERVICE_ROLE_KEY, pasarla
a la sb_secret_….feedback (Database → Webhooks): su definición
lleva la service_role key incrustada. Es el que filtró la llave; ver
spec/trampas.md.npm run test:conexion, npm run test:e2e y npm run capturas, que
son los tres que hablan con la base real.Ojo con un cambio de forma: las llaves nuevas van en el header apikey y no en
Authorization: Bearer. supabase-js lo maneja solo; cualquier curl a mano
que haya por ahí, no.
prueba_uno y prueba_dos. Conviene dejarlas, no borrarlas, porque las
usan tres cosas:
npm run capturas entra con prueba_uno (CONEXION_EMAIL en .env.local).
Sin ella no hay QA visual.npm run test:conexion le pide con esa cuenta el retrato de la base a
producción.npm run test:e2e no las usa: se crea las suyas y las borra.
Las claves ya se rotaron y viven solo en .env.local. Lo que falta es que se
noten como internas: ponerles un username que lo diga (ascent_qa_1) para
que ningún tester las encuentre en la búsqueda y les mande una solicitud.
Borrarlas recién cuando la beta termine.
test:e2e, es esperado).npm run test:e2e lo comprueba).supabase/schema.sql — todo el modelo de datos, triggers y políticas.src/motor/ — motor procedural de cuerpos celestes (shaders) + animación de subida de rango.src/app/ — pantallas: principal, social, álbum, datos, ajustes, login, onboarding.public/sw.js + manifest.webmanifest — PWA instalable.