GitVision Workshop: Transforming GitHub Commits into Eurovision Playlists
A fun tool that turns your GitHub code into Eurovision music during our 2-hour hands-on workshop. Code + Music = Fun!

by Andrea Griffiths

What We'll Build Today
Flutter App with GitHub Integration
Analyze commit patterns and developer coding style
AI-Powered Eurovision Recommendations
Match coding moods with iconic Eurovision songs
Spotify Integration
Turn recommendations into playable playlists
Social Sharing
Share your coding soundtrack with the world

2

We Are Developers 2025

Learning Objectives
Technical Skills
  • Multi-API integration architecture
  • AI engineering and response parsing
  • Asynchronous state management
Practical Experience
  • Building production-ready error handling
  • Implementing intelligent fallback strategies
  • Optimizing performance in multi-API applications

3

We Are Developers 2025

GitHub Copilot Chat Configuration Menu
Explore the versatile configuration options within GitHub Copilot to customize its behavior and optimize your development workflow.
1
Prompt Files
Manage and create custom .prompt.md files for tailored Copilot interactions, stored in .github/prompts/.
2
Instructions
Configure global coding style, documentation, and testing guidelines for Copilot, typically in .github/copilot-instructions.md.
3
Tool Sets
Define and customize which tools Copilot can access in agent mode, such as codebase navigation, terminal, or web search.
4
Modes
Switch between interaction modes like "Ask" (Q&A) or "Agent" (autonomous task execution) to control Copilot's actions.
5
MCP Servers
Connect to custom model servers, configure parameters, and adjust context settings for enterprise-specific Copilot deployments.
6
Generate Instructions
Automatically analyze your codebase to create instruction templates, helping establish consistent coding standards effortlessly.
7
Chat Settings
Access general settings for the Copilot Chat interface, including visual preferences, auto-completion, and context inclusion.

4

We Are Developers 2025

Technical Prerequisites & Architecture
Prerequisites
  • Flutter/Dart basics (widgets, async/await, HTTP requests)
  • REST API concepts and JSON parsing
  • GitHub and Spotify developer accounts
  • 8GB+ RAM, stable internet connection
Data Flow Architecture
GitHub Commits
Extract commit history and message content
Sentiment Analysis
Process commit messages for emotional context
AI Prompt
Match commit patterns to Eurovision songs
Spotify Integration
Create playable playlists from recommendations

5

We Are Developers 2025

Workshop Structure
1
Phase 1: GitHub Integration (35 min)
Connect to GitHub API and analyze commit patterns
2
Phase 2: AI Eurovision Magic (40 min)
Use AI to match commits with Eurovision songs
3
Phase 3: Spotify Integration (35 min)
Make playlists playable with Spotify
4
Phase 4: Social Sharing (25 min)
Add sharing features and analytics
5
Phase 5: Production Polish (15 min)
Error handling and performance optimization
Flow suggestions but this is your time!

6

We Are Developers 2025

Step 1 - Launch Development Environment
1
Launch Codespace
Click the button: No fork needed. Uses the workshop's minutes, not yours.
2
Verify Environment
Ensure the `gitvision` project loads. Flutter & Dart should already be installed.
Tip: Refresh if Codespace stalls during initialization.

7

We Are Developers 2025

Step 2 - Initial Setup
Commands to Run:
cd gitvision chmod +x workshop-start.sh ./workshop-start.sh
This script will:
  • Install required dependencies
  • Set up API configuration templates
  • Prepare the Flutter environment
You'll see a success message when the setup is complete.

8

We Are Developers 2025

Step 3 - Configure API Keys
Edit lib/config/api_tokens.dart with your credentials:
static const String githubModelsToken = "your_token_here"; static const String spotifyClientId = "your_client_id";
Where to get tokens:
  • GitHub: Use your personal access token with repo scope
  • Spotify: Create a free developer application at developer.spotify.com

9

