diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..6374d1f --- /dev/null +++ b/.env.example @@ -0,0 +1,7 @@ +# API Configuration +API_BASE_URL=https://api.openpodcast.dev +API_ANALYTICS_PATH=/analytics/v1 +API_REGISTER_PATH=/register + +# Development overrides (uncomment for local development) +# API_BASE_URL=http://localhost:8080 \ No newline at end of file diff --git a/.env.local b/.env.local new file mode 100644 index 0000000..3e3917a --- /dev/null +++ b/.env.local @@ -0,0 +1,4 @@ +# Local development environment +API_BASE_URL=http://localhost:8080 +API_ANALYTICS_PATH=/analytics/v1 +API_REGISTER_PATH=/register \ No newline at end of file diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..c33982f --- /dev/null +++ b/.env.production @@ -0,0 +1,4 @@ +# Production environment +API_BASE_URL=https://api.openpodcast.dev +API_ANALYTICS_PATH=/analytics/v1 +API_REGISTER_PATH=/register \ No newline at end of file diff --git a/src/assets/images/connect/spotify/step-2-podcast-list.png b/src/assets/images/connect/spotify/step-2-podcast-list.png new file mode 100644 index 0000000..ed7778b Binary files /dev/null and b/src/assets/images/connect/spotify/step-2-podcast-list.png differ diff --git a/src/assets/images/connect/spotify/step-3-team-members.png b/src/assets/images/connect/spotify/step-3-team-members.png new file mode 100644 index 0000000..ceb16f6 Binary files /dev/null and b/src/assets/images/connect/spotify/step-3-team-members.png differ diff --git a/src/assets/images/connect/spotify/step-4-invite-details.png b/src/assets/images/connect/spotify/step-4-invite-details.png new file mode 100644 index 0000000..a3a4844 Binary files /dev/null and b/src/assets/images/connect/spotify/step-4-invite-details.png differ diff --git a/src/assets/images/connect/spotify/step-5-1-permissions-collapsed.png b/src/assets/images/connect/spotify/step-5-1-permissions-collapsed.png new file mode 100644 index 0000000..e16561b Binary files /dev/null and b/src/assets/images/connect/spotify/step-5-1-permissions-collapsed.png differ diff --git a/src/assets/images/connect/spotify/step-5-2-permissions-expanded.png b/src/assets/images/connect/spotify/step-5-2-permissions-expanded.png new file mode 100644 index 0000000..21a6c7e Binary files /dev/null and b/src/assets/images/connect/spotify/step-5-2-permissions-expanded.png differ diff --git a/src/html/connect/index.html b/src/html/connect/index.html new file mode 100644 index 0000000..5abcae1 --- /dev/null +++ b/src/html/connect/index.html @@ -0,0 +1,505 @@ + + + + Podcast Verbinden - Open Podcast + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + +
+

+ Podcast Verbinden +

+

+ Wähle deine Podcast-Plattform unten und folge den einfachen Schritten, um uns schreibgeschützten Zugriff auf deine Analytics-Daten zu gewähren. +

+

+ Sicher: Wir speichern niemals Ihre Login-Daten - nur schreibgeschützter Zugriff auf Analytics-Daten. +

+
+
+
+ + +
+
+
+
+
+ + + +
+

Loslegen

+

Gib deine Daten ein, um deine Podcast-Plattformen zu verbinden

+
+ + + +
+
+ + +
+
+ + +
+ +
+ +
+

+ Indem du fortfährst, stimmst du zu, Analytics-Berichte per E-Mail zu erhalten. Kein Spam, nur deine Podcast-Daten. +

+
+
+
+
+ + + + + + + + +
+
+
+
+
+
+ + + +
+
+

Wir übernehmen den Rest

+

+ Sobald du den Verbindungsprozess oben abgeschlossen hast, wird unser Team automatisch benachrichtigt. + Wir melden uns innerhalb von 24 Stunden bei dir mit deinem ersten kostenlosen automatisierten PDF-Bericht. +

+
+

