BikeControl (SwiftControl)
使用 Zwift Click、Zwift Play、Shimano Di2,或任何藍牙控制器搭配 MyWhoosh、Rouvy、Zwift 等。可於 iOS、Android、Windows 與 macOS 免費試用。
AI 翻譯
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗Next.js 16 + TypeScript + Drizzle + Neon Postgres. Diseño: ../docs/system-design.md.
| Comando | Qué hace |
|---|---|
npm run dev | servidor de desarrollo |
npm test | tests (Postgres en memoria con PGlite, incluye aislamiento entre clubes) |
npm run typecheck | TypeScript |
npm run db:generate | genera migración desde src/server/db/schema.ts |
npm run db:migrate | aplica migraciones a Neon (usa DATABASE_URL_MIGRATE) |
src/server/db/schema.ts. RLS, roles y grants: drizzle/0001_rls.sql (SQL a mano).app_user (rutas del club, RLS siempre) y platform_user (auth, superadmin, jobs). La migración los crea NOLOGIN; hay que darles login y clave una vez: ALTER ROLE app_user LOGIN PASSWORD '...'.withTenant(clubId, fn) o withPlatform(fn) (src/server/db/client.ts).club_id necesita en su migración: ENABLE ROW LEVEL SECURITY, policy tenant_isolation, policy platform_all y GRANTs. Agregar un test en tests/tenant-isolation.test.ts..env.example.next-intl, idiomas es, en, pt (messages/*.json, URL con prefijo /es, /en, /pt). Un test falla si falta una clave en algún idioma.
src/server/auth/service.ts (login, refresh rotativo, logout, cambio de club). Endpoints: /api/auth/{login,refresh,logout,switch-club}.ph_at; refresh opaco de 30 días en ph_rt (path /api/auth, solo se guarda su hash). Cada refresh rota el token; reusar uno viejo revoca toda la sesión.src/proxy.ts es un guard optimista (firma y vencimiento). La autorización real: requireClubSession(), requireOwner(), requireSuperadmin() en las páginas y withTenant() en los datos.JWT_SECRET (32+ caracteres).auth_tokens ya existe), CSP con nonce, 2FA de superadmin.padel'hub, rama production)Puesta en marcha desde cero, en orden:
.env.local con DATABASE_URL_MIGRATE (conexión directa del dueño; neon connection-string --project-id <id> --role-name neondb_owner).npm run db:migratenpm run ops:setup-env: da login a app_user y platform_user, y completa DATABASE_URL, DATABASE_URL_PLATFORM y JWT_SECRET (usa --rotate para regenerarlos).npm run ops:smoke y npm run ops:smoke-auth: pruebas contra la base real; crean datos temporales y los borran.tsx directo porque PowerShell se come el -- de npm run:
npx tsx --conditions=react-server scripts/create-superadmin.ts --email <email> --name "<nombre>" --password "<clave>"npx tsx --conditions=react-server scripts/create-club.ts --slug <slug> --name "<nombre>" --owner-email <email> --owner-name "<nombre>" --password "<clave>" [--locale es|en|pt].env.local no se versiona. En Vercel hay que cargar DATABASE_URL, DATABASE_URL_PLATFORM y JWT_SECRET (nunca DATABASE_URL_MIGRATE).
.env.local apunta a la rama dev de Neon (datos de prueba, incluido el club demo-padel: npx tsx --conditions=react-server scripts/seed-demo.ts --password "<clave>").production están en .env.neon-production (a propósito con un nombre que Next no carga solo; antes se llamaba .env.production.local y next start lo habría usado). Esos valores se cargan en Vercel, no se copian a .env.local./[locale]/app/players)Listado con búsqueda y filtros (categoría, género, posición, horario) en la URL, alta manual con consentimiento, ficha editable y baja (solo dueño). Responsive: tabla en pantallas ≥1280px, tarjetas en 2 columnas en tablet, 1 columna con filtros plegables en celular. Servicio: src/server/services/players.ts.
Producción (main) y desarrollo (dev) en Vercel + Neon: ver DEPLOY.md.