OpenAthlete
AGPLv3 endurance training platform: EU-oriented hosting, transparent CTL/ATL/TSB logic in code, self-hosting, and full export. Built in Grenoble.
翻譯準備中
尚未偵測到更新。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.