+ Keine weiteren Maßnahmen erforderlich - lehne dich einfach zurück und warte auf deinen detaillierten Podcast-Analytics-Bericht! +

+
+
+
+
+
+ + + +
+
+
+ +
+
+ + + +
+

DSGVO-konform

+

Deutsches Unternehmen, DSGVO-konform. Wir verkaufen niemals deine Daten.

+
+ + +
+
+ + + +
+

Schnellstart

+

Konten verbinden, das war's! Keine technischen Kenntnisse oder Einrichtung erforderlich.

+
+ + +
+
+ + + +
+

Ihre Daten gehören Ihnen

+

Export nach CSV, PDF, JSON. Nutze deine Daten mit ChatGPT, Claude oder deinen eigenen Tools.

+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/src/html/en/connect/index.html b/src/html/en/connect/index.html new file mode 100644 index 0000000..d1b192c --- /dev/null +++ b/src/html/en/connect/index.html @@ -0,0 +1,500 @@ + + + + Connect Your Podcast - Open Podcast + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + +
+

+ Connect Your Podcast +

+

+ Choose your podcast platform below and follow the simple steps to grant us read-only access to your analytics data. +

+

+ Secure: We never store your login credentials - read-only access to analytics data. +

+
+
+
+ + +
+
+
+
+
+ + + +
+

Get Started

+

Enter your details to begin connecting your podcast platforms

+
+ + + +
+
+ + +
+
+ + +
+ +
+ +
+

+ By continuing, you agree to receive analytics reports via email. No spam, just your podcast data. +

+
+
+
+
+ + + + + + + + +
+
+
+
+
+
+ + + +
+
+

We'll Handle the Rest

+

+ Once you've completed the connection process above, our team will be notified automatically. + We'll reach out to you within 24 hours with your first free automated PDF report. +

+
+

+ No further action required - just sit back and wait for your detailed podcast analytics report! +

+
+
+
+
+
+ + + +
+
+
+ +
+
+ + + +
+

GDPR Compliant

+

German company, GDPR compliant. We never sell your data.

+
+ + +
+
+ + + +
+

Quick Start

+

Connect accounts, that's it! No technical knowledge or setup required.

+
+ + +
+
+ + + +
+

Your Data Belongs to You

+

Export to CSV, PDF, JSON. Use your data with ChatGPT, Claude or your own tools.

