Development

This guide covers everything you need to know to contribute to django-cast development.

Planning Future Work

Planned work is tracked in the project backlog. Add or update backlog entries there instead of maintaining separate planned-work lists in the README or docs.

Development Environment Setup

Prerequisites

Before you begin, ensure you have the following installed:

  • Python 3.11 or higher

  • Node.js 18 or higher

  • uv for Python package management

  • just command runner

  • Git

Cloning the Repository

Start by forking and cloning the django-cast repository:

$ git clone git@github.com:your-username/django-cast.git
$ cd django-cast
$ git checkout develop

Note

Development happens on the develop branch. The main branch is reserved for stable releases.

Setting Up the Python Environment

Create a virtual environment and install all dependencies:

$ just install
# or directly: uv sync

This command will:

  • Create a virtual environment if one doesn’t exist

  • Install django-cast in editable mode

  • Install all development dependencies

Setting Up the JavaScript Environment

Navigate to the JavaScript directory and install dependencies:

$ cd javascript
$ npm install

Bootstrap5 Theme (Required for Example App)

The example app uses the Bootstrap5 theme, which lives in a sibling repo. Install it in editable mode:

$ uv pip install -e ../cast-bootstrap5

If cast-bootstrap5 is not available, the example app will fall back to the built-in bootstrap4 theme.

Database Setup

Create and migrate the development database:

$ cd example
$ uv run python manage.py migrate

Bootstrap demo content (recommended after a clean DB rebuild):

$ uv run python scripts/bootstrap_example_data.py --reset-db

Note

This repository contains two manage.py entry points:

  • manage.py (repository root) defaults to tests.settings and is mainly used for running the test suite.

  • example/manage.py uses example_site.settings.dev and is intended for interactive development.

Running the Development Server

Django-cast is typically developed as an installed package in a separate project. For quick testing, you can use the example project:

$ cd example
$ uv run python manage.py runserver

Or start Django + both Vite dev servers together:

$ just dev

Note

just dev will skip the Bootstrap5 or cast-vue Vite servers if the sibling repos (../cast-bootstrap5 or ../cast-vue) are missing, and the example app will fall back to the built-in bootstrap4 theme.

For agent-friendly local workflow, you can also use:

$ just dev-tmux          # create detached tmux session "cast-dev" (run again to attach)
$ just dev-status        # quick health/status output
$ just dev-logs django   # tail one service log
$ just dev-logs-dir      # print current log directory
$ just dev-open          # open http://localhost:8000

For JavaScript development with hot reloading:

$ cd javascript
$ npm run dev

For the Bootstrap5 theme assets (default theme), run its Vite dev server too:

$ cd ../cast-bootstrap5/javascript
$ npm run dev

If you have the optional cast-vue theme installed, run its Vite dev server as well (see the cast-vue repository for details).

If you do not want to run Vite, set these environment variables to use the prebuilt manifests instead:

$ export CAST_VITE_DEV_MODE=0
$ export CAST_BOOTSTRAP5_VITE_DEV_MODE=0
$ export CAST_VUE_VITE_DEV_MODE=0

Note

Podcast pages (Podlove player) rely on the Vite dev server during local development. Keep the relevant npm run dev process running while testing podcast list/detail pages to ensure the player loads.

Styleguide

Use two different URLs during frontend verification. They serve different purposes.

Note

These dev-only routes are gated by CAST_ENABLE_DEV_TOOLS (or deprecated CAST_ENABLE_STYLEGUIDE alias). If disabled, they return 404. The styleguide route is still available, but the long-term direction is the reference-site workflow (ensure_reference_site + real page checks).

Component preview route:

http://localhost:8000/cast/styleguide/

This renders seeded preview components for the active theme (cards, media blocks, comments, galleries, podcast snippets). It is the fastest way to inspect visual regressions in isolated sections.

Real list-page behavior route:

http://localhost:8000/styleguide-blog/

This is a real Wagtail blog index page. Use it for end-to-end checks of:

  • search query behavior (?search=python)

  • facet selection (?date_facets=2026-02&tag_facets=django)

  • filter + pagination/navigation interactions

Note

/styleguide-blog/ is created by the styleguide seeder. If it returns a 404, create/update reference content first:

$ just ensure-reference-site

Switch styleguide theme via query param:

http://localhost:8000/cast/styleguide/?theme=bootstrap4

If the requested theme does not provide styleguide templates, the view falls back to a built-in theme and shows a warning banner.

Theme comparison and screenshots

Compare themes side-by-side in the browser:

http://localhost:8000/cast/theme-compare/?path=/styleguide-blog/

Use Playwright helpers for screenshots and console-error checks:

$ just screenshot /styleguide-blog/ --theme bootstrap5
$ just screenshot-all /styleguide-blog/
$ just check-page /styleguide-blog/ --theme bootstrap5
$ just compare-page /styleguide-blog/

If this is your first Playwright run on a machine, install browser binaries:

$ uv run playwright install chromium

Asset freshness checks

Detect stale built assets compared to source files:

$ just verify-assets

In DEBUG mode, django-cast also emits system check warning cast.W001 when local Vite source files are newer than the built manifest.

Podlove Performance Data

To create local podcast data that exercises the Podlove player:

$ cd example
$ uv run python scripts/create_podlove_perf_data.py --episodes 5 --transcripts 200

This creates a podcast at /show/ with multiple episodes and transcript payloads to profile list and detail pages. Increase --transcripts to mimic heavier payloads. If the slug already exists, delete the data or pick a different --slug value.

Note

