Basic Podcast Example
Basic Podcast Example
Section titled “Basic Podcast Example”This example shows a complete, minimal podcast website using Podcast Framework. Perfect for getting started quickly.
Overview
Section titled “Overview”What you’ll build:
- Homepage with recent episodes
- Episode archive with search
- Individual episode pages
- Guest directory
- About page
Time to build: 15-20 minutes
Difficulty: Beginner
Step 1: Create Project
Section titled “Step 1: Create Project”npm create @rejected-media/podcast-framework basic-podcastcd basic-podcastnpm installStep 2: Set Up Sanity
Section titled “Step 2: Set Up Sanity”# Initialize Sanitynpx sanity@latest init
# Answers:# Create new project? Yes# Project name: basic-podcast# Use default dataset? Yes# Output path: ./sanity
# Deploy schemascd sanitynpx sanity schema deploycd ..Step 3: Configure Environment
Section titled “Step 3: Configure Environment”Create .env:
cp .env.template .envEdit .env:
PUBLIC_SANITY_PROJECT_ID="your-project-id"PUBLIC_SANITY_DATASET="production"PUBLIC_SANITY_API_VERSION="2024-01-01"PUBLIC_SITE_URL="http://localhost:4321"Step 4: Add Content
Section titled “Step 4: Add Content”Start Sanity Studio:
npm run dev:sanityCreate Podcast:
- Click “Podcast” → Create new
- Fill in:
- Name: “Tech Talk”
- Tagline: “Weekly tech conversations”
- Is Active: ON
- Publish
Create Host:
- Click “Host” → Create new
- Fill in:
- Name: “Your Name”
- Publish
Create Guest:
- Click “Guest” → Create new
- Fill in:
- Name: “First Guest”
- Bio: “Expert in…”
- Publish
Create Episode:
- Click “Episode” → Create new
- Fill in:
- Title: “Welcome to the Show”
- Episode Number: 1
- Publish Date: Today
- Duration: “45:00”
- Description: “Our first episode…”
- Hosts: Select your host
- Guests: Select your guest
- Publish
Step 5: Start Dev Server
Section titled “Step 5: Start Dev Server”npm run devVisit http://localhost:4321 - your podcast site is running!
File Structure
Section titled “File Structure”basic-podcast/├── src/│ ├── pages/│ │ ├── index.astro # Homepage│ │ ├── about.astro # About page│ │ ├── episodes/│ │ │ ├── index.astro # Episode archive│ │ │ └── [slug].astro # Episode pages│ │ ├── guests/│ │ │ └── index.astro # Guest directory│ │ └── guest/│ │ └── [slug].astro # Guest profiles│ └── env.d.ts├── sanity/│ ├── schemas/ # Sanity schemas│ └── sanity.config.ts├── .env # Environment variables└── package.jsonPage Examples
Section titled “Page Examples”Homepage
Section titled “Homepage”---import { getPodcast, getEpisodes, getFeatured } from '@rejected-media/podcast-framework-core';import BaseLayout from '@rejected-media/podcast-framework-core/layouts/BaseLayout.astro';import FeaturedEpisodesCarousel from '@rejected-media/podcast-framework-core/components/FeaturedEpisodesCarousel.astro';
const podcast = await getPodcast();const featured = await getFeatured(3);const recent = (await getEpisodes()).slice(0, 6);---
<BaseLayout title={podcast?.name}> <!-- Hero --> <section class="bg-blue-600 text-white py-20"> <div class="max-w-4xl mx-auto px-4 text-center"> <h1 class="text-5xl font-bold mb-4">{podcast?.name}</h1> <p class="text-xl">{podcast?.tagline}</p> </div> </section>
<!-- Featured Episodes --> {featured && featured.length > 0 && ( <FeaturedEpisodesCarousel episodes={featured} /> )}
<!-- Recent Episodes --> <section class="max-w-6xl mx-auto px-4 py-12"> <h2 class="text-3xl font-bold mb-8">Recent Episodes</h2> <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> {recent.map(episode => ( <a href={`/episodes/${episode.slug.current}`}> <article class="bg-white rounded-lg shadow-md hover:shadow-lg transition"> {episode.coverImage?.url && ( <img src={episode.coverImage.url} alt={episode.title} class="w-full h-48 object-cover rounded-t-lg" /> )} <div class="p-6"> <p class="text-sm text-blue-600 font-semibold mb-2"> Episode {episode.episodeNumber} </p> <h3 class="text-xl font-bold mb-2">{episode.title}</h3> <p class="text-gray-600">{episode.description?.substring(0, 100)}...</p> </div> </article> </a> ))} </div> </section></BaseLayout>Episode Archive
Section titled “Episode Archive”---import { getEpisodes, getPodcast, formatDate } from '@rejected-media/podcast-framework-core';import BaseLayout from '@rejected-media/podcast-framework-core/layouts/BaseLayout.astro';import EpisodeSearch from '@rejected-media/podcast-framework-core/components/EpisodeSearch.astro';
const episodes = await getEpisodes();const podcast = await getPodcast();---
<BaseLayout title={`Episodes - ${podcast?.name}`}> <div class="max-w-6xl mx-auto px-4 py-12"> <h1 class="text-4xl font-bold mb-8">All Episodes</h1>
<EpisodeSearch />
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> {episodes.map(episode => ( <article data-episode-card data-episode-title={episode.title} data-episode-description={episode.description} data-episode-guests={episode.guests?.map(g => g.name).join(', ')} > <a href={`/episodes/${episode.slug.current}`}> <!-- Episode content --> </a> </article> ))} </div> </div></BaseLayout>Customization
Section titled “Customization”Add Theme
Section titled “Add Theme”- In Sanity Studio, click “Theme”
- Create new theme
- Set your brand colors
- Publish
- Refresh website
Add Newsletter
Section titled “Add Newsletter”- Get ConvertKit account
- Add API key to Podcast document in Sanity
- Newsletter forms automatically work!
Add Custom Page
Section titled “Add Custom Page”import BaseLayout from '@rejected-media/podcast-framework-core/layouts/BaseLayout.astro';
<BaseLayout title="Sponsors"> <h1>Our Sponsors</h1> <!-- Your content --></BaseLayout>Deployment
Section titled “Deployment”Deploy to Cloudflare Pages:
# Buildnpm run build
# Deploynpx wrangler pages deploy dist --project-name=basic-podcastOr use GitHub integration for automatic deployments.
What’s Included
Section titled “What’s Included”Pages:
- ✅ Homepage with hero and recent episodes
- ✅ Episode archive with search
- ✅ Individual episode pages
- ✅ Guest directory
- ✅ Guest profile pages
- ✅ About page
- ✅ 404 error page
Components:
- ✅ Header with navigation
- ✅ Footer with social links
- ✅ Episode search
- ✅ Featured episodes carousel (if you mark episodes as featured)
Features:
- ✅ CMS-driven content
- ✅ SEO optimized
- ✅ Mobile responsive
- ✅ Fast page loads
Next Steps
Section titled “Next Steps”- Add more episodes
- Customize theme
- Add custom domain
- Set up analytics
Related
Section titled “Related”- Quick Start - Getting started guide
- Customization - Customize further
- Deployment - Deploy to production