# CastDeck

CastDeck is a podcast hosting platform for publishing, managing, and distributing audio shows. It provides episode hosting, RSS feed generation, analytics, team workflows, and storage integrations for production podcast networks and independent creators.

## Features

- Show and episode management
- Podcast-compliant RSS feed generation
- Audio upload and processing pipeline
- Public episode pages with embedded player
- Apple Podcasts, Spotify, and directory-ready metadata
- Download and listener analytics
- Team roles and permissions
- Scheduled publishing
- Custom domains
- S3-compatible object storage support
- PostgreSQL-backed application data
- Background jobs for media processing and feed refreshes

## Install

### Requirements

- Node.js 20+
- PostgreSQL 15+
- Redis 7+
- S3-compatible storage bucket
- FFmpeg

### Local Setup

```bash
git clone https://github.com/example/castdeck.git
cd castdeck
npm install
cp .env.example .env
```

Create the database:

```bash
createdb castdeck
npm run db:migrate
npm run db:seed
```

Start the development server:

```bash
npm run dev
```

The app will be available at:

```text
http://localhost:3000
```

### Docker

```bash
docker compose up --build
```

Run migrations inside the app container:

```bash
docker compose exec app npm run db:migrate
```

## Usage

### Create an Admin User

```bash
npm run users:create-admin -- --email admin@example.com --password "change-me"
```

Sign in at:

```text
http://localhost:3000/admin
```

### Create a Show

1. Open the admin dashboard.
2. Select **New Show**.
3. Add title, description, category, language, artwork, and author details.
4. Save the show to generate its RSS feed URL.

Example feed URL:

```text
https://podcasts.example.com/shows/product-talk/feed.xml
```

### Publish an Episode

1. Open a show from the dashboard.
2. Select **New Episode**.
3. Upload an audio file.
4. Add title, summary, transcript, season, episode number, and publish date.
5. Publish immediately or schedule for later.

### Run Background Workers

Media processing, analytics aggregation, and scheduled publishing require workers:

```bash
npm run worker
```

For production, run at least one web process and one worker process.

## Configuration

CastDeck is configured with environment variables.

| Variable | Required | Description |
| --- | --- | --- |
| `APP_URL` | Yes | Public URL of the application |
| `DATABASE_URL` | Yes | PostgreSQL connection string |
| `REDIS_URL` | Yes | Redis connection string |
| `SESSION_SECRET` | Yes | Secret used to sign sessions |
| `STORAGE_DRIVER` | Yes | Storage backend, usually `s3` |
| `S3_ENDPOINT` | Yes | S3-compatible endpoint |
| `S3_BUCKET` | Yes | Bucket used for audio and artwork |
| `S3_ACCESS_KEY_ID` | Yes | Storage access key |
| `S3_SECRET_ACCESS_KEY` | Yes | Storage secret key |
| `S3_REGION` | No | Storage region |
| `MAIL_FROM` | No | Default sender address |
| `SMTP_URL` | No | SMTP connection URL |
| `ANALYTICS_RETENTION_DAYS` | No | Number of days to retain detailed analytics |

Example `.env`:

```env
APP_URL=http://localhost:3000
DATABASE_URL=postgres://postgres:postgres@localhost:5432/castdeck
REDIS_URL=redis://localhost:6379
SESSION_SECRET=replace-with-a-long-random-value

STORAGE_DRIVER=s3
S3_ENDPOINT=http://localhost:9000
S3_BUCKET=castdeck-dev
S3_ACCESS_KEY_ID=minio
S3_SECRET_ACCESS_KEY=minio123
S3_REGION=us-east-1

MAIL_FROM=CastDeck <no-reply@example.com>
SMTP_URL=smtp://localhost:1025
ANALYTICS_RETENTION_DAYS=365
```

## Production Notes

- Serve the app behind HTTPS.
- Use a durable object storage provider for media files.
- Configure CDN caching for audio assets and artwork.
- Run database migrations before deploying new versions.
- Keep workers running continuously for scheduled publishing and media processing.
- Back up PostgreSQL and object storage regularly.

## License

MIT