We Are Developers 2025

Step 4 - Launch The App
Run the app in web mode for the best workshop experience:
flutter run -d web-server
The app will open in your default browser at localhost:8080
  • Verify the app loads correctly
  • Check that the GitHub username input appears
  • Try a test username to ensure connectivity
💡 You can also test the app using the iOS emulator if you have it installed:
  1. Open the iOS Simulator from the Xcode menu
  1. In your terminal, run flutter run -d ios
  1. The app will launch in the iOS Simulator for you to test

10

We Are Developers 2025

Phase 1: GitHub Integration
What We're Building
In this phase, we'll connect to GitHub and analyze commit patterns to detect the developer's coding "vibe".
GitHub API Integration
Securely connect to GitHub and fetch commit history
Commit Analysis
Extract and analyze commit messages for sentiment
Eurovision Vibe Matching
Map commit patterns to Eurovision song categories

11

We Are Developers 2025

Phase 1: Key Files
Main Implementation Files:
  • lib/main.dart - Basic UI structure and GitHub integration skeleton
  • lib/models/commit.dart - Commit data structure
  • lib/config/api_tokens.dart - API configuration template
Files You'll Complete:
  • lib/services/github_service.dart - GitHub API wrapper with error handling
  • lib/sentiment_analyzer.dart - Eurovision mood detection logic
Your Phase 1 Tasks:
  1. Test existing GitHub integration with error scenarios
  1. Implement comprehensive GitHub API error handling
  1. Complete sentiment analysis keyword mapping
  1. Add rate limiting and retry logic

12

We Are Developers 2025

Phase 1: Implementation Steps
Test GitHub Integration
Enter valid and invalid GitHub usernames in the app. Success criteria: API returns 200 status code, correctly displays commit list, and handles 404 errors gracefully.
Explore Sentiment Analysis
Open lib/sentiment_analyzer.dart to review keyword → Eurovision vibe mapping and understand the detectVibe() method.
Add Error Handling
Implement comprehensive error handling with specific error types: RateLimitException, UserNotFoundException, and NetworkException in the GitHub service.
Test Your Changes
Verify that error handling works by testing with invalid usernames and simulating rate limit errors. Success criteria: User sees friendly messages for all error scenarios.

13

We Are Developers 2025

Commit Message Analysis
How We Detect Eurovision Vibes:

// Excerpt from sentiment_analyzer.dart // Analyze commit messages and return the detected vibe static String detectVibe(List commitMessages) { if (commitMessages.isEmpty) { return 'Productive'; // Default vibe } // This map defines the keywords for each vibe const Map> vibeKeywords = { 'Productive': ['add', 'implement', 'feature', 'improve', 'optimize', 'refactor'], 'Intense': ['fix', 'bug', 'issue', 'error', 'crash', 'hotfix'], 'Creative': ['design', 'style', 'ui', 'ux', 'animation', 'visual'], // ... and so on for other vibes }; // Count occurrences of keywords for each vibe Map vibeCounts = {}; for (String vibe in vibeKeywords.keys) { vibeCounts[vibe] = 0; } for (String message in commitMessages) { String lowerMessage = message.toLowerCase(); for (String vibe in vibeKeywords.keys) { for (String keyword in vibeKeywords[vibe]!) { if (lowerMessage.contains(keyword.toLowerCase())) { vibeCounts[vibe] = (vibeCounts[vibe] ?? 0) + 1; } } } }