The Podlove subscribe button bundle is a vendored, minified asset (upstream last updated in 2019). If you apply a local patch for layout stability, add a short header comment with the upstream URL and patch date, and record the change in release notes.

Running Tests

Python Tests

Run the Python test suite:

$ just test
# or directly: uv run pytest

Run only the intentionally slower integration/dev-surface checks:

$ just test-slow
# or directly: uv run pytest -m slow

Run only the faster non-slow tests:

$ just test-fast
# or directly: uv run pytest -m "not slow"

For specific tests:

$ just test-one tests/models_test.py::TestPostModel::test_post_slug

Test Coverage

Generate a coverage report:

$ just coverage

This runs the tests with coverage and opens the HTML report in your browser.

Or manually:

$ uv run coverage run -m pytest
$ uv run coverage html
$ open htmlcov/index.html

Test Database Management

The test database is reused between test runs for performance. If you’ve added new migrations:

$ rm tests/test_database.sqlite3  # Remove old test database
$ uv run python manage.py migrate  # Recreate with new migrations (uses tests.settings)

If you see widespread 404s or IntegrityErrors in tests (especially around Wagtail page URLs), the reused test database or Wagtail’s site-root path cache may be stale. In that case, recreate the test database using the steps above to reset the site root path cache and avoid leftover pages or slug collisions.

JavaScript Tests

Run JavaScript tests with Vitest:

$ just js-test
$ just js-test-watch
$ just js-coverage
# or directly:
$ cd javascript
$ npx vitest run

Build shipped JavaScript assets:

$ just js-build-comments
# or directly:
$ cd javascript
$ npm run build:comments

Testing Multiple Django/Wagtail Versions

Use tox to test against multiple Django and Wagtail versions:

$ just tox
# or directly: uv run tox

To test a specific environment:

$ uv run tox -e py312-django42-wagtail70

Code Quality

Run all quality checks (linting, type checking, and tests) in one command:

$ just check

This runs just lint, just typecheck, and just test in sequence, stopping on first failure.

Linting and Formatting

Django-cast uses Ruff for code formatting and linting. The project is configured with:

  • Line length: 119 characters

  • Black-compatible formatting

  • Import sorting

Format your code:

$ just lint

Fix linting issues:

$ uv run ruff format .
$ uv run ruff check --fix .

Pre-commit Hooks

Set up pre-commit hooks to automatically check code quality:

$ pre-commit install

Run all hooks manually:

$ just pre-commit
# or directly: pre-commit run --all-files

The pre-commit configuration includes:

  • Ruff formatting and linting

  • djhtml template formatting

  • Trailing whitespace removal

  • End-of-file fixes

  • YAML validation

Type Checking

Run mypy for static type checking:

$ just typecheck
# or directly: uv run mypy

The project uses type hints throughout the codebase. When adding new code, please include appropriate type annotations.

Configuration for mypy is in pyproject.toml. Key settings include:

  • python_version = "3.14"

  • ignore_missing_imports = true

  • plugins = ["mypy_django_plugin.main"]

Building Documentation

The documentation uses Sphinx with the Furo theme.

Building Locally

Build the documentation:

$ just docs

Or manually:

$ make -C docs clean
$ make -C docs html

View the built documentation:

$ open docs/_build/html/index.html

Documentation Standards

  • Use reStructuredText format for documentation files

  • Include code examples where appropriate

  • Document all public APIs

  • Keep documentation up-to-date with code changes

Writing Documentation

When adding new features:

  1. Update relevant .rst files in the docs/ directory

  2. Add docstrings to new Python functions/classes

  3. Include usage examples

  4. Update the changelog if applicable

Package Building

Django-cast uses the uv_build backend (not hatchling). Configuration is in pyproject.toml:

  • Build backend: uv_build

  • Source layout: src/cast/

  • Module configuration: module-root = "src" and module-name = "cast"

To build the package locally:

$ uv build

This creates wheel and source distributions in the dist/ directory.

For the complete release process, see Release Process.

Development Workflow

Branch Strategy

  • main: Stable releases only

  • develop: Active development

  • Feature branches: Branch from develop for new features

  • Hotfix branches: Branch from main for critical fixes

Making Changes

  1. Create a feature branch from develop

  2. Make your changes

  3. Add tests for new functionality

  4. Run just check (linting, type checking, and tests in one command)

  5. Update documentation

  6. Create a pull request to develop

Pull Request Guidelines

  • Include a clear description of changes

  • Reference any related issues

  • Ensure all tests pass

  • Maintain or improve code coverage

  • Update documentation as needed

  • Follow the existing code style

Debugging Tips

Django Extensions

The example project enables django-extensions in example/example_site/settings/dev.py (e.g. shell_plus).

Optional Debug Toolbar

If you want to use Django Debug Toolbar, add it to your environment and enable it in example/example_site/settings/local.py (which is imported from dev.py if present).

Logging

Enable detailed logging during development:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
        },
    },
    'loggers': {
        'cast': {
            'handlers': ['console'],
            'level': 'DEBUG',
        },
    },
}

Common Issues

Import Errors

Since the project uses src layout (src/cast/), ensure:

  • The project is installed into your environment (just install / uv sync)

  • Imports use cast (not src.cast)

  • PYTHONPATH includes src directory when needed

Database Migration Conflicts

When working with migrations:

  1. Always create migrations on the latest develop branch

  2. If conflicts occur, delete and recreate migrations

  3. Squash migrations periodically to keep them manageable

Getting Help

  • Open an issue on GitHub

  • Check existing issues and pull requests

  • Review the Contributing guide

  • Ask questions in discussions

Additional Resources