# 🚀 n8n Integration Guide - Complete Setup ## Übersicht Dieses Portfolio nutzt n8n für: - ⚡ **Echtzeit-Aktivitätsanzeige** (Coding, Musik, Gaming, etc.) - 💬 **AI-Chatbot** (mit OpenAI/Anthropic) - 📊 **Aktivitäts-Tracking** (GitHub, Spotify, Netflix, etc.) - 🎮 **Gaming-Status** (Steam, Discord) - 📧 **Automatische Benachrichtigungen** --- ## 🎨 Coole Ideen für Integrationen ### 1. **GitHub Activity Feed** 🔨 **Was es zeigt:** - "Currently coding: Portfolio Website" - "Last commit: 5 minutes ago" - "Working on: feature/n8n-integration" - Programming language (TypeScript, Python, etc.) **n8n Workflow:** ``` GitHub Webhook → Extract Data → Update Database → Display on Site ``` ### 2. **Spotify Now Playing** 🎵 **Was es zeigt:** - Aktueller Song + Artist - Album Cover (rotierend animiert!) - Fortschrittsbalken - "Listening to X since Y minutes" **n8n Workflow:** ``` Cron (every 30s) → Spotify API → Parse Track Data → Update Database ``` ### 3. **Netflix/YouTube/Twitch Watching** 📺 **Was es zeigt:** - "Watching: Breaking Bad S05E14" - "Streaming: Coding Tutorial" - Platform badges (Netflix/YouTube/Twitch) **n8n Workflow:** ``` Trakt.tv API → Get Current Watching → Update Database Discord Rich Presence → Extract Activity → Update Database ``` ### 4. **Gaming Activity** 🎮 **Was es zeigt:** - "Playing: Elden Ring" - Platform: Steam/PlayStation/Xbox - Play time - Achievement notifications **n8n Workflow:** ``` Steam API → Get Current Game → Update Database Discord Presence → Parse Game → Update Database ``` ### 5. **Mood & Custom Status** 😊 **Was es zeigt:** - Emoji mood (😊, 💻, 🏃, 🎮, 😴) - Custom message: "Focused on DevOps" - Auto-status based on time/activity **n8n Workflow:** ``` Schedule → Determine Status (work hours/break/sleep) → Update Database Manual Webhook → Set Custom Status → Update Database ``` ### 6. **Smart Notifications** 📬 **Was es zeigt:** - "New email from X" - "GitHub PR needs review" - "Calendar event in 15 min" **n8n Workflow:** ``` Email/Calendar/GitHub → Filter Important → Create Notification → Display ``` --- ## 📦 Setup: Datenbank Schema ### PostgreSQL Table: `activity_status` ```sql CREATE TABLE activity_status ( id SERIAL PRIMARY KEY, -- Activity activity_type VARCHAR(50), -- 'coding', 'listening', 'watching', 'gaming', 'reading' activity_details TEXT, activity_project VARCHAR(255), activity_language VARCHAR(50), activity_repo VARCHAR(255), -- Music music_playing BOOLEAN DEFAULT FALSE, music_track VARCHAR(255), music_artist VARCHAR(255), music_album VARCHAR(255), music_platform VARCHAR(50), -- 'spotify', 'apple' music_progress INTEGER, -- 0-100 music_album_art TEXT, -- Watching watching_title VARCHAR(255), watching_platform VARCHAR(50), -- 'youtube', 'netflix', 'twitch' watching_type VARCHAR(50), -- 'video', 'stream', 'movie', 'series' -- Gaming gaming_game VARCHAR(255), gaming_platform VARCHAR(50), -- 'steam', 'playstation', 'xbox' gaming_status VARCHAR(50), -- 'playing', 'idle' -- Status status_mood VARCHAR(10), -- emoji status_message TEXT, updated_at TIMESTAMP DEFAULT NOW() ); ``` --- ## 🔧 n8n Workflows ### Workflow 1: GitHub Activity Tracker **Trigger:** Webhook bei Push/Commit **Frequenz:** Echtzeit ```json { "nodes": [ { "name": "GitHub Webhook", "type": "n8n-nodes-base.webhook", "parameters": { "path": "github-activity", "method": "POST" } }, { "name": "Extract Commit Data", "type": "n8n-nodes-base.function", "parameters": { "functionCode": "const commit = items[0].json;\nreturn [\n {\n json: {\n activity_type: 'coding',\n activity_details: commit.head_commit.message,\n activity_project: commit.repository.name,\n activity_language: 'TypeScript',\n activity_repo: commit.repository.html_url,\n updated_at: new Date().toISOString()\n }\n }\n];" } }, { "name": "Update Database", "type": "n8n-nodes-base.postgres", "parameters": { "operation": "executeQuery", "query": "INSERT INTO activity_status (activity_type, activity_details, activity_project, activity_language, activity_repo, updated_at) VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT (id) DO UPDATE SET activity_type = $1, activity_details = $2, activity_project = $3, activity_language = $4, activity_repo = $5, updated_at = $6 WHERE activity_status.id = 1" } } ] } ``` **Setup in GitHub:** 1. Gehe zu deinem Repository → Settings → Webhooks 2. Add webhook: `https://your-n8n-instance.com/webhook/github-activity` 3. Content type: `application/json` 4. Events: Push events --- ### Workflow 2: Spotify Now Playing **Trigger:** Cron (alle 30 Sekunden) ```json { "nodes": [ { "name": "Schedule", "type": "n8n-nodes-base.cron", "parameters": { "cronExpression": "*/30 * * * * *" } }, { "name": "Spotify API", "type": "n8n-nodes-base.httpRequest", "parameters": { "url": "https://api.spotify.com/v1/me/player/currently-playing", "method": "GET", "authentication": "oAuth2", "headers": { "Authorization": "Bearer {{$credentials.spotify.accessToken}}" } } }, { "name": "Parse Track Data", "type": "n8n-nodes-base.function", "parameters": { "functionCode": "const track = items[0].json;\nif (!track || !track.is_playing) {\n return [{ json: { music_playing: false } }];\n}\n\nreturn [\n {\n json: {\n music_playing: true,\n music_track: track.item.name,\n music_artist: track.item.artists[0].name,\n music_album: track.item.album.name,\n music_platform: 'spotify',\n music_progress: Math.round((track.progress_ms / track.item.duration_ms) * 100),\n music_album_art: track.item.album.images[0].url,\n updated_at: new Date().toISOString()\n }\n }\n];" } }, { "name": "Update Database", "type": "n8n-nodes-base.postgres", "parameters": { "operation": "executeQuery", "query": "UPDATE activity_status SET music_playing = $1, music_track = $2, music_artist = $3, music_album = $4, music_platform = $5, music_progress = $6, music_album_art = $7, updated_at = $8 WHERE id = 1" } } ] } ``` **Spotify API Setup:** 1. Gehe zu https://developer.spotify.com/dashboard 2. Create App 3. Add Redirect URI: `https://your-n8n-instance.com/oauth/callback` 4. Kopiere Client ID & Secret in n8n Credentials 5. Scopes: `user-read-currently-playing`, `user-read-playback-state` --- ### Workflow 3: AI Chatbot mit OpenAI **Trigger:** Webhook bei Chat-Message ```json { "nodes": [ { "name": "Chat Webhook", "type": "n8n-nodes-base.webhook", "parameters": { "path": "chat", "method": "POST" } }, { "name": "Build Context", "type": "n8n-nodes-base.function", "parameters": { "functionCode": "const userMessage = items[0].json.message;\n\nconst context = `You are Dennis Konkol's AI assistant. Here's information about Dennis:\n\n- Student in Osnabrück, Germany\n- Passionate self-hoster and DevOps enthusiast\n- Skills: Next.js, Flutter, Docker Swarm, Traefik, CI/CD, n8n\n- Runs own infrastructure on IONOS and OVHcloud\n- Projects: Clarity (Flutter dyslexia app), Self-hosted portfolio with Docker Swarm\n- Hobbies: Gaming, Jogging, Experimenting with tech\n- Fun fact: Uses pen & paper for calendar despite automating everything\n\nAnswer questions about Dennis professionally and friendly. Keep answers concise (2-3 sentences).\n\nUser question: ${userMessage}`;\n\nreturn [{ json: { context, userMessage } }];" } }, { "name": "OpenAI Chat", "type": "n8n-nodes-base.openAi", "parameters": { "resource": "chat", "operation": "message", "model": "gpt-4", "messages": { "values": [ { "role": "system", "content": "={{$node[\"Build Context\"].json[\"context\"]}}" }, { "role": "user", "content": "={{$node[\"Build Context\"].json[\"userMessage\"]}}" } ] } } }, { "name": "Return Response", "type": "n8n-nodes-base.respondToWebhook", "parameters": { "responseBody": "={{ { reply: $json.message.content } }}" } } ] } ``` **OpenAI API Setup:** 1. Gehe zu https://platform.openai.com/api-keys 2. Create API Key 3. Add zu n8n Credentials 4. Wähle Model: gpt-4 oder gpt-3.5-turbo --- ### Workflow 4: Discord/Steam Gaming Status **Trigger:** Cron (alle 60 Sekunden) ```json { "nodes": [ { "name": "Schedule", "type": "n8n-nodes-base.cron", "parameters": { "cronExpression": "0 * * * * *" } }, { "name": "Discord API", "type": "n8n-nodes-base.httpRequest", "parameters": { "url": "https://discord.com/api/v10/users/@me", "method": "GET", "authentication": "oAuth2", "headers": { "Authorization": "Bot {{$credentials.discord.token}}" } } }, { "name": "Parse Gaming Status", "type": "n8n-nodes-base.function", "parameters": { "functionCode": "const user = items[0].json;\nconst activity = user.activities?.find(a => a.type === 0); // 0 = Playing\n\nif (!activity) {\n return [{ json: { gaming_game: null, gaming_status: 'idle' } }];\n}\n\nreturn [\n {\n json: {\n gaming_game: activity.name,\n gaming_platform: 'discord',\n gaming_status: 'playing',\n updated_at: new Date().toISOString()\n }\n }\n];" } }, { "name": "Update Database", "type": "n8n-nodes-base.postgres", "parameters": { "operation": "executeQuery", "query": "UPDATE activity_status SET gaming_game = $1, gaming_platform = $2, gaming_status = $3, updated_at = $4 WHERE id = 1" } } ] } ``` --- ### Workflow 5: Smart Status (Auto-Detect) **Trigger:** Cron (alle 5 Minuten) ```json { "nodes": [ { "name": "Schedule", "type": "n8n-nodes-base.cron", "parameters": { "cronExpression": "*/5 * * * *" } }, { "name": "Determine Status", "type": "n8n-nodes-base.function", "parameters": { "functionCode": "const hour = new Date().getHours();\nconst day = new Date().getDay(); // 0 = Sunday, 6 = Saturday\n\nlet mood = '💻';\nlet message = 'Working on projects';\n\n// Sleep time (0-7 Uhr)\nif (hour >= 0 && hour < 7) {\n mood = '😴';\n message = 'Sleeping (probably dreaming of code)';\n}\n// Morning (7-9 Uhr)\nelse if (hour >= 7 && hour < 9) {\n mood = '☕';\n message = 'Morning coffee & catching up';\n}\n// Work time (9-17 Uhr, Mo-Fr)\nelse if (hour >= 9 && hour < 17 && day >= 1 && day <= 5) {\n mood = '💻';\n message = 'Deep work mode - coding & learning';\n}\n// Evening (17-22 Uhr)\nelse if (hour >= 17 && hour < 22) {\n mood = '🎮';\n message = 'Relaxing - gaming or watching shows';\n}\n// Late night (22-24 Uhr)\nelse if (hour >= 22) {\n mood = '🌙';\n message = 'Late night coding session';\n}\n// Weekend\nif (day === 0 || day === 6) {\n mood = '🏃';\n message = 'Weekend vibes - exploring & experimenting';\n}\n\nreturn [\n {\n json: {\n status_mood: mood,\n status_message: message,\n updated_at: new Date().toISOString()\n }\n }\n];" } }, { "name": "Update Database", "type": "n8n-nodes-base.postgres", "parameters": { "operation": "executeQuery", "query": "UPDATE activity_status SET status_mood = $1, status_message = $2, updated_at = $3 WHERE id = 1" } } ] } ``` --- ## 🔌 Frontend API Integration ### Update `/app/api/n8n/status/route.ts` ```typescript import { NextResponse } from 'next/server'; import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); export async function GET() { try { // Fetch from your activity_status table const status = await prisma.$queryRaw` SELECT * FROM activity_status WHERE id = 1 LIMIT 1 `; if (!status || status.length === 0) { return NextResponse.json({ activity: null, music: null, watching: null, gaming: null, status: null, }); } const data = status[0]; return NextResponse.json({ activity: data.activity_type ? { type: data.activity_type, details: data.activity_details, project: data.activity_project, language: data.activity_language, repo: data.activity_repo, timestamp: data.updated_at, } : null, music: data.music_playing ? { isPlaying: data.music_playing, track: data.music_track, artist: data.music_artist, album: data.music_album, platform: data.music_platform, progress: data.music_progress, albumArt: data.music_album_art, } : null, watching: data.watching_title ? { title: data.watching_title, platform: data.watching_platform, type: data.watching_type, } : null, gaming: data.gaming_game ? { game: data.gaming_game, platform: data.gaming_platform, status: data.gaming_status, } : null, status: data.status_mood ? { mood: data.status_mood, customMessage: data.status_message, } : null, }); } catch (error) { console.error('Error fetching activity status:', error); return NextResponse.json({ activity: null, music: null, watching: null, gaming: null, status: null, }, { status: 500 }); } } ``` ### Create `/app/api/n8n/chat/route.ts` ```typescript import { NextResponse } from 'next/server'; export async function POST(request: Request) { try { const { message } = await request.json(); // Call your n8n chat webhook const response = await fetch(`${process.env.N8N_WEBHOOK_URL}/webhook/chat`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ message }), }); if (!response.ok) { throw new Error('n8n webhook failed'); } const data = await response.json(); return NextResponse.json({ reply: data.reply }); } catch (error) { console.error('Chat API error:', error); return NextResponse.json( { reply: 'Sorry, I encountered an error. Please try again later.' }, { status: 500 } ); } } ``` --- ## 🌟 Zusätzliche coole Ideen ### 1. **Live Coding Stats** - Lines of code today - Most used language this week - GitHub contribution graph - Pull requests merged ### 2. **Coffee Counter** ☕ - Button in n8n Dashboard: "I had coffee" - Displays: "3 coffees today" - Funny messages bei > 5 cups ### 3. **Mood Tracker** - Manual mood updates via Discord Bot - Shows emoji + custom message - Persists über den Tag ### 4. **Auto-DND Status** - Wenn du in einem Meeting bist (Calendar API) - Wenn du fokussiert arbeitest (Pomodoro Timer) - Custom status: "🔴 In Deep Work - Back at 15:00" ### 5. **Project Highlights** - "Currently building: X" - "Deployed Y minutes ago" - "Last successful build: Z" ### 6. **Social Activity** - "New blog post: Title" - "Trending on Twitter: X mentions" - "LinkedIn: Y profile views this week" --- ## 📝 Environment Variables Add to `.env.local`: ```bash # n8n N8N_WEBHOOK_URL=https://your-n8n-instance.com N8N_API_KEY=your_n8n_api_key # Spotify SPOTIFY_CLIENT_ID=your_spotify_client_id SPOTIFY_CLIENT_SECRET=your_spotify_client_secret # OpenAI OPENAI_API_KEY=your_openai_api_key # Discord (optional) DISCORD_BOT_TOKEN=your_discord_bot_token # GitHub (optional) GITHUB_WEBHOOK_SECRET=your_github_webhook_secret ``` --- ## 🚀 Quick Start 1. **Setup Database:** ```bash psql -U postgres -d portfolio_dev -f setup_activity_status.sql ``` 2. **Create n8n Workflows:** - Import workflows via n8n UI - Configure credentials - Activate workflows 3. **Update API Routes:** - Add `status/route.ts` and `chat/route.ts` - Set environment variables 4. **Test:** ```bash npm run dev ``` - Check bottom-right corner for activity bubbles - Click chat button to test AI --- ## 🎯 Best Practices 1. **Caching:** Cache API responses für 30s (nicht bei jedem Request neu fetchen) 2. **Error Handling:** Graceful fallbacks wenn n8n down ist 3. **Rate Limiting:** Limitiere Chat-Requests (max 10/minute) 4. **Privacy:** Zeige nur das, was du teilen willst 5. **Performance:** Nutze Webhooks statt Polling wo möglich --- ## 🤝 Community Ideas Teile deine coolen n8n-Integrationen! - Discord: Zeig deinen Setup - GitHub: Share deine Workflows - Blog: Write-up über dein System Happy automating! 🎉