Transformez vos images de workout vélo en fichiers .zwo importables dans Zwift, Intervals.icu et TrainingPeaks.
- 📷 Upload d'images - Glissez-déposez ou prenez une photo de votre workout
- 🤖 Analyse IA - GPT-4 Vision extrait automatiquement la structure du workout
- ✏️ Éditeur interactif - Modifiez les étapes, puissances et durées
- 📊 Visualisation graphique - Aperçu du workout avec zones de puissance colorées
- 🔄 Drag & Drop - Réorganisez les étapes par glisser-déposer
- 📥 Export ZWO - Téléchargez au format .zwo compatible Zwift
- 🌐 Bilingue - Interface en français et anglais
- 🔒 Rate Limiting - Protection contre les abus avec quota journalier (Redis/mémoire)
- Node.js 18+
- Clé API OpenAI avec accès GPT-4 Vision
# Cloner le repository
git clone https://github.com/tcrevel/imagetowo.git
cd imagetowo
# Installer les dépendances
npm install
# Configurer les variables d'environnement
cp .env.example .env.local
# Éditer .env.local avec votre clé API OpenAI
# Lancer le serveur de développement
npm run devOuvrez http://localhost:3000 dans votre navigateur.
Créez un fichier .env.local à la racine du projet :
# Required: Clé API OpenAI pour GPT-4 Vision
OPENAI_API_KEY=sk-your-api-key-here
# Optional: Taille max des fichiers (défaut: 10MB)
MAX_FILE_SIZE=10485760
# Optional: Formats d'images autorisés
ALLOWED_IMAGE_FORMATS=image/jpeg,image/png,image/webp,image/heic
# Optional: Origines autorisées en dev (tunnels, codespaces)
ALLOWED_DEV_ORIGINS=127.0.0.1,localhost
# Optional: CORS en production (* pour toutes les origines)
# ALLOWED_PROD_ORIGINS=*- Connectez-vous à intervals.icu
- Allez dans Library → Workouts
- Cliquez sur + Add → Import from File
- Sélectionnez votre fichier
.zwo
- Connectez-vous à trainingpeaks.com
- Allez dans Workout Library
- Cliquez sur Import Workouts → Import from File
- Sélectionnez votre fichier
.zwo
- Copiez le fichier
.zwodans :- Windows:
Documents\Zwift\Workouts\[votre ID] - Mac:
Documents/Zwift/Workouts/[votre ID]
- Windows:
- Lancez Zwift → Training → Custom Workouts
imagetowo/
├── app/
│ ├── api/
│ │ └── workouts/
│ │ ├── parse/ # POST - Analyse d'image avec GPT-4 Vision
│ │ ├── quota/ # GET - Vérification du quota restant
│ │ └── export/zwo/ # POST - Génération du fichier ZWO
│ ├── layout.tsx
│ └── page.tsx
├── components/
│ ├── uploader.tsx # Upload drag & drop + camera
│ ├── workout-editor.tsx # Éditeur de workout complet
│ ├── workout-chart.tsx # Visualisation graphique
│ ├── step-editor.tsx # Éditeur d'étape individuelle
│ ├── quota-badge.tsx # Affichage du quota restant
│ └── language-switcher.tsx # Sélecteur de langue
├── lib/
│ ├── hooks/ # React hooks (useQuota)
│ ├── i18n/ # Internationalisation EN/FR
│ ├── schemas/ # Schémas Zod (workout, step, API)
│ └── services/
│ ├── openai.ts # Intégration GPT-4 Vision
│ ├── rate-limit.ts # Service de rate limiting
│ ├── redis.ts # Client Redis singleton
│ └── zwo.ts # Génération XML ZWO
└── __tests__/ # Tests Vitest
# Lancer les tests
npm test
# Mode watch
npm run test:watch
# Avec couverture
npm run test:coverage# Build de production
npm run build
# Lancer en production
npm start- Connectez votre repository GitHub à Vercel
- Ajoutez les variables d'environnement :
OPENAI_API_KEY(requis)REDIS_URL(optionnel, recommandé pour le rate limiting distribué)DAILY_PARSE_LIMIT(optionnel, défaut: 5)
- Déployez !
💡 Astuce : Utilisez Upstash pour un Redis gratuit compatible Vercel.
ImageToWo inclut un système de limitation de requêtes pour contrôler les coûts API et prévenir les abus.
- Identification : Combinaison IP + fingerprint navigateur
- Quota : 5 analyses par utilisateur par jour (configurable)
- Stockage : Redis (recommandé) ou mémoire (fallback automatique)
# Activer/désactiver le rate limiting (défaut: true)
RATE_LIMIT_ENABLED=true
# Nombre d'analyses par jour par utilisateur (défaut: 5)
DAILY_PARSE_LIMIT=5
# URL Redis pour le stockage distribué (optionnel)
# Sans Redis, utilise le stockage en mémoire (instance unique)
REDIS_URL=redis://localhost:6379| Provider | Tier gratuit | URL |
|---|---|---|
| Upstash | 10k requêtes/jour | rediss://...@xxx.upstash.io:6379 |
| Redis Cloud | 30MB | redis://...@xxx.redislabs.com:port |
| Railway | $5 crédit | Variable REDIS_URL fournie |
| Render | 25MB | Variable REDIS_URL fournie |
Les endpoints renvoient des headers informatifs :
X-RateLimit-Limit: 5 # Quota total
X-RateLimit-Remaining: 3 # Requêtes restantes
X-RateLimit-Reset: 1234567890 # Timestamp de réinitialisation
- Framework: Next.js 16 avec App Router
- Langage: TypeScript
- Styling: Tailwind CSS v4
- UI: shadcn/ui
- Validation: Zod v4
- IA: OpenAI GPT-4 Vision
- Cache: Redis (optionnel, pour rate limiting distribué)
- Tests: Vitest
Le format .zwo est un fichier XML utilisé par Zwift pour décrire les workouts structurés. ImageToWo génère des fichiers ZWO compatibles avec :
- Zwift
- Intervals.icu
- TrainingPeaks
- TrainerRoad (import manuel)
MIT © tcrevel
Made with ❤️ for cyclists who hate typing workout structures manually