A ready-to-use template for creating beautiful podcast websites built with Podcast Framework.
Click the "Use this template" button above to create your own repository.
git clone https://github.com/YOUR_USERNAME/your-podcast.git
cd your-podcastnpm installCreate a Sanity project at sanity.io/manage
- Click "Create Project"
- Name your project
- Copy the Project ID
# Copy the template
cp .env.template .env.local
# Edit .env.local and add your credentials
nano .env.localRequired variables:
PUBLIC_SANITY_PROJECT_ID- Your Sanity project ID (exposed to client)SANITY_PROJECT_ID- Your Sanity project ID (server-side)PUBLIC_SANITY_DATASET- Usually "production" (exposed to client)SANITY_DATASET- Usually "production" (server-side)SANITY_API_TOKEN- Create a write token in Sanity dashboard (for API routes)
Start the website:
npm run devStart Sanity Studio (in another terminal):
npm run sanity:devThe Sanity Studio is your content management interface. Run it locally to add/edit episodes:
npm run sanity:devThis starts the Studio at http://localhost:3333
To make your Studio accessible from anywhere (recommended for production):
- Make sure your
.env.localhas correct credentials - Deploy to Sanity Cloud:
npm run sanity:deploy
- Follow the prompts to choose a studio hostname
- Your Studio will be available at
https://your-studio.sanity.studio
The free tier includes unlimited Studio hosting.
- Create and edit podcast episodes
- Manage guests and hosts
- Configure podcast metadata
- Upload audio files
- Add episode transcripts
- Rich text editing for show notes
The framework includes a built-in newsletter signup form that integrates with ConvertKit.
For the newsletter signup form to appear, both of the following must be configured:
-
ConvertKit API credentials in
.env:CONVERTKIT_API_KEY=your_api_key CONVERTKIT_FORM_ID=your_form_id
-
Newsletter enabled in Sanity CMS:
- Open Sanity Studio (http://localhost:3333 or your deployed Studio)
- Go to the "Podcast" document
- Set
Newsletter Enabledto true - Set
Is Activeto true - Save and publish
This design allows you to:
- Temporarily disable the newsletter without removing API credentials
- Test the site without ConvertKit configured
- Control newsletter visibility per environment
Newsletter form not appearing?
- β
Check ConvertKit credentials are in
.env - β
Verify
newsletterEnabled: truein Sanity podcast document - β
Verify
isActive: truein Sanity podcast document - β Restart dev server after adding environment variables
If you have an existing podcast with episodes in an RSS feed (from Transistor, Spotify, Apple Podcasts, etc.), you can bulk import them into Sanity.
Run the import after you've set up Sanity CMS but before your first deployment.
npm run import:episodesThe CLI will:
- Prompt for your podcast's RSS feed URL
- Fetch all episodes from the feed
- Parse episode metadata (title, description, audio URL, publish date, etc.)
- Create episode documents in Sanity CMS
- Show a summary of imported episodes
ποΈ Importing episodes from RSS feed...
β Found 42 episodes in feed
β Creating episode documents in Sanity...
β Imported 42 episodes successfully
Episodes are now in your Sanity CMS. Visit your Studio to review and publish them.
To import new episodes without duplicating existing ones:
npm run import:episodesThe CLI intelligently skips episodes that already exist in Sanity (matched by episode number or GUID).
- Transistor
- Spotify for Podcasters
- Apple Podcasts
- Buzzsprout
- Libsyn
- Any RSS 2.0 or Atom podcast feed
Import fails?
- β Verify your RSS feed URL is correct and accessible
- β
Check Sanity credentials are in
.env - β Ensure you have write permissions (SANITY_API_TOKEN with Editor role)
- β Check console output for specific error messages
- @rejected-media/podcast-framework-core - Components, layouts, utilities
- @rejected-media/podcast-framework-sanity-schema - CMS schemas
- Astro 5 - Static site generator
- Sanity 3 - Headless CMS
- Header - Navigation with mobile menu
- Footer - Social links and newsletter
- NewsletterSignup - Email subscription
- EpisodeSearch - Client-side search
- TranscriptViewer - Transcript display
- FeaturedEpisodesCarousel - Episode carousel
- SkeletonLoader - Loading states
- BlockContent - Rich text renderer
- β SEO optimized (meta tags, Schema.org)
- β Google Analytics 4 ready
- β Responsive design
- β Accessibility (WCAG 2.1 AA)
- β Episode transcripts
- β Newsletter signup
- β Community contributions
- β Multi-cloud deployment (Cloudflare/Vercel/Netlify)
Create src/components/ComponentName.astro to override any framework component:
---
// src/components/Header.astro
---
<header class="custom-header">
<!-- Your custom header -->
</header>The framework automatically uses your version!
// sanity/sanity.config.ts
import { extendEpisodeSchema } from '@rejected-media/podcast-framework-sanity-schema';
const episode = extendEpisodeSchema([
{
name: 'sponsor',
type: 'reference',
to: [{ type: 'sponsor' }]
}
]);Edit podcast.config.js to enable/disable features:
features: {
transcripts: true,
newsletter: true,
search: true,
comments: false // Disable comments
}This template is pre-configured for Cloudflare Pages with the adapter already installed. You can also deploy to Netlify or Vercel with minor configuration changes.
All platforms require:
- Node.js 18+ for the build
- SSR adapter installed (handles API routes and server-side rendering)
- Environment variables configured in the platform dashboard
Why Cloudflare Pages?
- β Free tier includes unlimited bandwidth
- β Global CDN with 300+ locations
- β Built-in analytics
- β Zero-config SSL
- β Excellent performance
Adapter: Already installed (@astrojs/cloudflare)
Deployment Steps:
-
Push code to GitHub
git init git add . git commit -m "Initial commit" git remote add origin https://github.com/YOUR_USERNAME/your-podcast.git git push -u origin main
-
Create Cloudflare Pages project
- Go to Cloudflare Dashboard β Pages
- Click "Create a project"
- Select "Connect to Git"
- Authorize GitHub and select your repository
-
Configure build settings
- Framework preset: Astro
- Build command:
npm run build - Build output directory:
dist - Root directory: (leave empty)
-
Add environment variables (in Cloudflare Pages dashboard):
PUBLIC_SANITY_PROJECT_ID=your_project_id PUBLIC_SANITY_DATASET=production SANITY_PROJECT_ID=your_project_id SANITY_DATASET=production SANITY_API_TOKEN=your_write_token PUBLIC_SITE_URL=https://your-podcast.pages.dev # Optional: Newsletter CONVERTKIT_API_KEY=your_api_key CONVERTKIT_FORM_ID=your_form_id # Optional: Email notifications RESEND_API_KEY=your_resend_key NOTIFICATION_EMAIL=admin@yourpodcast.com # Optional: Analytics GA_MEASUREMENT_ID=G-XXXXXXXXXX -
Deploy!
- Click "Save and Deploy"
- Wait 2-3 minutes for build
- Your site will be live at
https://your-podcast.pages.dev
-
Set up custom domain (optional)
- Go to your Pages project β Custom domains
- Click "Set up a custom domain"
- Follow DNS configuration instructions
Troubleshooting:
- β Build fails β Check environment variables are set
- β API routes 404 β Verify adapter is
@astrojs/cloudflareinastro.config.mjs - β Missing content β Check Sanity project ID and token
Branch Deployments:
mainbranch β Production (your-podcast.pages.dev)- Other branches β Preview deployments (branch-name.your-podcast.pages.dev)
Adapter Required: @astrojs/vercel
Setup:
-
Install Vercel adapter
npm uninstall @astrojs/cloudflare npm install @astrojs/vercel
-
Update
astro.config.mjsimport vercel from '@astrojs/vercel/serverless'; export default defineConfig({ output: 'server', adapter: vercel(), // ... rest of config });
-
Deploy
- Push to GitHub
- Import project at vercel.com/new
- Vercel auto-detects Astro and configures build
- Add environment variables in Vercel dashboard
- Deploy!
Build settings:
- Framework: Astro
- Build command:
npm run build - Output directory:
dist
Adapter Required: @astrojs/netlify
Setup:
-
Install Netlify adapter
npm uninstall @astrojs/cloudflare npm install @astrojs/netlify
-
Update
astro.config.mjsimport netlify from '@astrojs/netlify'; export default defineConfig({ output: 'server', adapter: netlify(), // ... rest of config });
-
Create
netlify.toml(optional, for build config)[build] command = "npm run build" publish = "dist" [[plugins]] package = "@netlify/plugin-nextjs"
-
Deploy
- Push to GitHub
- Go to app.netlify.com
- Click "Add new site" β "Import from Git"
- Select repository and configure
- Add environment variables in Netlify dashboard
- Deploy!
All platforms need these variables:
| Variable | Value | Description |
|---|---|---|
PUBLIC_SANITY_PROJECT_ID |
Your project ID | From sanity.io/manage (client-side) |
PUBLIC_SANITY_DATASET |
production |
Usually "production" (client-side) |
SANITY_PROJECT_ID |
Your project ID | From sanity.io/manage (server-side) |
SANITY_DATASET |
production |
Usually "production" (server-side) |
SANITY_API_TOKEN |
Write token | For API routes (contribute, etc.) |
PUBLIC_SITE_URL |
Your domain | Full URL (https://...) |
Optional variables:
| Variable | Required For | Description |
|---|---|---|
CONVERTKIT_API_KEY |
Newsletter | From ConvertKit settings |
CONVERTKIT_FORM_ID |
Newsletter | Your form ID |
RESEND_API_KEY |
Email notifications | From resend.com |
NOTIFICATION_EMAIL |
Email notifications | Where to send admin emails |
GA_MEASUREMENT_ID |
Google Analytics | G-XXXXXXXXXX format |
STUDIO_URL |
Email links | URL to your Studio (optional) |
For a professional setup with staging and production environments:
-
Create two Sanity datasets:
staging- for testingproduction- for live site
-
Set up two deployments:
- Staging: Deploy from
stagingbranch β UsesSANITY_DATASET=staging - Production: Deploy from
mainbranch β UsesSANITY_DATASET=production
- Staging: Deploy from
-
Workflow:
# Develop on feature branch git checkout -b feature/new-design git commit -m "Update homepage design" # Merge to staging for testing git checkout staging git merge feature/new-design git push origin staging # β Deploys to staging.yourpodcast.com # After testing, promote to production git checkout main git merge staging git push origin main # β Deploys to yourpodcast.com
See DEPLOYMENT.md for a comprehensive production deployment guide.
Before your first deployment:
- β All environment variables configured in platform dashboard
- β
Sanity Studio deployed (
npm run sanity:deploy) - β DNS configured (if using custom domain)
- β SSL/TLS enabled (auto on all platforms)
- β Episodes imported or created in Sanity
- β Podcast metadata configured (name, description, logo)
- β Theme configured (colors, typography, layout)
- β Homepage config created and activated in Sanity
- β About page config created (optional)
- β Test newsletter signup (if enabled)
- β Test contribution form
- β Verify episode pages load correctly
- β Check mobile responsiveness
First deployment usually takes:
- β±οΈ Cloudflare Pages: 2-3 minutes
- β±οΈ Vercel: 1-2 minutes
- β±οΈ Netlify: 2-4 minutes
Subsequent deployments:
- β±οΈ All platforms: 1-2 minutes (cached dependencies)
- Setup Guide: See Quick Start above
- Deployment Guide: See Deployment above
- Customization: See Customization above
You may see 10 low-severity warnings when running npm audit. These are known, documented, and not a security concern. They originate from an unmaintained package deep in Sanity's dependency tree.
TL;DR: Low severity (2.9/10), extremely low exploitation probability (<0.1%), only affects server-side development tools, and doesn't impact your public website.
For full details, see: SECURITY.md
The framework includes a CLI tool for common tasks:
# Validate your project
npx @podcast-framework/cli validate
# List available components
npx @podcast-framework/cli list-components
# Override a component
npx @podcast-framework/cli override Header
# Check for framework updates
npx @podcast-framework/cli check-updates
# Update framework packages
npx @podcast-framework/cli updateFound a bug or want to contribute? Visit the main repository.
MIT License - see LICENSE
Happy podcasting! ποΈ