// Excerpt from sentiment_analyzer.dart // Analyze commit messages and return the detected vibe static String detectVibe(List<String> commitMessages) { if (commitMessages.isEmpty) { return 'Productive'; // Default vibe } // This map defines the keywords for each vibe const Map<String, List<String>> vibeKeywords = { 'Productive': ['add', 'implement', 'feature', 'improve', 'optimize', 'refactor'], 'Intense': ['fix', 'bug', 'issue', 'error', 'crash', 'hotfix'], 'Creative': ['design', 'style', 'ui', 'ux', 'animation', 'visual'], // ... and so on for other vibes }; // Count occurrences of keywords for each vibe Map<String, int> vibeCounts = {}; for (String vibe in vibeKeywords.keys) { vibeCounts[vibe] = 0; } for (String message in commitMessages) { String lowerMessage = message.toLowerCase(); for (String vibe in vibeKeywords.keys) { for (String keyword in vibeKeywords[vibe]!) { if (lowerMessage.contains(keyword.toLowerCase())) { vibeCounts[vibe] = (vibeCounts[vibe] ?? 0) + 1; } } } }

14

We Are Developers 2025

Phase 2: AI Eurovision Magic
What We're Building
In this phase, we'll use AI to intelligently match GitHub commit patterns with Eurovision songs.
AI Models API Integration
Connect to AI services to analyze commit patterns
Eurovision-Specific Prompts
Craft specialized prompts with Eurovision context
Song Data Parsing
Extract structured song recommendations from AI responses
Fallback System
Ensure recommendations even when AI services fail

15

We Are Developers 2025

Phase 2: AI Implementation
Let's explore how we'll implement AI in our Eurovision playlist generator:
GitHub Models API
We're using GPT-4.1 via GitHub Models with the endpoint: https://models.github.ai/inference
Authentication is handled through your GitHub token.
Prompt Engineering
Our strategy includes providing context (relevant commit history and patterns), defining the task (requesting Eurovision song matches based on vibe), and specifying format (JSON response with song, artist, year).
Response Handling
We'll parse the AI's JSON responses to extract structured song recommendations that match the development vibe detected from your commits.

16

We Are Developers 2025

Phase 2: Key Files
Implementation Files:
  • lib/services/ai_playlist_service.dart - AI playlist generation
  • lib/models/eurovision_song.dart - Song data model
  • lib/prompts/eurovision_prompts.dart - AI prompt templates
Your Phase 2 Tasks:
  1. Complete the generateEurovisionPlaylist() method
  1. Enhance Eurovision song model validation
  1. Test AI responses and implement error handling

17

We Are Developers 2025

Live Coding: AI Prompt Builder 💻
String _buildEurovisionPrompt(SentimentResult sentiment) { return ''' Based on coding mood: "${sentiment.mood}" (${sentiment.confidence} confidence) Suggest 5 Eurovision songs matching this developer vibe: - Different years and countries - Match energy/theme to coding mood - Include reasoning for each choice JSON format: [{"title":"", "artist":"", "country":"", "year":2024, "reasoning":""}] Commit keywords: ${sentiment.keywords.join(', ')} '''; }

18

We Are Developers 2025

