{"id":37228852,"url":"https://github.com/dauble/yoto-app","last_synced_at":"2026-01-15T03:29:54.793Z","repository":{"id":331635057,"uuid":"1131659906","full_name":"dauble/yoto-app","owner":"dauble","description":"Simple app for custom Yoto cards","archived":false,"fork":false,"pushed_at":"2026-01-10T22:28:47.000Z","size":82,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-11T04:09:49.343Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dauble.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-10T13:01:09.000Z","updated_at":"2026-01-10T22:27:48.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/dauble/yoto-app","commit_stats":null,"previous_names":["dauble/yoto-app"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/dauble/yoto-app","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dauble%2Fyoto-app","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dauble%2Fyoto-app/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dauble%2Fyoto-app/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dauble%2Fyoto-app/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dauble","download_url":"https://codeload.github.com/dauble/yoto-app/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dauble%2Fyoto-app/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28442282,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-15T00:55:22.719Z","status":"online","status_checked_at":"2026-01-15T02:00:08.019Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-15T03:29:54.088Z","updated_at":"2026-01-15T03:29:54.787Z","avatar_url":"https://github.com/dauble.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🏎️ Yoto Formula 1 Card Generator\n\nA Next.js application that automatically creates and updates Yoto MYO (Make Your Own) cards with the latest Formula 1 race information. Perfect for F1 fans who want their Yoto players to announce upcoming races!\n\n## ✨ Features\n\n### Core Features\n\n- 🏁 **Next Race Information** - Automatically fetches the next upcoming F1 race\n- 🌍 **Timezone Conversion** - Displays race time in the user's local timezone based on IP address\n- 🔄 **Auto-Update** - Updates the same card with new race info (no need to create new cards each time)\n- 🎙️ **Text-to-Speech** - Uses ElevenLabs via Yoto Labs API to generate audio\n- 🔐 **OAuth Authentication** - Secure authentication with Yoto (required before use)\n- 📱 **Responsive Design** - Works on desktop and mobile devices\n\n### Advanced Features\n\n- 🖼️ **Custom Cover Images** - Automatically uploads cover art from `public/assets/card-images/`\n- 📊 **Real-Time Job Status** - Live polling shows TTS generation progress (queued → processing → completed)\n- 🎵 **Audio File Upload** - Upload your own audio files to create MYO-compatible cards\n- 🔓 **Logout Functionality** - Easily logout and switch Yoto accounts\n- 📡 **Device Deployment** - Automatically deploys to all connected Yoto devices\n\n## 🚀 Quick Start\n\n### Prerequisites\n\n- Node.js 18+ installed\n- A [Yoto Developer Account](https://yoto.dev/)\n- Yoto OAuth credentials (Client ID \u0026 Secret)\n- A physical Yoto MYO card (optional, for linking the playlist)\n\n### Installation\n\n1. **Clone the repository**\n\n   ```bash\n   git clone https://github.com/\u003cyour-github-username\u003e/yoto-f1-card.git\n   cd yoto-f1-card\n   ```\n\n2. **Install dependencies**\n\n   ```bash\n   npm install\n   ```\n\n3. **Set up environment variables**\n\n   Copy `.env.example` to `.env` and fill in your Yoto credentials:\n\n   ```bash\n   cp .env.example .env\n   ```\n\n   Edit `.env` with your credentials:\n\n   ```env\n   YOTO_CLIENT_ID=your_client_id_here\n   YOTO_CLIENT_SECRET=your_client_secret_here\n   ```\n\n   **Note:** No need for `NEXT_PUBLIC_APP_URL` - the app auto-detects the correct URL at runtime!\n\n4. **Run the development server**\n\n   ```bash\n   npm run dev\n   ```\n\n5. **Open your browser**\n\n   Navigate to [http://localhost:3000](http://localhost:3000)\n\n## 📖 How to Use\n\n### First Time Setup\n\n1. **Connect with Yoto** - Click the \"🔐 Connect with Yoto\" button and authenticate\n   - Authentication is required before you can use any features\n   - Your session will persist across browser restarts\n2. **Add Cover Image** (Optional) - Place an image named `countdown-to-f1-card.png` in `public/assets/card-images/`\n\n### Generate TTS Card\n\n1. **Generate Card** - Click \"Generate F1 Card\" to create your first card with text-to-speech\n2. **Watch Progress** - Real-time status shows: Queued → Processing → Completed\n3. **Check Your Library** - The card will appear in your Yoto library when complete\n4. **Link to MYO Card** - Use the Yoto app to link the playlist to your physical MYO card\n5. **Auto-Update** - Click \"Generate F1 Card\" again anytime to update with the latest race info!\n\n### Upload Audio to MYO Card\n\n1. **Prepare Audio** - Have an MP3, M4A, or WAV file ready\n2. **Upload** - Use the \"Upload Audio to MYO Card\" form to select and upload your audio\n3. **Wait for Processing** - The app will upload and transcode your audio (15-60 seconds)\n4. **Link to MYO** - Follow the instructions to link the card in your Yoto app\n\n### Logout\n\n- Click the \"Logout\" button in the footer to disconnect your Yoto account\n- You'll need to re-authenticate to use the app again\n\n## 🎯 How Auto-Update Works\n\nThe first time you generate a card, the app:\n\n- Creates a new playlist in your Yoto library\n- Stores the card ID locally\n- Returns the playlist information\n\nOn subsequent generations:\n\n- Updates the **same** card with new race information\n- No duplicate cards created\n- Your MYO card automatically gets the latest data!\n\n## 🛠️ Technology Stack\n\n- **Framework**: Next.js 14 (App Router)\n- **Authentication**: Yoto OAuth 2.0\n- **Data Sources**:\n  - OpenF1 API for race data\n  - ipapi.co for timezone detection\n- **TTS**: Yoto Labs API with ElevenLabs\n- **Storage**: Configstore for local token/card storage\n- **Styling**: CSS Modules\n\n## 📦 Deployment\n\n### Deploy to Fly.io\n\n1. **Install Fly CLI**\n\n   ```bash\n   brew install flyctl\n   ```\n\n2. **Login to Fly**\n\n   ```bash\n   fly auth login\n   ```\n\n3. **Launch your app**\n\n   ```bash\n   fly launch\n   ```\n\n4. **Set environment variables**\n\n   ```bash\n   fly secrets set YOTO_CLIENT_ID=your_client_id\n   fly secrets set YOTO_CLIENT_SECRET=your_client_secret\n   ```\n\n5. **Deploy**\n\n   ```bash\n   fly deploy\n   ```\n\n6. **Set up automatic deployments (optional)**\n   - Get your Fly API token: `fly auth token`\n   - Add `FLY_API_TOKEN` to GitHub repository secrets\n   - Every push to `main` branch will auto-deploy via GitHub Actions!\n\n### Deploy to Vercel\n\n[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/yoto-dev/yoto-f1-card)\n\n1. Click the deploy button above\n2. Add your environment variables in Vercel dashboard\n3. Deploy!\n\n## 🤝 Contributing\n\nContributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.\n\n## 🐛 Troubleshooting\n\n### \"Not authenticated\" error\n\n- You must click \"🔐 Connect with Yoto\" before using any features\n- If you see the login button, your session has expired - click it to re-authenticate\n- Check that your OAuth credentials are correct in `.env`\n- Make sure your Yoto app has both redirect URIs configured:\n  - `http://localhost:3000/api/auth/callback` (local)\n  - `https://your-domain.com/api/auth/callback` (production)\n\n### Can't see the login button\n\n- Click \"Logout\" in the footer to clear your session\n- Alternatively, visit `http://localhost:3000/api/auth/logout`\n- Refresh the page and the login button should appear\n\n### Card not updating\n\n- Watch the real-time status indicator - it shows: Queued → Processing → Completed\n- TTS processing typically takes 10-30 seconds\n- When status shows \"✅ Completed\", your card is ready in your Yoto library\n- Check your Yoto library in the app\n\n### Cover image not appearing\n\n- Ensure image is named `countdown-to-f1-card.png` in `public/assets/card-images/`\n- Supported formats: PNG or JPG\n- Check console logs for upload confirmation\n\n### MYO audio upload fails\n\n- Ensure audio file is in a supported format (MP3, M4A, WAV)\n- File size should be under 100MB\n- Wait for transcoding to complete (usually 15-60 seconds)\n- Check that you're authenticated with Yoto\n\n### Race time showing wrong timezone\n\n- The app auto-detects timezone from your IP\n- If running locally, it may default to your server's timezone\n\n### OAuth redirect issues on deployed app\n\n- The app automatically detects the correct URL using request headers\n- No configuration needed - works on Fly.io, Vercel, and other platforms\n- If issues persist, check your Yoto app redirect URI matches your domain\n\n## 📄 License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## 🙏 Acknowledgments\n\n- [Yoto](https://yoto.dev/) for their amazing developer API\n- [OpenF1](https://openf1.org/) for F1 data\n- The F1 and Yoto communities\n\n## 🔗 Links\n\n- [Yoto Developer Portal](https://yoto.dev/)\n- [Yoto Discord Community](https://discord.gg/FkwBpYf2CN)\n- [OpenF1 API Documentation](https://openf1.org/)\n\n---\n\nBuilt with ❤️ for the Yoto community\n\n## Customization\n\n1. Modify `src/services/f1Service.js` to adjust data fetching\n2. Update `src/app/page.js` to change the UI\n3. Edit chapter scripts in the `generateF1Script` function\n\n## Sharing with Yoto Community\n\nOnce your card is ready, follow the [Yoto Publishing Guidelines](https://yoto.dev/publishing/) to share it with the community.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdauble%2Fyoto-app","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdauble%2Fyoto-app","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdauble%2Fyoto-app/lists"}