Experimental repo to rewrite Y-video using Django and HTMX
- uv package manager
- Clone the repository:
git clone <repository-url>
cd yvideo-py- Install dependencies including development tools:
uv sync --dev
npm ci # eslint and dependencies
uv run python -m playwright install chromium- Set up pre-commit hooks:
uv run pre-commit install-
Create secret_settings.py from secret_settings_template.py. Populate secret_settings.py with the correct values
-
Run database migrations:
uv run manage.py migrate- Seed deterministic development data and copy checked-in sample media files:
uv run manage.py seed_demo_dataThe deterministic demo dataset includes a local admin with netid devadmin and password devadmin.
The seed command copies the checked-in sample mp4 files from demo_media/ into MEDIA_ROOT.
If you want to wipe local state and rebuild from the current models, use:
bash scripts/dangerously_reset_local_state.sh --bootstrapThat removes the local SQLite database, generated media under media/, and any local
derived files in media/. It does not touch demo_media/, committed migrations,
or yvideo/secret_settings.py.
If you want a one-click local app login for that admin, enable DEV_QUICK_LOGIN_ENABLED = True
in yvideo/secret_settings.py and visit /login/dev/quick/ on localhost. The route
returns 404 unless both DEBUG and DEV_QUICK_LOGIN_ENABLED are true, and it is only
usable from localhost or 127.0.0.1.
See DEPLOY.md for production deployment with Podman Quadlets and Apache.
Start the Django development server:
uv run manage.py runserverThe application will be available at http://localhost:8000
If you want to use the legacy migration workflow, the Django app reads from a local SQLite snapshot instead of connecting directly to the legacy PostgreSQL database.
- Copy
scripts/dump_legacy_to_sqlite_settings_template.pytoscripts/dump_legacy_to_sqlite_settings.py - Fill in the legacy PostgreSQL credentials in
scripts/dump_legacy_to_sqlite_settings.py - Test the script:
uv run scripts/dump_legacy_to_sqlite.py- Enable legacy migration in
yvideo/secret_settings.py:
LEGACY_MIGRATION_ENABLED = TrueBy default, the snapshot is written to
var/legacy_migration/legacy_dump.sqlite3. Every preflight run dumps a fresh
snapshot itself before reading it. See
LEGACY_MIGRATION.md for details.
- Pre-commit hooks: Automatically run linting and formatting on commit
- Ruff: Fast Python linter and formatter
- ESLint: Javascript/CSS/JSON linter
To manually run pre-commit on all files (this is the command used in Github Actions):
uv run pre-commit run --all-filesFor local database-backed Django tests, run:
uv run manage.py testThat uses the normal project settings and migration graph. No collectstatic is required:
with DEBUG = True in secret_settings.py (the development and CI default), {% static %}
resolves against core/static/ directly. collectstatic and the hashed-filename
ManifestStaticFilesStorage are production-only, where the deploy entrypoint runs them for you
— see DEPLOY.md.
For the pure-arithmetic Javascript unit tests, run:
node --test tests/js/*.test.jsThese use Node's built-in test runner and need no npm install. They cover
core/static/js/video-geometry.js, which decides where every blur annotation is drawn, and
run as their own CI job.
For browser-backed end-to-end tests against the deterministic demo dataset, run:
uv run pytest tests/e2e --browser chromiumThe pytest Playwright e2e suite runs headless Chromium, enables the local dev quick-login route for the test server, seeds demo data before each test, and runs in CI as a separate job instead of inside pre-commit.
A few behaviours cannot be covered by either suite, because they depend on a platform the test browsers do not have — iOS media handling, a screen reader, real display hardware. See MANUAL_TESTING.md for what those are, how to check them by hand, and why each one resists automation. Check it before releasing anything that touches video playback or blur annotations.
To upgrade dependency versions, use the following commands:
uv sync --upgrade
uv sync --upgrade --dev
npm updateCheck to make sure that the version numbers stored in pyproject.toml and package.json are exact, i.e. == instead of >=/^/etc.