GitHub Models API Implementation 🔌
Future<String> _callGitHubModelsAPI(String prompt) async { final response = await http.post( Uri.parse('https://models.github.ai/inference/chat/completions'), headers: { 'Authorization': 'Bearer ${ApiConfig.githubToken}', 'Content-Type': 'application/json', }, body: jsonEncode({ 'messages': [ {'role': 'system', 'content': 'Eurovision expert & music curator'}, {'role': 'user', 'content': prompt} ], 'model': 'openai/gpt-4.1', 'temperature': 0.7, // Balance creativity + consistency }), ); // ... error handling }

19

We Are Developers 2025

AI Response Handling
Parsing AI Responses
// In ai_playlist_service.dart List<EurovisionSong> _parseAIResponse(String response) { try { // Extract JSON from AI response (handles non-JSON text) final jsonMatch = RegExp(r'\[[\s\S]*\]').firstMatch(response); if (jsonMatch == null) { throw FormatException('No JSON array found in response'); } final jsonString = jsonMatch.group(0); final List songsList = jsonDecode(jsonString); return songsList .map((song) => EurovisionSong.fromJson(song)) .toList(); } catch (e) { // Handle parsing errors gracefully print('Error parsing AI response: $e'); return _getFallbackSongs(); } }
Eurovision Song Model
// In eurovision_song.dart class EurovisionSong { final String title; final String artist; final String country; final int year; final String reasoning; // Constructor and validation EurovisionSong({ required this.title, required this.artist, required this.country, required this.year, required this.reasoning, }) : assert(year >= 1956 && year <= 2025); // JSON parsing methods factory EurovisionSong.fromJson(Map json) {...} }

20

We Are Developers 2025

Phase 3: Spotify Integration
What We're Building
In this phase, we'll connect to Spotify to make our Eurovision recommendations playable.
OAuth Authentication
Implement secure Spotify authentication flow
Song Search
Find Eurovision songs on Spotify with fallback strategies
Playable Interface
Create an interactive playlist with play controls
Graceful Fallbacks
Handle missing tracks and API limitations

21

We Are Developers 2025

Eurovision Song Search Strategy
Search Implementation:
// Primary search with Eurovision context String query = "${song.title} ${song.artist} eurovision"; var results = await spotify.searchTracks(query); // First fallback: without Eurovision context if (results.isEmpty) { query = "${song.title} ${song.artist}"; results = await spotify.searchTracks(query); } // Second fallback: title only if (results.isEmpty) { query = "${song.title}"; results = await spotify.searchTracks(query); } // Handle not found if (results.isEmpty) { return EurovisionTrack.notFound(song); }
Common Challenges:
  • Alternative versions - The Eurovision version might not be the most popular recording
  • Name variations - Artist names may be spelled differently
  • Missing songs - Some older or obscure Eurovision entries might not be on Spotify
  • Language differences - Songs might be listed under original language titles

22

We Are Developers 2025

Phase 4: Social Sharing
What We're Building
In this phase, we'll add features to share Eurovision coding playlists on social media.
Pick one!
Sharing Service
Platform-specific implementation for Twitter, Instagram, and LinkedIn
Analytics Tracking
Monitor user engagement and sharing patterns
Shareable Cards
Visually appealing playlist cards with Eurovision branding
Copy Options
Text-based sharing and clipboard functionality

23

We Are Developers 2025

Phase 5: Production Polish
What We're Building
In this final phase, we'll add production-quality features and optimizations.
Comprehensive Error Handling
Implement user-friendly error messages for all API failures and edge cases
Loading States
Add progress indicators and skeleton screens for better user experience
Performance Optimization
Implement caching and request batching to improve app responsiveness
Visual Polish
Add final visual touches and animations for a professional look and feel

24

We Are Developers 2025

Error Handling Strategy
GitHub API Failures:
try { commits = await githubService.fetchCommits(username); } catch (e) { if (e is RateLimitException) { showRateLimitDialog(); } else if (e is UserNotFoundException) { showUserNotFoundMessage(); } else { showGenericErrorMessage(); } }
AI API Failures:
try { playlist = await aiService.generatePlaylist(commits); } catch (e) { // Fallback to rule-based recommendations playlist = sentimentAnalyzer .getRecommendations(commits); // Track failure for analytics analytics.trackEvent('ai_failure', { 'error_type': e.toString(), 'fallback_used': true }); }

25

We Are Developers 2025

What You've Accomplished
Complete Flutter App
Built a production-ready application with multiple API integrations
Major APIs Integrated
GitHub, AI Models, and Spotify working together seamlessly
Countries Represented
All Eurovision participating nations throughout history
Workshop Phases
Completed all development phases from integration to production polish

26

We Are Developers 2025

Next Steps & Resources
Immediate Improvements
  • Implement playlist persistence
  • Add user preferences and favorites
  • Improve AI prompt engineering
Stay Connected
Share your Eurovision coding playlists with #githubcommunity
Documentation
"Every great developer has their soundtrack. Today you discovered yours is Eurovision! 🇪🇺"