RSS_to_Podcast_Form

Markdown Guest 2 Views Size: 71.61 KB Posted on: Dec 10, 25 @ 11:11 PM

Podcast Episode Form with RSS Auto-Population

Here's a complete form implementation that auto-populates from RSS feeds and allows manual editing:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Podcast Episode Manager</title>
    <style>
        :root {
            --primary: #1a73e8;
            --secondary: #34a853;
            --danger: #ea4335;
            --warning: #fbbc04;
            --light: #f8f9fa;
            --dark: #202124;
            --gray: #5f6368;
            --border: #dadce0;
        }

        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
            line-height: 1.6;
            color: var(--dark);
            background-color: var(--light);
            padding: 20px;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            border-radius: 12px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            overflow: hidden;
        }

        .header {
            background: linear-gradient(135deg, var(--primary), #6c63ff);
            color: white;
            padding: 30px;
            text-align: center;
        }

        .header h1 {
            font-size: 2.5rem;
            margin-bottom: 10px;
        }

        .header p {
            opacity: 0.9;
            font-size: 1.1rem;
        }

        .tabs {
            display: flex;
            background: #f1f3f4;
            border-bottom: 1px solid var(--border);
        }

        .tab {
            padding: 15px 30px;
            background: none;
            border: none;
            font-size: 16px;
            cursor: pointer;
            transition: all 0.3s ease;
            position: relative;
        }

        .tab.active {
            background: white;
            color: var(--primary);
            font-weight: 600;
        }

        .tab.active::after {
            content: '';
            position: absolute;
            bottom: -1px;
            left: 0;
            right: 0;
            height: 3px;
            background: var(--primary);
        }

        .tab-content {
            display: none;
            padding: 30px;
        }

        .tab-content.active {
            display: block;
        }

        .section {
            background: white;
            border: 1px solid var(--border);
            border-radius: 8px;
            margin-bottom: 24px;
            overflow: hidden;
        }

        .section-header {
            background: #f8f9fa;
            padding: 16px 24px;
            border-bottom: 1px solid var(--border);
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .section-header h3 {
            color: var(--dark);
            font-size: 18px;
            margin: 0;
        }

        .section-content {
            padding: 24px;
        }

        .form-group {
            margin-bottom: 20px;
        }

        label {
            display: block;
            margin-bottom: 8px;
            font-weight: 500;
            color: var(--dark);
        }

        .required::after {
            content: " *";
            color: var(--danger);
        }

        input[type="text"],
        input[type="number"],
        input[type="url"],
        input[type="datetime-local"],
        textarea,
        select {
            width: 100%;
            padding: 12px;
            border: 1px solid var(--border);
            border-radius: 6px;
            font-size: 16px;
            transition: border 0.3s ease;
        }

        input[type="text"]:focus,
        input[type="number"]:focus,
        input[type="url"]:focus,
        textarea:focus,
        select:focus {
            outline: none;
            border-color: var(--primary);
            box-shadow: 0 0 0 3px rgba(26, 115, 232, 0.1);
        }

        textarea {
            min-height: 100px;
            resize: vertical;
        }

        .form-row {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
            gap: 20px;
        }

        .checkbox-group {
            display: flex;
            gap: 20px;
            flex-wrap: wrap;
        }

        .checkbox-item {
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .btn {
            padding: 12px 24px;
            border: none;
            border-radius: 6px;
            font-size: 16px;
            font-weight: 500;
            cursor: pointer;
            transition: all 0.3s ease;
            display: inline-flex;
            align-items: center;
            gap: 8px;
        }

        .btn-primary {
            background: var(--primary);
            color: white;
        }

        .btn-primary:hover {
            background: #0d62d9;
            transform: translateY(-2px);
        }

        .btn-secondary {
            background: var(--secondary);
            color: white;
        }

        .btn-secondary:hover {
            background: #2c8e44;
        }

        .btn-outline {
            background: white;
            color: var(--primary);
            border: 2px solid var(--primary);
        }

        .btn-outline:hover {
            background: var(--primary);
            color: white;
        }

        .btn-danger {
            background: var(--danger);
            color: white;
        }

        .btn-danger:hover {
            background: #d33426;
        }

        .btn-small {
            padding: 6px 12px;
            font-size: 14px;
        }

        .form-actions {
            display: flex;
            gap: 12px;
            justify-content: flex-end;
            margin-top: 30px;
            padding-top: 20px;
            border-top: 1px solid var(--border);
        }

        .status-badge {
            display: inline-block;
            padding: 4px 12px;
            border-radius: 20px;
            font-size: 12px;
            font-weight: 500;
            text-transform: uppercase;
        }

        .status-draft {
            background: #fef3c7;
            color: #92400e;
        }

        .status-ready {
            background: #d1fae5;
            color: #065f46;
        }

        .status-published {
            background: #dbeafe;
            color: #1e40af;
        }

        .tag-input {
            display: flex;
            flex-wrap: wrap;
            gap: 8px;
            padding: 8px;
            border: 1px solid var(--border);
            border-radius: 6px;
            min-height: 48px;
        }

        .tag {
            background: #e8f0fe;
            color: var(--primary);
            padding: 4px 12px;
            border-radius: 16px;
            font-size: 14px;
            display: flex;
            align-items: center;
            gap: 6px;
        }

        .tag-remove {
            background: none;
            border: none;
            color: var(--primary);
            cursor: pointer;
            font-size: 16px;
            line-height: 1;
        }

        .tag-input input {
            flex: 1;
            min-width: 150px;
            border: none;
            outline: none;
            padding: 8px;
            font-size: 16px;
        }

        .repeater-item {
            background: #f8f9fa;
            border: 1px solid var(--border);
            border-radius: 6px;
            padding: 16px;
            margin-bottom: 12px;
        }

        .repeater-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 12px;
        }

        .repeater-title {
            font-weight: 600;
            color: var(--dark);
        }

        .file-preview {
            display: flex;
            align-items: center;
            gap: 12px;
            padding: 12px;
            background: #f8f9fa;
            border: 1px solid var(--border);
            border-radius: 6px;
            margin-top: 8px;
        }

        .file-preview img {
            width: 60px;
            height: 60px;
            object-fit: cover;
            border-radius: 4px;
        }

        .file-info {
            flex: 1;
        }

        .file-name {
            font-weight: 500;
            margin-bottom: 4px;
        }

        .file-size {
            font-size: 14px;
            color: var(--gray);
        }

        .progress-bar {
            height: 4px;
            background: var(--border);
            border-radius: 2px;
            overflow: hidden;
            margin-top: 8px;
        }

        .progress-fill {
            height: 100%;
            background: var(--primary);
            width: 0%;
            transition: width 0.3s ease;
        }

        .rss-import-section {
            background: #f0f7ff;
            border: 2px dashed var(--primary);
            border-radius: 8px;
            padding: 30px;
            text-align: center;
            margin-bottom: 30px;
        }

        .rss-import-section h3 {
            color: var(--primary);
            margin-bottom: 16px;
        }

        .episode-selector {
            max-height: 300px;
            overflow-y: auto;
            border: 1px solid var(--border);
            border-radius: 6px;
            margin-top: 16px;
        }

        .episode-item {
            padding: 12px 16px;
            border-bottom: 1px solid var(--border);
            cursor: pointer;
            transition: background 0.2s ease;
        }

        .episode-item:hover {
            background: #f8f9fa;
        }

        .episode-item.selected {
            background: #e8f0fe;
            border-left: 4px solid var(--primary);
        }

        .episode-title {
            font-weight: 500;
            margin-bottom: 4px;
        }

        .episode-meta {
            font-size: 14px;
            color: var(--gray);
        }

        .auto-populated {
            background: #f0f7ff !important;
            border-color: var(--primary) !important;
        }

        .field-status {
            display: flex;
            justify-content: space-between;
            margin-bottom: 4px;
        }

        .field-source {
            font-size: 12px;
            color: var(--gray);
            font-style: italic;
        }

        .source-rss {
            color: var(--primary);
        }

        .source-manual {
            color: var(--secondary);
        }

        .source-missing {
            color: var(--warning);
        }

        @media (max-width: 768px) {
            .container {
                margin: 0;
                border-radius: 0;
            }

            .header {
                padding: 20px;
            }

            .header h1 {
                font-size: 2rem;
            }

            .tab {
                padding: 12px 16px;
                font-size: 14px;
            }

            .tab-content {
                padding: 20px;
            }

            .form-row {
                grid-template-columns: 1fr;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <!-- Header -->
        <div class="header">
            <h1>🎙️ Podcast Episode Manager</h1>
            <p>Import from RSS, edit, and manage your podcast episodes</p>
        </div>

        <!-- Tabs -->
        <div class="tabs">
            <button class="tab active" onclick="switchTab('import')">📥 Import RSS</button>
            <button class="tab" onclick="switchTab('episode')">🎧 Episode Details</button>
            <button class="tab" onclick="switchTab('media')">🎵 Media & Files</button>
            <button class="tab" onclick="switchTab('publish')">🚀 Publish & Distribute</button>
            <button class="tab" onclick="switchTab('workflow')">⚙️ Workflow</button>
        </div>

        <!-- Import Tab -->
        <div id="import-tab" class="tab-content active">
            <div class="rss-import-section">
                <h3>Import Episode from RSS Feed</h3>
                <p>Paste your RSS feed URL to auto-populate episode details</p>

                <div class="form-group">
                    <label for="rss-url">RSS Feed URL</label>
                    <div style="display: flex; gap: 10px;">
                        <input type="url" id="rss-url" placeholder="https://anchor.fm/s/98e2f3e0/podcast/rss" style="flex: 1;">
                        <button class="btn btn-primary" onclick="fetchRSS()">Fetch Episodes</button>
                    </div>
                </div>

                <div id="episode-list" class="episode-selector" style="display: none;">
                    <!-- Episode list will be populated here -->
                </div>

                <div id="import-status" style="margin-top: 16px; display: none;">
                    <div class="progress-bar">
                        <div class="progress-fill" id="import-progress"></div>
                    </div>
                    <p id="import-message" style="margin-top: 8px;"></p>
                </div>
            </div>

            <div class="section">
                <div class="section-header">
                    <h3>Currently Imported Episode</h3>
                    <span id="import-status-badge" class="status-badge status-draft">No Data</span>
                </div>
                <div class="section-content">
                    <div id="current-episode-info" style="text-align: center; padding: 40px; color: var(--gray);">
                        <p>No episode imported yet.</p>
                        <p>Fetch an RSS feed and select an episode to get started.</p>
                    </div>
                </div>
            </div>
        </div>

        <!-- Episode Details Tab -->
        <div id="episode-tab" class="tab-content">
            <div class="section">
                <div class="section-header">
                    <h3>Core Episode Information</h3>
                    <span id="episode-status" class="status-badge status-draft">Draft</span>
                </div>
                <div class="section-content">
                    <div class="form-row">
                        <div class="form-group">
                            <label for="episode_title" class="required">Episode Title</label>
                            <div class="field-status">
                                <span>Required</span>
                                <span id="episode_title_source" class="field-source source-missing">Missing</span>
                            </div>
                            <input type="text" id="episode_title" name="episode_title" placeholder="Enter episode title">
                        </div>

                        <div class="form-group">
                            <label for="episode_subtitle">Subtitle</label>
                            <div class="field-status">
                                <span>Optional</span>
                                <span id="episode_subtitle_source" class="field-source source-missing">Missing</span>
                            </div>
                            <input type="text" id="episode_subtitle" name="episode_subtitle" placeholder="Short description (max 150 chars)">
                        </div>
                    </div>

                    <div class="form-row">
                        <div class="form-group">
                            <label for="season_number">Season Number</label>
                            <div class="field-status">
                                <span>Optional</span>
                                <span id="season_number_source" class="field-source source-missing">Missing</span>
                            </div>
                            <input type="number" id="season_number" name="season_number" min="1" placeholder="1">
                        </div>

                        <div class="form-group">
                            <label for="episode_number">Episode Number</label>
                            <div class="field-status">
                                <span>Optional</span>
                                <span id="episode_number_source" class="field-source source-missing">Missing</span>
                            </div>
                            <input type="number" id="episode_number" name="episode_number" min="1" placeholder="1">
                        </div>

                        <div class="form-group">
                            <label for="series_information">Series Information</label>
                            <div class="field-status">
                                <span>Optional</span>
                                <span id="series_information_source" class="field-source source-missing">Manual</span>
                            </div>
                            <input type="text" id="series_information" name="series_information" placeholder="e.g., Part 2 of 3">
                        </div>
                    </div>

                    <div class="form-row">
                        <div class="form-group">
                            <label for="publication_datetime" class="required">Publication Date & Time</label>
                            <div class="field-status">
                                <span>Required</span>
                                <span id="publication_datetime_source" class="field-source source-missing">Missing</span>
                            </div>
                            <input type="datetime-local" id="publication_datetime" name="publication_datetime">
                        </div>

                        <div class="form-group">
                            <label for="episode_duration">Duration</label>
                            <div class="field-status">
                                <span>Optional</span>
                                <span id="episode_duration_source" class="field-source source-missing">Missing</span>
                            </div>
                            <input type="text" id="episode_duration" name="episode_duration" placeholder="HH:MM:SS">
                        </div>

                        <div class="form-group">
                            <label for="explicit_content">Explicit Content</label>
                            <div class="field-status">
                                <span>Required</span>
                                <span id="explicit_content_source" class="field-source source-missing">Missing</span>
                            </div>
                            <select id="explicit_content" name="explicit_content">
                                <option value="">Select</option>
                                <option value="no">No (Clean)</option>
                                <option value="yes">Yes (Explicit)</option>
                            </select>
                        </div>
                    </div>
                </div>
            </div>

            <div class="section">
                <div class="section-header">
                    <h3>Content & Format</h3>
                </div>
                <div class="section-content">
                    <div class="form-row">
                        <div class="form-group">
                            <label for="content_format" class="required">Content Format</label>
                            <div class="field-status">
                                <span>Required</span>
                                <span id="content_format_source" class="field-source source-missing">Manual</span>
                            </div>
                            <select id="content_format" name="content_format">
                                <option value="">Select format</option>
                                <option value="interview">Interview</option>
                                <option value="solo">Solo/Monologue</option>
                                <option value="panel">Panel Discussion</option>
                                <option value="deep-dive">Deep Dive</option>
                                <option value="storytelling">Storytelling</option>
                                <option value="mixtape">Mixtape/Curation</option>
                                <option value="qa">Q&A</option>
                                <option value="live">Live Recording</option>
                            </select>
                        </div>

                        <div class="form-group">
                            <label for="primary_category" class="required">Primary Category</label>
                            <div class="field-status">
                                <span>Required</span>
                                <span id="primary_category_source" class="field-source source-missing">Missing</span>
                            </div>
                            <select id="primary_category" name="primary_category">
                                <option value="">Select category</option>
                                <option value="arts">Arts</option>
                                <option value="business">Business</option>
                                <option value="comedy">Comedy</option>
                                <option value="education">Education</option>
                                <option value="news">News</option>
                                <option value="society">Society & Culture</option>
                                <option value="sports">Sports</option>
                                <option value="technology">Technology</option>
                            </select>
                        </div>
                    </div>

                    <div class="form-group">
                        <label for="topics_keywords">Topics & Keywords</label>
                        <div class="field-status">
                            <span>Optional</span>
                            <span id="topics_keywords_source" class="field-source source-missing">Manual</span>
                        </div>
                        <div class="tag-input" id="topics_keywords_container">
                            <input type="text" id="topics_keywords_input" placeholder="Type and press Enter to add keywords">
                        </div>
                    </div>

                    <div class="form-group">
                        <label for="episode_summary" class="required">Episode Summary</label>
                        <div class="field-status">
                            <span>Required</span>
                            <span id="episode_summary_source" class="field-source source-missing">Missing</span>
                        </div>
                        <textarea id="episode_summary" name="episode_summary" placeholder="Write a detailed summary of the episode..."></textarea>
                    </div>
                </div>
            </div>

            <div class="section">
                <div class="section-header">
                    <h3>People</h3>
                    <button type="button" class="btn btn-outline btn-small" onclick="addGuest()">+ Add Guest</button>
                </div>
                <div class="section-content">
                    <div class="form-group">
                        <label for="hosts" class="required">Host(s)</label>
                        <div class="field-status">
                            <span>Required</span>
                            <span id="hosts_source" class="field-source source-missing">Missing</span>
                        </div>
                        <select id="hosts" name="hosts" multiple style="height: 100px;">
                            <option value="john_doe">John Doe</option>
                            <option value="jane_smith">Jane Smith</option>
                            <option value="alex_johnson">Alex Johnson</option>
                        </select>
                        <small>Hold Ctrl/Cmd to select multiple hosts</small>
                    </div>

                    <div id="guests-container">
                        <!-- Guest entries will be added here -->
                    </div>
                </div>
            </div>

            <div class="section">
                <div class="section-header">
                    <h3>Show Notes & Links</h3>
                </div>
                <div class="section-content">
                    <div class="form-group">
                        <label for="show_notes">Detailed Show Notes</label>
                        <div class="field-status">
                            <span>Optional</span>
                            <span id="show_notes_source" class="field-source source-missing">Missing</span>
                        </div>
                        <textarea id="show_notes" name="show_notes" placeholder="Include timestamps, links, and key takeaways..."></textarea>
                    </div>

                    <div id="resources-container">
                        <!-- Resource links will be added here -->
                    </div>

                    <div class="form-row">
                        <div class="form-group">
                            <label for="primary_cta_text">Primary CTA Text</label>
                            <input type="text" id="primary_cta_text" name="primary_cta_text" placeholder="e.g., Get the Free Guide">
                        </div>
                        <div class="form-group">
                            <label for="primary_cta_url">Primary CTA URL</label>
                            <input type="url" id="primary_cta_url" name="primary_cta_url" placeholder="https://example.com/guide">
                        </div>
                    </div>

                    <div class="form-row">
                        <div class="form-group">
                            <label for="secondary_cta_text">Secondary CTA Text</label>
                            <input type="text" id="secondary_cta_text" name="secondary_cta_text" placeholder="e.g., Subscribe to Newsletter">
                        </div>
                        <div class="form-group">
                            <label for="secondary_cta_url">Secondary CTA URL</label>
                            <input type="url" id="secondary_cta_url" name="secondary_cta_url" placeholder="https://example.com/newsletter">
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- Media & Files Tab -->
        <div id="media-tab" class="tab-content">
            <div class="section">
                <div class="section-header">
                    <h3>Episode Media</h3>
                </div>
                <div class="section-content">
                    <div class="form-group">
                        <label for="episode_artwork" class="required">Episode Artwork</label>
                        <div class="field-status">
                            <span>Required</span>
                            <span id="episode_artwork_source" class="field-source source-missing">Missing</span>
                        </div>
                        <input type="file" id="episode_artwork" name="episode_artwork" accept="image/*" onchange="previewImage(this)">
                        <div id="artwork-preview" class="file-preview" style="display: none;">
                            <img id="artwork-thumbnail" src="" alt="Artwork Preview">
                            <div class="file-info">
                                <div class="file-name" id="artwork-name"></div>
                                <div class="file-size" id="artwork-size"></div>
                            </div>
                            <button type="button" class="btn btn-danger btn-small" onclick="clearArtwork()">Remove</button>
                        </div>
                        <small>Square image, 3000x3000px recommended, JPG or PNG</small>
                    </div>

                    <div class="form-group">
                        <label for="audio_file" class="required">Audio File (MP3)</label>
                        <div class="field-status">
                            <span>Required</span>
                            <span id="audio_file_source" class="field-source source-missing">Missing</span>
                        </div>
                        <input type="file" id="audio_file" name="audio_file" accept="audio/mpeg" onchange="previewAudio(this)">
                        <div id="audio-preview" class="file-preview" style="display: none;">
                            <div class="file-info">
                                <div class="file-name" id="audio-name"></div>
                                <div class="file-size" id="audio-size"></div>
                            </div>
                        </div>
                        <small>MP3 format, max 200MB</small>
                    </div>

                    <div class="form-group">
                        <label for="transcript_file">Transcript (TXT)</label>
                        <input type="file" id="transcript_file" name="transcript_file" accept=".txt">
                    </div>

                    <div class="form-group">
                        <label for="subtitles_file">Subtitles (SRT/VTT)</label>
                        <input type="file" id="subtitles_file" name="subtitles_file" accept=".srt,.vtt">
                    </div>

                    <div class="form-group">
                        <label for="glossary_file">Glossary / Unique Words</label>
                        <input type="file" id="glossary_file" name="glossary_file" accept=".txt,.json">
                    </div>
                </div>
            </div>
        </div>

        <!-- Publish & Distribute Tab -->
        <div id="publish-tab" class="tab-content">
            <div class="section">
                <div class="section-header">
                    <h3>Publishing Settings</h3>
                </div>
                <div class="section-content">
                    <div class="form-group">
                        <label for="episode_slug">Episode Slug / URL</label>
                        <div class="field-status">
                            <span>Optional</span>
                            <span id="episode_slug_source" class="field-source source-missing">Auto-generated</span>
                        </div>
                        <input type="text" id="episode_slug" name="episode_slug" placeholder="auto-generated-from-title">
                        <small>Used for the episode URL. Will be auto-generated from title if left empty.</small>
                    </div>

                    <div class="form-group">
                        <label for="meta_description">Meta Description</label>
                        <textarea id="meta_description" name="meta_description" maxlength="155" placeholder="SEO description for search engines"></textarea>
                        <small><span id="meta-desc-count">0</span>/155 characters</small>
                    </div>

                    <div class="form-group">
                        <label>Distribution Channels</label>
                        <div class="checkbox-group">
                            <div class="checkbox-item">
                                <input type="checkbox" id="publish_apple" name="publish_apple" checked>
                                <label for="publish_apple">Apple Podcasts</label>
                            </div>
                            <div class="checkbox-item">
                                <input type="checkbox" id="publish_spotify" name="publish_spotify" checked>
                                <label for="publish_spotify">Spotify</label>
                            </div>
                            <div class="checkbox-item">
                                <input type="checkbox" id="publish_youtube" name="publish_youtube">
                                <label for="publish_youtube">YouTube</label>
                            </div>
                            <div class="checkbox-item">
                                <input type="checkbox" id="include_newsletter" name="include_newsletter" checked>
                                <label for="include_newsletter">Newsletter</label>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <div class="section">
                <div class="section-header">
                    <h3>Related Content</h3>
                </div>
                <div class="section-content">
                    <div class="form-group">
                        <label for="related_episodes">Related Episodes</label>
                        <select id="related_episodes" name="related_episodes" multiple style="height: 100px;">
                            <option value="ep1">Previous Episode: Getting Started</option>
                            <option value="ep2">Next Episode: Advanced Topics</option>
                            <option value="ep3">Interview with Expert</option>
                        </select>
                        <small>Hold Ctrl/Cmd to select multiple episodes</small>
                    </div>

                    <div class="form-group">
                        <label for="merchandise_ideas">Merchandise Ideas</label>
                        <div class="tag-input" id="merchandise_container">
                            <input type="text" id="merchandise_input" placeholder="Type and press Enter to add merch ideas">
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- Workflow Tab -->
        <div id="workflow-tab" class="tab-content">
            <div class="section">
                <div class="section-header">
                    <h3>Workflow & Status</h3>
                </div>
                <div class="section-content">
                    <div class="form-row">
                        <div class="form-group">
                            <label for="internal_status">Internal Status</label>
                            <select id="internal_status" name="internal_status">
                                <option value="draft">Draft</option>
                                <option value="in_review">In Review</option>
                                <option value="ready">Ready to Publish</option>
                                <option value="scheduled">Scheduled</option>
                                <option value="published">Published</option>
                            </select>
                        </div>

                        <div class="form-group">
                            <label for="assigned_editor">Assigned Editor</label>
                            <select id="assigned_editor" name="assigned_editor">
                                <option value="">Unassigned</option>
                                <option value="editor1">Jane Smith</option>
                                <option value="editor2">John Doe</option>
                                <option value="editor3">Alex Johnson</option>
                            </select>
                        </div>
                    </div>

                    <div class="form-group">
                        <label for="internal_notes">Internal Notes</label>
                        <textarea id="internal_notes" name="internal_notes" placeholder="Notes for the team..."></textarea>
                    </div>
                </div>
            </div>

            <div class="section">
                <div class="section-header">
                    <h3>Timestamps (Chapters)</h3>
                    <button type="button" class="btn btn-outline btn-small" onclick="addTimestamp()">+ Add Timestamp</button>
                </div>
                <div class="section-content">
                    <div id="chapters-container">
                        <!-- Chapter entries will be added here -->
                    </div>
                </div>
            </div>
        </div>

        <!-- Form Actions -->
        <div class="form-actions">
            <button type="button" class="btn btn-outline" onclick="resetForm()">Reset Form</button>
            <button type="button" class="btn btn-secondary" onclick="saveDraft()">Save Draft</button>
            <button type="button" class="btn btn-primary" onclick="submitForm()">Publish Episode</button>
        </div>
    </div>

    <script>
        // Global variables
        let currentEpisode = null;
        let episodeData = {
            // Initialize with default values
            episode_title: '',
            episode_subtitle: '',
            season_number: '',
            episode_number: '',
            series_information: '',
            publication_datetime: '',
            episode_duration: '',
            explicit_content: '',
            content_format: '',
            primary_category: '',
            topics_keywords: [],
            episode_summary: '',
            hosts: [],
            guests: [],
            show_notes: '',
            resources_links: [],
            primary_cta_text: '',
            primary_cta_url: '',
            secondary_cta_text: '',
            secondary_cta_url: '',
            chapters: [],
            episode_artwork: null,
            audio_file: null,
            transcript_file: null,
            subtitles_file: null,
            glossary_file: null,
            episode_slug: '',
            meta_description: '',
            publish_apple: true,
            publish_spotify: true,
            publish_youtube: false,
            include_newsletter: true,
            related_episodes: [],
            merchandise_ideas: [],
            internal_status: 'draft',
            internal_notes: '',
            assigned_editor: '',
            // Track field sources
            field_sources: {}
        };

        // Tab switching
        function switchTab(tabName) {
            // Hide all tabs
            document.querySelectorAll('.tab-content').forEach(tab => {
                tab.classList.remove('active');
            });

            // Remove active class from all tabs
            document.querySelectorAll('.tab').forEach(tab => {
                tab.classList.remove('active');
            });

            // Show selected tab
            document.getElementById(`${tabName}-tab`).classList.add('active');

            // Activate corresponding tab button
            document.querySelectorAll('.tab').forEach(tab => {
                if (tab.textContent.includes(tabName.charAt(0).toUpperCase() + tabName.slice(1))) {
                    tab.classList.add('active');
                }
            });
        }

        // Fetch RSS feed
        async function fetchRSS() {
            const rssUrl = document.getElementById('rss-url').value;
            if (!rssUrl) {
                alert('Please enter an RSS feed URL');
                return;
            }

            const importStatus = document.getElementById('import-status');
            const importProgress = document.getElementById('import-progress');
            const importMessage = document.getElementById('import-message');

            importStatus.style.display = 'block';
            importProgress.style.width = '30%';
            importMessage.textContent = 'Fetching RSS feed...';

            try {
                // Note: In a real implementation, you would use a CORS proxy
                // or server-side endpoint to fetch RSS feeds
                const response = await fetch(`https://api.allorigins.win/get?url=${encodeURIComponent(rssUrl)}`);
                const data = await response.json();

                importProgress.style.width = '60%';
                importMessage.textContent = 'Parsing RSS feed...';

                // Parse the RSS feed
                const parser = new DOMParser();
                const xmlDoc = parser.parseFromString(data.contents, 'text/xml');

                // Extract channel info
                const channel = xmlDoc.querySelector('channel');
                const episodes = xmlDoc.querySelectorAll('item');

                // Display episodes
                const episodeList = document.getElementById('episode-list');
                episodeList.innerHTML = '';
                episodeList.style.display = 'block';

                episodes.forEach((episode, index) => {
                    const title = episode.querySelector('title')?.textContent || `Episode ${index + 1}`;
                    const pubDate = episode.querySelector('pubDate')?.textContent || '';
                    const guid = episode.querySelector('guid')?.textContent || '';

                    const episodeDiv = document.createElement('div');
                    episodeDiv.className = 'episode-item';
                    episodeDiv.dataset.index = index;
                    episodeDiv.dataset.guid = guid;
                    episodeDiv.innerHTML = `
                        <div class="episode-title">${title}</div>
                        <div class="episode-meta">${pubDate}</div>
                    `;

                    episodeDiv.onclick = () => selectEpisode(episode, channel);
                    episodeList.appendChild(episodeDiv);
                });

                importProgress.style.width = '100%';
                importMessage.textContent = `Found ${episodes.length} episodes`;

                setTimeout(() => {
                    importStatus.style.display = 'none';
                }, 2000);

            } catch (error) {
                console.error('Error fetching RSS:', error);
                importProgress.style.width = '0%';
                importMessage.textContent = 'Error fetching RSS feed. Please check the URL and try again.';
                importMessage.style.color = 'var(--danger)';
            }
        }

        // Select episode from RSS
        function selectEpisode(episodeElement, channelElement) {
            // Update UI
            document.querySelectorAll('.episode-item').forEach(item => {
                item.classList.remove('selected');
            });
            event.currentTarget.classList.add('selected');

            // Parse RSS data
            const rssData = {
                // Core information
                episode_title: getRssValue(episodeElement, 'title'),
                episode_subtitle: getRssValue(episodeElement, 'itunes|subtitle'),
                episode_summary: getRssValue(episodeElement, 'description') || 
                                getRssValue(episodeElement, 'content|encoded') ||
                                getRssValue(episodeElement, 'itunes|summary'),
                publication_datetime: getRssValue(episodeElement, 'pubDate'),
                episode_duration: getRssValue(episodeElement, 'itunes|duration'),
                explicit_content: getRssValue(episodeElement, 'itunes|explicit'),
                episode_number: getRssValue(episodeElement, 'itunes|episode'),
                season_number: getRssValue(episodeElement, 'itunes|season'),
                content_format: getRssValue(episodeElement, 'itunes|episodeType'),

                // Media
                episode_artwork: getRssAttribute(episodeElement, 'itunes|image', 'href') ||
                                getRssAttribute(channelElement, 'itunes|image', 'href'),
                audio_file: getRssAttribute(episodeElement, 'enclosure', 'url'),
                transcript_file: getRssAttribute(episodeElement, 'podcast|transcript', 'url'),

                // Channel info
                primary_category: getRssAttribute(channelElement, 'itunes|category', 'text'),
                hosts: [getRssValue(channelElement, 'itunes|author') || 
                       getRssValue(channelElement, 'dc|creator')].filter(Boolean),

                // URLs
                episode_slug: getRssValue(episodeElement, 'link') || 
                             getRssValue(episodeElement, 'guid'),
                meta_description: getRssValue(episodeElement, 'itunes|summary')
            };

            // Update form with RSS data
            updateFormWithRSSData(rssData);

            // Update current episode display
            document.getElementById('current-episode-info').innerHTML = `
                <h3>${rssData.episode_title || 'Untitled Episode'}</h3>
                <p>${rssData.episode_subtitle || ''}</p>
                <p><small>Duration: ${rssData.episode_duration || 'N/A'} | 
                Explicit: ${rssData.explicit_content || 'N/A'}</small></p>
                <button class="btn btn-outline" onclick="switchTab('episode')">
                    Edit Episode Details →
                </button>
            `;

            document.getElementById('import-status-badge').textContent = 'Imported';
            document.getElementById('import-status-badge').className = 'status-badge status-ready';

            // Switch to episode tab
            switchTab('episode');
        }

        // Helper function to get RSS value
        function getRssValue(element, name) {
            if (!element) return '';

            // Handle namespaced elements
            const parts = name.split('|');
            if (parts.length === 2) {
                const [namespace, localName] = parts;
                return element.getElementsByTagNameNS(`http://www.itunes.com/dtds/podcast-1.0.dtd`, localName)[0]?.textContent || '';
            }

            return element.querySelector(name)?.textContent || '';
        }

        // Helper function to get RSS attribute
        function getRssAttribute(element, name, attr) {
            if (!element) return '';

            const parts = name.split('|');
            if (parts.length === 2) {
                const [namespace, localName] = parts;
                const elem = element.getElementsByTagNameNS(`http://www.itunes.com/dtds/podcast-1.0.dtd`, localName)[0];
                return elem?.getAttribute(attr) || '';
            }

            return element.querySelector(name)?.getAttribute(attr) || '';
        }

        // Update form with RSS data
        function updateFormWithRSSData(rssData) {
            // Store the data
            currentEpisode = rssData;

            // Update each field
            for (const [key, value] of Object.entries(rssData)) {
                if (value) {
                    const element = document.getElementById(key);
                    if (element) {
                        element.value = value;

                        // Mark as auto-populated
                        element.classList.add('auto-populated');

                        // Update field source indicator
                        const sourceElement = document.getElementById(`${key}_source`);
                        if (sourceElement) {
                            sourceElement.textContent = 'RSS';
                            sourceElement.className = 'field-source source-rss';
                        }

                        // Store in episodeData
                        episodeData[key] = value;
                        episodeData.field_sources[key] = 'rss';
                    }
                }
            }

            // Special handling for arrays
            if (rssData.hosts && rssData.hosts.length > 0) {
                const hostsSelect = document.getElementById('hosts');
                Array.from(hostsSelect.options).forEach(option => {
                    if (rssData.hosts.some(host => option.text.toLowerCase().includes(host.toLowerCase()))) {
                        option.selected = true;
                    }
                });
            }

            // Update meta description counter
            updateMetaDescCounter();

            // Update status badge
            document.getElementById('episode-status').textContent = 'Imported';
            document.getElementById('episode-status').className = 'status-badge status-ready';
        }

        // Add guest
        function addGuest() {
            const container = document.getElementById('guests-container');
            const guestCount = container.children.length + 1;

            const guestDiv = document.createElement('div');
            guestDiv.className = 'repeater-item';
            guestDiv.innerHTML = `
                <div class="repeater-header">
                    <span class="repeater-title">Guest #${guestCount}</span>
                    <button type="button" class="btn btn-danger btn-small" onclick="removeGuest(this)">Remove</button>
                </div>
                <div class="form-row">
                    <div class="form-group">
                        <label>Guest Name</label>
                        <input type="text" name="guest_name[]" placeholder="Full name">
                    </div>
                    <div class="form-group">
                        <label>Title / Company</label>
                        <input type="text" name="guest_title[]" placeholder="Position and company">
                    </div>
                </div>
                <div class="form-group">
                    <label>Bio</label>
                    <textarea name="guest_bio[]" placeholder="Short bio"></textarea>
                </div>
                <div class="form-row">
                    <div class="form-group">
                        <label>Website / Social Link</label>
                        <input type="url" name="guest_website[]" placeholder="https://">
                    </div>
                    <div class="form-group">
                        <label>Headshot</label>
                        <input type="file" name="guest_headshot[]" accept="image/*">
                    </div>
                </div>
            `;

            container.appendChild(guestDiv);
        }

        // Remove guest
        function removeGuest(button) {
            button.closest('.repeater-item').remove();
            updateGuestNumbers();
        }

        // Update guest numbers
        function updateGuestNumbers() {
            const guests = document.querySelectorAll('#guests-container .repeater-item');
            guests.forEach((guest, index) => {
                guest.querySelector('.repeater-title').textContent = `Guest #${index + 1}`;
            });
        }

        // Add timestamp
        function addTimestamp() {
            const container = document.getElementById('chapters-container');
            const chapterCount = container.children.length + 1;

            const chapterDiv = document.createElement('div');
            chapterDiv.className = 'repeater-item';
            chapterDiv.innerHTML = `
                <div class="repeater-header">
                    <span class="repeater-title">Chapter #${chapterCount}</span>
                    <button type="button" class="btn btn-danger btn-small" onclick="removeChapter(this)">Remove</button>
                </div>
                <div class="form-row">
                    <div class="form-group">
                        <label>Timecode</label>
                        <input type="text" name="chapter_timecode[]" placeholder="HH:MM:SS">
                    </div>
                    <div class="form-group">
                        <label>Chapter Title</label>
                        <input type="text" name="chapter_title[]" placeholder="Introduction">
                    </div>
                </div>
                <div class="form-group">
                    <label>Description</label>
                    <textarea name="chapter_description[]" placeholder="Optional description"></textarea>
                </div>
            `;

            container.appendChild(chapterDiv);
        }

        // Remove chapter
        function removeChapter(button) {
            button.closest('.repeater-item').remove();
            updateChapterNumbers();
        }

        // Update chapter numbers
        function updateChapterNumbers() {
            const chapters = document.querySelectorAll('#chapters-container .repeater-item');
            chapters.forEach((chapter, index) => {
                chapter.querySelector('.repeater-title').textContent = `Chapter #${index + 1}`;
            });
        }

        // Preview image
        function previewImage(input) {
            if (input.files && input.files[0]) {
                const file = input.files[0];
                const reader = new FileReader();

                reader.onload = function(e) {
                    const preview = document.getElementById('artwork-preview');
                    const thumbnail = document.getElementById('artwork-thumbnail');
                    const name = document.getElementById('artwork-name');
                    const size = document.getElementById('artwork-size');

                    thumbnail.src = e.target.result;
                    name.textContent = file.name;
                    size.textContent = formatFileSize(file.size);
                    preview.style.display = 'flex';

                    // Update field source
                    const sourceElement = document.getElementById('episode_artwork_source');
                    sourceElement.textContent = 'Manual Upload';
                    sourceElement.className = 'field-source source-manual';

                    input.classList.remove('auto-populated');
                };

                reader.readAsDataURL(file);
            }
        }

        // Preview audio
        function previewAudio(input) {
            if (input.files && input.files[0]) {
                const file = input.files[0];
                const preview = document.getElementById('audio-preview');
                const name = document.getElementById('audio-name');
                const size = document.getElementById('audio-size');

                name.textContent = file.name;
                size.textContent = formatFileSize(file.size);
                preview.style.display = 'flex';

                // Update field source
                const sourceElement = document.getElementById('audio_file_source');
                sourceElement.textContent = 'Manual Upload';
                sourceElement.className = 'field-source source-manual';

                input.classList.remove('auto-populated');
            }
        }

        // Clear artwork
        function clearArtwork() {
            document.getElementById('episode_artwork').value = '';
            document.getElementById('artwork-preview').style.display = 'none';

            // Update field source
            const sourceElement = document.getElementById('episode_artwork_source');
            sourceElement.textContent = 'Missing';
            sourceElement.className = 'field-source source-missing';
        }

        // Format file size
        function formatFileSize(bytes) {
            if (bytes === 0) return '0 Bytes';
            const k = 1024;
            const sizes = ['Bytes', 'KB', 'MB', 'GB'];
            const i = Math.floor(Math.log(bytes) / Math.log(k));
            return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
        }

        // Update meta description counter
        function updateMetaDescCounter() {
            const textarea = document.getElementById('meta_description');
            const counter = document.getElementById('meta-desc-count');
            counter.textContent = textarea.value.length;
        }

        // Initialize tag inputs
        function initTagInputs() {
            // Topics/keywords
            const topicsInput = document.getElementById('topics_keywords_input');
            const topicsContainer = document.getElementById('topics_keywords_container');

            topicsInput.addEventListener('keypress', function(e) {
                if (e.key === 'Enter' && this.value.trim()) {
                    e.preventDefault();
                    addTag(this.value.trim(), topicsContainer);
                    this.value = '';
                }
            });

            // Merchandise ideas
            const merchInput = document.getElementById('merchandise_input');
            const merchContainer = document.getElementById('merchandise_container');

            merchInput.addEventListener('keypress', function(e) {
                if (e.key === 'Enter' && this.value.trim()) {
                    e.preventDefault();
                    addTag(this.value.trim(), merchContainer);
                    this.value = '';
                }
            });
        }

        // Add tag
        function addTag(text, container) {
            const tag = document.createElement('div');
            tag.className = 'tag';
            tag.innerHTML = `
                ${text}
                <button type="button" class="tag-remove" onclick="removeTag(this)">×</button>
            `;

            // Insert before the input
            const input = container.querySelector('input');
            container.insertBefore(tag, input);
        }

        // Remove tag
        function removeTag(button) {
            button.closest('.tag').remove();
        }

        // Reset form
        function resetForm() {
            if (confirm('Are you sure you want to reset the form? All changes will be lost.')) {
                // Clear all inputs
                document.querySelectorAll('input, textarea, select').forEach(element => {
                    if (element.type !== 'button') {
                        element.value = '';
                        element.classList.remove('auto-populated');
                    }
                });

                // Clear checkboxes
                document.querySelectorAll('input[type="checkbox"]').forEach(cb => {
                    cb.checked = false;
                });

                // Reset multi-selects
                document.querySelectorAll('select[multiple]').forEach(select => {
                    Array.from(select.options).forEach(option => {
                        option.selected = false;
                    });
                });

                // Clear file previews
                document.querySelectorAll('.file-preview').forEach(preview => {
                    preview.style.display = 'none';
                });

                // Clear containers
                document.getElementById('guests-container').innerHTML = '';
                document.getElementById('chapters-container').innerHTML = '';

                // Reset field sources
                document.querySelectorAll('.field-source').forEach(source => {
                    source.textContent = 'Missing';
                    source.className = 'field-source source-missing';
                });

                // Reset current episode
                currentEpisode = null;
                episodeData = {
                    field_sources: {}
                };

                // Update UI
                document.getElementById('current-episode-info').innerHTML = `
                    <p>No episode imported yet.</p>
                    <p>Fetch an RSS feed and select an episode to get started.</p>
                `;

                document.getElementById('import-status-badge').textContent = 'No Data';
                document.getElementById('import-status-badge').className = 'status-badge status-draft';

                document.getElementById('episode-status').textContent = 'Draft';
                document.getElementById('episode-status').className = 'status-badge status-draft';
            }
        }

        // Save draft
        function saveDraft() {
            // Collect form data
            collectFormData();

            // In a real app, this would save to a database
            console.log('Saving draft:', episodeData);

            // Update UI
            document.getElementById('episode-status').textContent = 'Draft Saved';
            document.getElementById('episode-status').className = 'status-badge status-ready';

            // Show success message
            alert('Draft saved successfully!');
        }

        // Submit form
        function submitForm() {
            // Collect form data
            collectFormData();

            // Validate required fields
            const requiredFields = [
                'episode_title',
                'episode_summary',
                'episode_artwork',
                'audio_file'
            ];

            const missingFields = [];
            for (const field of requiredFields) {
                if (!episodeData[field]) {
                    missingFields.push(field.replace('_', ' '));
                }
            }

            if (missingFields.length > 0) {
                alert(`Please fill in the following required fields:\n\n• ${missingFields.join('\n• ')}`);
                return;
            }

            // Submit to server (simulated)
            console.log('Submitting episode:', episodeData);

            // Show success message
            alert('Episode submitted successfully!');

            // Update status
            document.getElementById('internal_status').value = 'published';
            document.getElementById('episode-status').textContent = 'Published';
            document.getElementById('episode-status').className = 'status-badge status-published';
        }

        // Collect form data
        function collectFormData() {
            // Collect basic fields
            const fields = [
                'episode_title', 'episode_subtitle', 'season_number', 'episode_number',
                'series_information', 'publication_datetime', 'episode_duration',
                'explicit_content', 'content_format', 'primary_category', 'episode_summary',
                'show_notes', 'primary_cta_text', 'primary_cta_url', 'secondary_cta_text',
                'secondary_cta_url', 'episode_slug', 'meta_description', 'internal_status',
                'internal_notes', 'assigned_editor'
            ];

            fields.forEach(field => {
                const element = document.getElementById(field);
                if (element) {
                    episodeData[field] = element.value;
                }
            });

            // Collect checkboxes
            episodeData.publish_apple = document.getElementById('publish_apple').checked;
            episodeData.publish_spotify = document.getElementById('publish_spotify').checked;
            episodeData.publish_youtube = document.getElementById('publish_youtube').checked;
            episodeData.include_newsletter = document.getElementById('include_newsletter').checked;

            // Collect multi-selects
            episodeData.hosts = Array.from(document.getElementById('hosts').selectedOptions).map(opt => opt.value);
            episodeData.related_episodes = Array.from(document.getElementById('related_episodes').selectedOptions).map(opt => opt.value);

            // Collect tags
            episodeData.topics_keywords = Array.from(document.querySelectorAll('#topics_keywords_container .tag'))
                .map(tag => tag.textContent.replace('×', '').trim());

            episodeData.merchandise_ideas = Array.from(document.querySelectorAll('#merchandise_container .tag'))
                .map(tag => tag.textContent.replace('×', '').trim());

            // Collect guests
            episodeData.guests = [];
            document.querySelectorAll('#guests-container .repeater-item').forEach(item => {
                const guest = {
                    guest_name: item.querySelector('input[name="guest_name[]"]')?.value || '',
                    guest_title: item.querySelector('input[name="guest_title[]"]')?.value || '',
                    guest_bio: item.querySelector('textarea[name="guest_bio[]"]')?.value || '',
                    guest_website: item.querySelector('input[name="guest_website[]"]')?.value || '',
                    guest_headshot: item.querySelector('input[name="guest_headshot[]"]')?.files[0] || null
                };
                if (guest.guest_name) {
                    episodeData.guests.push(guest);
                }
            });

            // Collect chapters
            episodeData.chapters = [];
            document.querySelectorAll('#chapters-container .repeater-item').forEach(item => {
                const chapter = {
                    chapter_timecode: item.querySelector('input[name="chapter_timecode[]"]')?.value || '',
                    chapter_title: item.querySelector('input[name="chapter_title[]"]')?.value || '',
                    chapter_description: item.querySelector('textarea[name="chapter_description[]"]')?.value || ''
                };
                if (chapter.chapter_timecode && chapter.chapter_title) {
                    episodeData.chapters.push(chapter);
                }
            });

            // Collect files
            episodeData.episode_artwork = document.getElementById('episode_artwork').files[0] || null;
            episodeData.audio_file = document.getElementById('audio_file').files[0] || null;
            episodeData.transcript_file = document.getElementById('transcript_file').files[0] || null;
            episodeData.subtitles_file = document.getElementById('subtitles_file').files[0] || null;
            episodeData.glossary_file = document.getElementById('glossary_file').files[0] || null;
        }

        // Initialize
        document.addEventListener('DOMContentLoaded', function() {
            // Initialize tag inputs
            initTagInputs();

            // Set up meta description counter
            document.getElementById('meta_description').addEventListener('input', updateMetaDescCounter);

            // Set default publication date to tomorrow
            const tomorrow = new Date();
            tomorrow.setDate(tomorrow.getDate() + 1);
            const formattedDate = tomorrow.toISOString().slice(0, 16);
            document.getElementById('publication_datetime').value = formattedDate;

            // Add sample guests and chapters
            addGuest();
            addTimestamp();

            // Mark manual fields
            const manualFields = [
                'content_format', 'series_information', 'topics_keywords',
                'primary_cta_text', 'primary_cta_url', 'secondary_cta_text', 'secondary_cta_url',
                'merchandise_ideas', 'internal_status', 'internal_notes', 'assigned_editor'
            ];

            manualFields.forEach(field => {
                const sourceElement = document.getElementById(`${field}_source`);
                if (sourceElement) {
                    sourceElement.textContent = 'Manual';
                    sourceElement.className = 'field-source source-manual';
                }
            });
        });
    </script>
</body>
</html>

Key Features of This Implementation:

1. RSS Auto-Population

  • Fetches RSS feed and extracts episode data
  • Maps RSS fields to form fields automatically
  • Shows field source indicators (RSS/Manual/Missing)
  • Highlights auto-populated fields

2. Smart Field Management

  • Field Source Tracking: Each field shows where the data came from
  • Auto-populated Styling: Fields from RSS are visually distinct
  • Missing Field Indicators: Shows which required fields are empty
  • Manual Override: Can edit any auto-populated field

3. Tabbed Interface

  • Import RSS Tab: Fetch and select episodes
  • Episode Details Tab: Core information, content, people, show notes
  • Media & Files Tab: Upload artwork, audio, transcripts
  • Publish & Distribute: Distribution channels, related content
  • Workflow Tab: Internal status, timestamps, team notes

4. Interactive Components

  • Tag Inputs: For topics/keywords and merchandise ideas
  • Repeater Sections: Add multiple guests, chapters, resources
  • File Previews: Image and audio file previews
  • Dynamic Validation: Real-time field validation

5. Data Collection

  • Collects all form data into a structured object
  • Preserves RSS source information
  • Handles file uploads
  • Supports nested data (guests, chapters)

6. User Experience

  • Clear visual hierarchy
  • Responsive design
  • Progress indicators
  • Status badges
  • Intuitive navigation

How It Works:

  1. Import: Paste RSS URL → Fetch episodes → Select episode
  2. Auto-Populate: Form fills with RSS data, source indicators update
  3. Edit: Manually edit any field (overwrites RSS data)
  4. Add: Fill in missing fields not in RSS (guests, CTAs, etc.)
  5. Save/Publish: Validate and submit to server

This form bridges the gap between RSS import (automatic) and manual content creation, making podcast episode management efficient while maintaining flexibility.

Raw Paste

Comments 0
Login to post a comment.
  • No comments yet. Be the first.
Login to post a comment. Login or Register
We use cookies. To comply with GDPR in the EU and the UK we have to show you these.

We use cookies and similar technologies to keep this website functional (including spam protection via Google reCAPTCHA or Cloudflare Turnstile), and — with your consent — to measure usage and show ads. See Privacy.