BikeControl (SwiftControl)
使用 Zwift Click、Zwift Play、Shimano Di2 或任何藍牙控制器,搭配 MyWhoosh、Rouvy、Zwift 等。iOS、Android、Windows、macOS 均可免費試用。
AI 翻译
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
Aplicación de entrenamiento multi-usuario. Combina el plan anual de periodización de Andres Tovar (intacto, ver más abajo) con una capa profesional de cuentas, administración de atletas, repertorio de ejercicios con media y persistencia en la nube. • Atleta — inicia sesión y ve su plan de entrenamiento, bienestar, calculadora de 1RM y la sección de ciencia. El progreso se guarda en la nube. • Admin — ve a todos los atletas, les asigna rutinas y administra el repertorio de ejercicios (alta/baja por categoría, foto de portada y video por subida o enlace de TikTok/Instagram/YouTube).查看完整 README ↗
Aplicación de entrenamiento multi-usuario. Combina el plan anual de periodización de Andres Tovar (intacto, ver más abajo) con una capa profesional de cuentas, administración de atletas, repertorio de ejercicios con media y persistencia en la nube.
| Capa | Tecnología |
|---|---|
| UI | React 19, Vite 8, Tailwind CSS v4 |
| Iconos / gráficos | lucide-react, recharts |
| Backend | Supabase (Postgres, Auth, Storage, Edge Functions) |
| Hosting | Vercel o Netlify (SPA estática) |
La app es una SPA: el enrutado es por renderizado condicional en
src/App.jsx según loading → user → profile.role, no por rutas de URL.
Requisitos: Node 20+ y un proyecto de Supabase.
npm install
cp .env.example .env # completa con tus claves de Supabase
npm run dev # http://localhost:5173
Solo se usan claves públicas (prefijo VITE_, expuestas al navegador). Nunca
pongas la service_role key aquí — vive únicamente en el entorno del Edge Function.
| Variable | Descripción |
|---|---|
VITE_SUPABASE_URL | URL del proyecto, p. ej. https://xxxx.supabase.co |
VITE_SUPABASE_ANON_KEY | Publishable / anon key (sb_publishable_…) |
.env y sus variantes están en .gitignore; solo se versiona .env.example.
npm run build # genera dist/
npm run preview # sirve dist/ localmente
npm run lint # eslint
El proyecto trae configuración lista para ambos hostings. Ambos sirven la SPA con
fallback a index.html y aplican las cabeceras de seguridad.
vercel.json: rewrites de SPA (todo lo que no sea
/assets/* va a index.html), cabeceras de seguridad y cache inmutable de assets.public/_redirects (fallback SPA 200) y
public/_headers (mismas cabeceras de seguridad y cache).Configura VITE_SUPABASE_URL y VITE_SUPABASE_ANON_KEY en el panel del hosting.
Comando de build npm run build, directorio de salida dist.
src/
App.jsx Shell: splash → auth → admin/atleta + menú de cuenta
main.jsx Punto de entrada, envuelve en <AuthProvider>
contexts/
AuthContext.jsx Sesión, perfil, isAdmin, signIn/signUp/signOut
AppStateContext.jsx useStorage(key, def) → blob jsonb en user_app_state
features/
auth/AuthScreen.jsx Login/registro por usuario O email
training/TrainingApp.jsx App del atleta (plan intacto)
admin/ AdminApp, AthletesPanel, ExercisesPanel
data/fotos-de-fase.js Fotos de cada fase del programa (por id de fase)
lib/
supabase.js Cliente (claves desde env, sin secretos)
api.js Acceso a datos (ejercicios, atletas, rutinas, media)
theme.js Tokens de estilo (T, FONT)
training-utils.js Helpers de cálculo del plan
wearables.js Punto de extensión para wearables (ver abajo)
supabase/
functions/signup/ Edge Function de registro (emails sintéticos)
Login por usuario o email: el RPC email_for_login(identifier) resuelve el
email real y luego se llama a signInWithPassword. Los registros por usuario crean
un email sintético {username}@traininglab.app mediante el Edge Function signup
(con email_confirm: true). Funciones SECURITY DEFINER con search_path fijado:
is_admin(), email_for_login(), handle_new_user() (trigger), set_updated_at().
src/lib/wearables.js es el seam listo para integrar relojes
inteligentes (Apple Health, Google Fit, Garmin, Whoop). Define un contrato de provider
(connect/disconnect/fetchMetrics), una forma normalizada de métricas
(WearableMetrics) y un registro. La implementación concreta está diferida a
propósito — todavía no se importa desde la UI. Para activarlo: implementa un provider
y regístralo con registerWearableProvider(...).
is_admin()./object/public/ (los atletas renderizan media por URL guardada, sin listar el bucket).*.vercel.app / *.netlify.app con fallback seguro.X-Content-Type-Options, X-Frame-Options: DENY,
Referrer-Policy, Permissions-Policy, Cross-Origin-Opener-Policy.service_role key NO está
en el repo; vive solo en el entorno del Edge Function en Supabase.El security review de Supabase deja 5 avisos esperados:
is_admin() ejecutable por anon/authenticated — requerido: varias políticas
RLS declaradas TO public lo evalúan durante el acceso a tablas. Revocarlo rompería RLS.email_for_login() ejecutable por anon — requerido para el login por usuario
antes de autenticarse.
3–4. Lecturas asociadas a lo anterior derivadas de las mismas políticas TO public.El plan de entrenamiento de Andres es de larga data y no se altera.
No modifiques, renombres ni "optimices" el contenido de los datos del plan:
F2_LOWER_EX, F2_UPPER_EX, F3_DAYS, F4_DAYS, F5_DAYS, F6_LIFT_EX,
F7_WEEK, F8_WEEK, DELOAD_WEEKS, las constantes *_PROG, genF6Weeks y sus
objetos *Science, ni el array PHASES. No cambies ejercicios, series, repeticiones,
intensidades, porcentajes, cues, notas, textos de ciencia, trade-offs ni referencias.
Solo el renderizado visual puede mejorarse; los datos se quedan exactamente como están.