No description
Find a file
2026-03-28 13:12:48 +01:00
.opencode Complete webhook feature: import tab, bookmarklet page, tests 2026-03-26 17:56:34 +01:00
.sisyphus/plans Complete webhook feature: import tab, bookmarklet page, tests 2026-03-26 17:56:34 +01:00
backend Fix: addLink() and API token datetime comparison 2026-03-26 19:29:37 +00:00
data feat: Complete PCM v1.0 2026-03-24 10:00:28 +00:00
frontend Fix: Load API tokens when opening settings 2026-03-26 21:19:32 +00:00
mcp-server adding security fixes 2026-03-25 09:27:36 +01:00
n8n Add n8n Telegram Bot Integration 2026-03-24 23:17:18 +00:00
test_reports Complete webhook feature: import tab, bookmarklet page, tests 2026-03-26 17:56:34 +01:00
traefik Add Traefik with self-signed cert for local HTTPS 2026-03-25 19:51:36 +00:00
.env.example adding authentication via OAuth provider 2026-03-25 08:41:45 +01:00
.gitignore Add .gitignore (removed .env from history) 2026-03-25 20:05:05 +00:00
AGENTS.md Complete webhook feature: import tab, bookmarklet page, tests 2026-03-26 17:56:34 +01:00
docker-compose.override.yml Fix: addLink() and API token datetime comparison 2026-03-26 19:29:37 +00:00
docker-compose.yml fix network setting for traefik 2026-03-25 21:32:18 +01:00
flake.lock Complete webhook feature: import tab, bookmarklet page, tests 2026-03-26 17:56:34 +01:00
flake.nix Complete webhook feature: import tab, bookmarklet page, tests 2026-03-26 17:56:34 +01:00
import_data.py Initial commit of PCM Podcast Manager 2026-03-24 09:42:37 +00:00
pytest.ini Fix test infrastructure 2026-03-26 18:07:35 +01:00
README.md Add API token scopes, expiration and comprehensive tests 2026-03-26 15:21:51 +01:00

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

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:

  1. Traefik is running with its Docker provider enabled
  2. 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: Recreate because 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