Your YouTube channels, zero noise π―
Hey! Iβm GOTXE π, and YTCV came from something very simple: I would open YouTube with a clear mission... and end up somewhere else π
That is not necessarily bad. Discovering new things is great. But many times I wanted the opposite: open, check my subscriptions, catch up, and move on with my day π
So I built this app for myself, and now Iβm sharing it in case it helps you too.
YTCV is a self-hosted viewer to see only what matters to you: your subscriptions, in chronological order, with a clean, direct, no-nonsense experience β¨
And remember: the real enemy is not the algorithm, it is procrastination. You are in control πͺ
[!IMPORTANT] IMPORTANT Do not forget the YouTubers you like. They still need your direct support (subscriptions, likes, comments, merch, etc.) to keep creating quality content. Also use the official YouTube app for that and support your favorite creators.
- What does YTCV do?
- Screenshots
- Usage
- First access (recommended flow)
- Login from other devices (passkey or code)
- OAuth without headaches
- Troubleshooting
- Documentation
- Support
- Legal notice
- License
- Imports your subscriptions with Google OAuth + YouTube Data API v3.
- Shows videos in real chronological order (as it should be π«‘).
- Lets you filter watched/unwatched and organize by categories.
- After first Google login, you create your local DB user so you can log in from any device with that user, without using Google again.
- Runs in containers (backend + proxy), ideal for self-hosting.
The recommended way is Docker Compose.
Storage modes (choose one):
- Docker named volumes (no host folder management)
- No need to create host folders.
- Compose uses Docker-managed volumes (
ytcv_data,ytcv_logs).
- Host persistent folders (recommended on Synology)
- Create host folders, for example:
/volume1/docker/ytclearview/
ββ data/
ββ logs/
- Then map them as bind mounts in compose:
services:
backend:
volumes:
- /volume1/docker/ytclearview/data:/data
- /volume1/docker/ytclearview/logs:/logsRelease and images:
- Release:
v0.13.0-> https://github.com/GOTXE/yt-clear-view/releases/tag/v0.13.0 - Backend image: https://github.com/GOTXE/yt-clear-view/pkgs/container/ytcv-backend
- Proxy image: https://github.com/GOTXE/yt-clear-view/pkgs/container/ytcv-proxy
- Pull example:
docker pull ghcr.io/gotxe/ytcv-backend:v0.13.0
docker pull ghcr.io/gotxe/ytcv-proxy:v0.13.0Before launching YTCV, prepare this in Google Cloud. Here are direct searches:
- Create project in Google Cloud Console:
- Enable YouTube Data API v3:
- Create OAuth 2.0 credentials for web app:
- Configure OAuth consent screen:
- Configure device login (Device Authorization / Device Flow):
No local build, using GHCR images.
Templates:
You have two options:
- If you cloned the full repo:
cp backend/.env.prod.example backend/.env- If you did NOT clone the repo (for example, you use your own
docker-compose.yml):
- Create a
.envfile in the same folder as your compose file. - Fill it with the required variables.
FLASK_SECRET_KEY=put_a_long_unique_secret_here
AUTH_MODE=google
YT_API_KEY=your_youtube_api_key
GOOGLE_CLIENT_ID=your_client_id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your_client_secret
GOOGLE_REDIRECT_URI=http://localhost:5550/api/auth/google/callback
FRONTEND_URL=http://localhost:8080
CORS_ORIGINS=http://localhost:8080,http://localhost:5550Options for GOOGLE_REDIRECT_URI FRONTEND_URL CORS_ORIGINS (choose one):
- Localhost (no HTTPS)
GOOGLE_REDIRECT_URI=http://localhost:5550/api/auth/google/callback- Use this when everything runs on the same machine (browser + containers).
- It is the simplest local option. Google OAuth logins work fine with
localhostwithout HTTPS. You will need to do Google login on that device first. After that first login, you can log in from any device with your local user without going through Google OAuth again.
- External domain (with HTTPS)
GOOGLE_REDIRECT_URI=https://your-domain/api/auth/google/callback- Use this when you access from other devices or outside your local network.
- Google OAuth for web apps works reliably with a public hostname and HTTPS.
- In this scenario, also adjust these:
FRONTEND_URL=https://your-domainCORS_ORIGINS=https://your-domain
- If frontend and API live on different domains, add both origins in
CORS_ORIGINS:CORS_ORIGINS=https://your-frontend,https://your-api
Minimum required values before starting Docker Compose:
FLASK_SECRET_KEYAUTH_TOKEN_ENCRYPTION_KEYYT_API_KEYGOOGLE_CLIENT_IDGOOGLE_CLIENT_SECRETGOOGLE_REDIRECT_URIFRONTEND_URLCORS_ORIGINS
Generate secrets with Python:
python3 -c "import secrets; print(secrets.token_urlsafe(64))"
python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"The stack runs:
backend: Flask APIproxy: frontend + reverse proxy onhttp://localhost:8080
Example if you use the repo (infra/compose/compose.yaml):
YTCV_TAG=v0.13.0 docker compose -f infra/compose/compose.yaml up -dYou can customize startup with variables:
YTCV_TAG: image version (v0.13.0,latest, etc.).YTCV_HTTP_PORT: public port (default8080).
Examples:
# Port 8090
YTCV_TAG=v0.13.0 YTCV_HTTP_PORT=8090 docker compose -f infra/compose/compose.yaml up -dBasic equivalent compose example (if you want your own):
services:
backend:
image: ghcr.io/gotxe/ytcv-backend:${YTCV_TAG:-latest}
env_file:
- ./.env
environment:
AUTH_MODE: google
DATABASE_URI: sqlite:////data/youtube_clear_view.db
volumes:
- ytcv_data:/data
- ytcv_logs:/logs
proxy:
image: ghcr.io/gotxe/ytcv-proxy:${YTCV_TAG:-latest}
depends_on:
- backend
ports:
- "${YTCV_HTTP_PORT:-8080}:8080"
volumes:
ytcv_data:
ytcv_logs:Open:
http://localhost:8080https://your-domain(if using external domain)
- Open the main web app:
http://localhost:8080(local)https://your-domain(external domain)
-
Complete the first login with Google (OAuth).
-
Complete the initial wizard:
- create/configure your local app user,
- finish initial setup so you can sign in from other devices without repeating Google OAuth every time.
IMPORTANT: On first boot (fresh database), admin/user bootstrap can take noticeably longer than a normal login. Wait until the wizard fully completes before retrying or refreshing.
- Access admin panel when needed:
http://localhost:8080/gestor/https://your-domain/gestor/
After first access and initial setup, you can sign in from other devices using:
- Passkey (WebAuthn)
- Best for phones, laptops, and compatible browsers.
- Flow: on the new device choose passkey login and complete biometric/PIN verification.
- Pairing code
- Best for TV or devices with uncomfortable text input.
- Flow: new device shows a code, you approve it from an already authenticated device, and the new device signs in.
Note:
- First account bootstrap still starts with Google OAuth.
- After that, these methods avoid repeating OAuth on every device.
Local build from repo for development and PRs.
cp backend/.env.dev.example backend/.env
# Edit backend/.env
./scripts/dev_docker.sh up --mode dev --buildEquivalent command:
docker compose -f infra/compose/compose.yaml -f infra/compose/compose.dev.yaml up -d --build# Change public port
YTCV_HTTP_PORT=8081 YTCV_TAG=v0.13.0 docker compose -f infra/compose/compose.yaml up -d
# Update standard install
YTCV_TAG=v0.13.0 docker compose -f infra/compose/compose.yaml pull
YTCV_TAG=v0.13.0 docker compose -f infra/compose/compose.yaml up -d
# Rebuild proxy only (frontend)
./scripts/dev_docker.sh up --mode dev --build proxy
# Stop dev stack
./scripts/dev_docker.sh down --mode dev[!TIP] SUPER IMPORTANT For frontend devs: watch browser cache. If you change frontend and do not bump
CACHE_VERSIONinfrontend/sw.js, your browser may keep serving the old frontend from cache and make you think your changes did not work. Always rebuildproxyand bumpCACHE_VERSIONafter frontend changes. The web app has a service worker and JS update notice. Click to load the new version. Otherwise, the browser may serve an old version and drive you crazy π
You have two paths:
localhostcallback (everything on same machine)
http://localhost:5550/api/auth/google/callback
- External domain callback (multi-device Google login)
https://your-domain/api/auth/google/callback
Important:
- Avoid LAN IP callback over HTTP for Google OAuth.
- If it is not
localhost, use HTTPS.
- OAuth callback error:
GOOGLE_REDIRECT_URImust match exactly in Google Cloud Console andbackend/.env.
- Port already in use:
- change
YTCV_HTTP_PORT.
- change
- Backend is βhealthyβ but you cannot log in:
- check
AUTH_MODE=google, OAuth credentials, and consistency betweenFRONTEND_URLandCORS_ORIGINS. Also make sure you completed admin user setup and local DB user login (created after first Google login).
- check
- Locked out after failed logins (
423error):- after 5 failed password attempts an account is locked for 15 minutes. Wait it out, or restart the backend to lift the lock sooner.
- Forgot the admin/gestor password:
- set
ADMIN_RESET_PASSWORD=trueinbackend/.env, restart the backend, and check the backend logs β a new temporary password is generated for every admin account and printed there (you must change it on next login). Remove the variable and restart again once you are back in. - if you need to demote/disable all existing admins instead and go through the bootstrap wizard again, use
ADMIN_FORCE_RESET=true(destructive: it disables all current admin accounts).
- set
- Forgot a normal user's password:
- an admin can set a temporary password for that user from the admin panel (
Gestorβ users β reset password). If no admin account is reachable, use the admin password reset above first.
- an admin can set a temporary password for that user from the admin panel (
π§ W.I.P.: still under construction, but you can already take a look π If you find anything weird or have questions, open an issue π
Bug? π Improvement idea? π‘
- Open a GitHub issue.
- Include version (
v0.13.0or tag), environment, and reproduction steps.
YTCV is an independent project and is not affiliated with YouTube/Google. It uses the official YouTube Data API v3 and follows its terms of use.
Your use of YTCV is your responsibility. Make sure you comply with Google and YouTube policies when using this tool.
And of course, YTCV and its author/developer are not responsible for any damage, data loss, or productivity addiction that may result from using this application. Use it in moderation and enjoy your distraction-free experience.
MIT. See LICENSE.