+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/src/js/config.js b/src/js/config.js new file mode 100644 index 0000000..66faba1 --- /dev/null +++ b/src/js/config.js @@ -0,0 +1,32 @@ +// API Configuration +// This file is generated during build process or manually configured +// for different environments + +window.OpenPodcastConfig = { + // Default to production values + API_BASE_URL: 'https://api.openpodcast.dev', + API_ANALYTICS_PATH: '/analytics/v1', + API_REGISTER_PATH: '/register', + + // Auto-detect local development + init() { + // Check if we're running locally + if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') { + this.API_BASE_URL = 'http://localhost:8080'; + } + + return this; + }, + + // Get full API URLs + getRegisterUrl() { + return this.API_BASE_URL + this.API_REGISTER_PATH; + }, + + getAnalyticsUrl() { + return this.API_BASE_URL + this.API_ANALYTICS_PATH; + } +}; + +// Initialize config +window.OpenPodcastConfig.init(); \ No newline at end of file diff --git a/src/js/connect.js b/src/js/connect.js new file mode 100644 index 0000000..a531428 --- /dev/null +++ b/src/js/connect.js @@ -0,0 +1,166 @@ +// Connect page functionality +// Shared JavaScript for both German and English connect pages + +function copyToClipboard(text, button) { + navigator.clipboard.writeText(text).then(function() { + const originalHTML = button.innerHTML; + button.innerHTML = ''; + button.classList.add('text-green-600'); + setTimeout(function() { + button.innerHTML = originalHTML; + button.classList.remove('text-green-600'); + }, 2000); + }); +} + +function toggleCard(cardId) { + const content = document.getElementById(cardId + '-content'); + const arrow = document.getElementById(cardId + '-arrow'); + const header = document.getElementById(cardId + '-header'); + + if (content.classList.contains('hidden')) { + content.classList.remove('hidden'); + arrow.style.transform = 'rotate(180deg)'; + header.classList.add('border-b', 'border-gray-100'); + } else { + content.classList.add('hidden'); + arrow.style.transform = 'rotate(0deg)'; + header.classList.remove('border-b', 'border-gray-100'); + } +} + +async function registerUser(name, email) { + try { + const response = await fetch(window.OpenPodcastConfig.getRegisterUrl(), { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ name, email }) + }); + + const data = await response.json(); + + if ((response.ok && data.success) || (response.status === 409 && data.data)) { + // Store API key for future use (works for both new users and existing users) + localStorage.setItem('openpodcast_api_key', data.data.apiKey); + localStorage.setItem('openpodcast_user_id', data.data.userId); + localStorage.setItem('openpodcast_user_name', data.data.name); + + // Show platform connection options + showPlatformCards(); + hideRegistrationForm(); + + return data; + } else { + throw new Error(data.error || 'Registration failed'); + } + } catch (error) { + console.error('Registration failed:', error); + throw error; + } +} + +function showPlatformCards() { + // Update welcome message with user name + const userName = localStorage.getItem('openpodcast_user_name'); + if (userName) { + document.getElementById('user-name').textContent = userName; + } + + document.getElementById('platform-cards').classList.remove('hidden'); + document.getElementById('welcome-message').classList.remove('hidden'); +} + +function hideRegistrationForm() { + document.getElementById('registration-section').classList.add('hidden'); +} + +function showRegistrationError(message) { + const errorDiv = document.getElementById('registration-error'); + errorDiv.textContent = message; + errorDiv.classList.remove('hidden'); +} + +function hideRegistrationError() { + document.getElementById('registration-error').classList.add('hidden'); +} + +// Handle Podigee OAuth callback +function handlePodigeeCallback() { + const urlParams = new URLSearchParams(window.location.search); + const authCode = urlParams.get('code'); + const error = urlParams.get('error'); + + if (authCode) { + // Successfully received OAuth code from Podigee + showPodigeeSuccess(); + // Remove URL parameters from browser history + window.history.replaceState({}, document.title, window.location.pathname); + } else if (error) { + showPodigeeError(); + // Remove URL parameters from browser history + window.history.replaceState({}, document.title, window.location.pathname); + } +} + +function showPodigeeSuccess() { + const successDiv = document.getElementById('podigee-success'); + const connectButton = document.getElementById('podigee-connect-button'); + if (successDiv && connectButton) { + successDiv.classList.remove('hidden'); + connectButton.classList.add('hidden'); + } +} + +function showPodigeeError() { + const errorDiv = document.getElementById('podigee-error'); + if (errorDiv) { + errorDiv.classList.remove('hidden'); + } +} + +// Initialize connect page functionality +function initConnectPage(messages) { + // Check if user is already registered when page loads + const apiKey = localStorage.getItem('openpodcast_api_key'); + const userName = localStorage.getItem('openpodcast_user_name'); + + if (apiKey && userName) { + document.getElementById('user-name').textContent = userName; + showPlatformCards(); + hideRegistrationForm(); + } + + // Handle Podigee OAuth callback + handlePodigeeCallback(); + + // Handle registration form submission + const form = document.getElementById('registration-form'); + if (form) { + form.addEventListener('submit', async function(e) { + e.preventDefault(); + + const name = document.getElementById('user-name-input').value.trim(); + const email = document.getElementById('user-email-input').value.trim(); + const submitButton = document.getElementById('register-button'); + + if (!name || !email) { + showRegistrationError(messages.fillAllFields); + return; + } + + submitButton.disabled = true; + submitButton.textContent = messages.registering; + hideRegistrationError(); + + try { + await registerUser(name, email); + } catch (error) { + showRegistrationError(error.message || messages.registrationFailed); + submitButton.disabled = false; + submitButton.textContent = messages.getStarted; + } + }); + } +} \ No newline at end of file