# Subfeed Self-hosted, multi-user web app for browsing **your own YouTube subscriptions** the way you actually want: precise filtering and sorting (by language, topic, length, age, watch state…), a fast local-first feed, and one-click playback that opens the real youtube.com — so your browser's ad blocking and SponsorBlock keep working exactly as before. Each user signs in with their own Google account (invite-only) and sees only their own subscriptions. All the expensive data (channels, videos, metadata) is fetched from YouTube once and stored locally, so filtering/searching/sorting are instant and don't burn API quota. > Status: early development. Milestone **M1** (foundation) is in place: docker-compose stack, > FastAPI backend, Google OAuth login with an email invite-list, and encrypted token storage. ## Requirements - Docker + Docker Compose - A Google Cloud project with an OAuth client (see below) ## Quick start 1. Copy the env template and generate secrets: ```sh cp .env.example .env python -c "import secrets;print('SECRET_KEY=',secrets.token_urlsafe(48))" python -c "import base64,os;print('TOKEN_ENCRYPTION_KEY=',base64.urlsafe_b64encode(os.urandom(32)).decode())" ``` Paste the generated values into `.env`. 2. Create a Google OAuth client (Google Cloud Console → APIs & Services): - Enable the **YouTube Data API v3**. - OAuth consent screen: **External**, publishing status **Testing**, and add every invited Google account as a **Test user** (up to 100 — no app verification needed at this scale). - Create credentials → **OAuth client ID** → type **Web application**. - Authorized redirect URI: `http://localhost:8080/auth/callback` (must match `OAUTH_REDIRECT_URL` in `.env`). - Put the client ID/secret into `.env`, and list invited emails in `ALLOWED_EMAILS`. 3. Start it: ```sh docker compose up --build ``` Open http://localhost:8080 and sign in. Database migrations run automatically on startup. ## Backup & moving to another machine All data lives in the `pgdata` Postgres volume — moving to another host (e.g. a Proxmox Linux server) does **not** require re-fetching from YouTube. Copy your `.env` (keep the same `TOKEN_ENCRYPTION_KEY` and Google client so stored tokens stay valid), then: ```sh ./scripts/backup.sh # -> backups/subfeed-.dump (Windows: scripts\backup.ps1) ./scripts/restore.sh backups/ # on the new host after `docker compose up` ``` ## Tech FastAPI + PostgreSQL backend, React + Vite frontend (added in a later milestone), packaged with Docker Compose. ## Note This project is developed with AI assistance.