No description
|
|
||
|---|---|---|
| .opencode | ||
| .sisyphus/plans | ||
| backend | ||
| data | ||
| frontend | ||
| mcp-server | ||
| n8n | ||
| test_reports | ||
| traefik | ||
| .env.example | ||
| .gitignore | ||
| AGENTS.md | ||
| docker-compose.override.yml | ||
| docker-compose.yml | ||
| flake.lock | ||
| flake.nix | ||
| import_data.py | ||
| pytest.ini | ||
| README.md | ||
PCM - Podcast Content Manager
A lightweight web app for managing podcast episode research — collecting news links, assigning them to episodes, and archiving after broadcast.
Features
- Inbox → Planned → Archived workflow for news items
- Episode management with episode numbers and air dates
- Tagging for categorizing news topics
- One-click archive when an episode airs (archives all assigned news)
- Responsive UI with Tailwind CSS card layout
Deployment
Local Development
docker compose up -d --build
- Frontend: http://localhost:8080
- Backend API: http://localhost:8000/docs (Swagger UI)
Data is persisted in ./data/pcm.db (SQLite).
Traefik (Automated HTTPS)
Deploy behind an existing Traefik reverse proxy. Containers join Traefik's Docker network and are auto-discovered.
Prerequisites on the host:
- Traefik is running with its Docker provider enabled
- The network Traefik uses is named
pcm-network
If your Traefik uses a different network name, either rename it:
docker network create pcm-network
docker network connect pcm-network <your-traefik-container>
Or adjust your Traefik config to use pcm-network.
Deploy:
# Set your domain and cert resolver in .env
cp .env.example .env
# Edit .env with your HOST and CERT_RESOLVER
# Start (TRAEFIK_EXTERNAL=true connects to your existing network)
TRAEFIK_EXTERNAL=true HOST=pcm.example.com docker compose up -d --build
Traefik labels on the containers handle routing, TLS, and certificate provisioning via your existing DNS challenge resolver.
| Variable | Default | Description |
|---|---|---|
HOST |
(required) | Your domain, e.g. pcm.example.com |
TRAEFIK_EXTERNAL |
false |
Set true to join existing Traefik network |
CERT_RESOLVER |
hetzner |
Traefik certificate resolver name |
API_BASE_URL |
/api |
Path prefix for the API (change if Traefik routes differently) |
API Endpoints
Episodes
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/episodes |
List all episodes |
| POST | /api/episodes |
Create episode {number, air_date, status} |
| PUT | /api/episodes/:id |
Update episode |
| POST | /api/episodes/:id/archive |
Mark aired + archive all news |
| DELETE | /api/episodes/:id |
Delete (moves news back to inbox) |
News
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/news?status=inbox |
List news (optional filters) |
| POST | /api/news |
Create news item |
| PUT | /api/news/:id |
Update news fields |
| POST | /api/news/:id/assign/:ep_id |
Assign to episode (→ planned) |
| DELETE | /api/news/:id |
Hard delete |
Tags
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/tags |
List all unique tags |
Kubernetes Deployment Example
apiVersion: apps/v1
kind: Deployment
metadata:
name: pcm
namespace: pcm
spec:
replicas: 1
strategy:
type: Recreate # SQLite = RWO volume
selector:
matchLabels:
app: pcm
template:
metadata:
labels:
app: pcm
spec:
containers:
- name: backend
image: ghcr.io/kreativmonkey/pcm-backend:latest
ports:
- containerPort: 8000
volumeMounts:
- name: data
mountPath: /app/data
- name: frontend
image: ghcr.io/kreativmonkey/pcm-frontend:latest
ports:
- containerPort: 80
volumes:
- name: data
persistentVolumeClaim:
claimName: pcm-data
---
apiVersion: v1
kind: Service
metadata:
name: pcm
namespace: pcm
spec:
selector:
app: pcm
ports:
- name: api
port: 8000
targetPort: 8000
- name: web
port: 80
targetPort: 80
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pcm-data
namespace: pcm
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 1Gi
Note: Use
strategy: Recreatebecause SQLite needs exclusive RWO access. For production, consider switching to PostgreSQL.
Implemented
- OAuth2 login (OIDC)
- Multiuser support
Future Plans
- Drag & drop between columns
- RSS feed import
- Export to show notes (Markdown)
- Webhooks
- Browser Add-On
- Teams
Tech Stack
- Backend: Python 3.11, FastAPI, SQLite
- Frontend: Vanilla JS, Tailwind CSS
- Deployment: Docker Compose / Kubernetes