# CastForge

CastForge is a podcast hosting platform for publishing, distributing, and analyzing audio shows. It provides episode management, RSS feed generation, storage integration, listener analytics, team roles, and distribution tools for major podcast directories.

The project is designed for independent creators, podcast networks, and teams that need reliable hosting with full control over metadata, publishing workflows, and configuration.

## Features

- Show and episode management
- Draft, scheduled, and published episode states
- Automatic podcast RSS feed generation
- Audio file upload and processing
- Episode artwork and chapter metadata support
- Public podcast landing pages
- Listener analytics by episode, platform, region, and referrer
- Team accounts with role-based permissions
- Custom domains for podcast pages and feeds
- Webhook support for publishing events
- Configurable storage backends
- Directory-ready metadata for Apple Podcasts, Spotify, YouTube Music, and other platforms

## Install

### Requirements

- Node.js 20 or newer
- PostgreSQL 15 or newer
- Redis 7 or newer
- pnpm 9 or newer
- S3-compatible object storage for production audio hosting

### Setup

Clone the repository:

```bash
git clone https://github.com/example/castforge.git
cd castforge
```

Install dependencies:

```bash
pnpm install
```

Copy the environment file:

```bash
cp .env.example .env
```

Run database migrations:

```bash
pnpm db:migrate
```

Start the development server:

```bash
pnpm dev
```

The application will be available at:

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

## Usage

Create an admin user:

```bash
pnpm users:create-admin
```

Sign in to the dashboard and create your first podcast. From there you can:

1. Add show details, artwork, categories, and owner metadata.
2. Upload audio files for new episodes.
3. Save episodes as drafts or schedule them for release.
4. Publish episodes to update the podcast RSS feed.
5. Submit the generated RSS feed URL to podcast directories.

A podcast feed URL follows this format:

```text
https://your-domain.com/feed/{show-slug}.xml
```

Episode media files are served from the configured storage backend. In production, use object storage with a CDN in front of it for reliable playback and download performance.

## Configuration

CastForge is configured through environment variables.

### Application

```env
APP_URL=http://localhost:3000
APP_NAME=CastForge
NODE_ENV=development
PORT=3000
```

### Database

```env
DATABASE_URL=postgresql://castforge:castforge@localhost:5432/castforge
```

### Redis

```env
REDIS_URL=redis://localhost:6379
```

### Storage

For local development:

```env
STORAGE_DRIVER=local
LOCAL_STORAGE_PATH=./storage
```

For S3-compatible storage:

```env
STORAGE_DRIVER=s3
S3_BUCKET=castforge-media
S3_REGION=us-east-1
S3_ENDPOINT=
S3_ACCESS_KEY_ID=your-access-key
S3_SECRET_ACCESS_KEY=your-secret-key
S3_PUBLIC_BASE_URL=https://media.example.com
```

### Email

```env
MAIL_DRIVER=smtp
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=postmaster@example.com
SMTP_PASSWORD=your-password
SMTP_FROM="CastForge <noreply@example.com>"
```

### Authentication

```env
SESSION_SECRET=change-this-in-production
INVITE_ONLY=false
```

### Analytics

```env
ANALYTICS_ENABLED=true
ANALYTICS_RETENTION_DAYS=730
TRUST_PROXY=false
```

### Webhooks

```env
WEBHOOKS_ENABLED=true
WEBHOOK_SIGNING_SECRET=change-this-secret
```

## Common Commands

Run the development server:

```bash
pnpm dev
```

Build for production:

```bash
pnpm build
```

Start the production server:

```bash
pnpm start
```

Run tests:

```bash
pnpm test
```

Run database migrations:

```bash
pnpm db:migrate
```

Seed development data:

```bash
pnpm db:seed
```

## Production Notes

- Set `NODE_ENV=production`.
- Use a strong `SESSION_SECRET`.
- Serve uploaded media from S3-compatible storage or another durable object store.
- Put a CDN in front of audio files for better playback performance.
- Configure backups for PostgreSQL and object storage.
- Enable `TRUST_PROXY=true` when running behind a trusted reverse proxy.
- Use HTTPS for the application, feeds, media URLs, and custom domains.