Development

Development is performed locally using the same Django application and PostgreSQL database technology used in deployed environments.

The development environment is intentionally kept relatively simple. Production services are replaced with local alternatives where practical so that routine development does not require access to production infrastructure or credentials.

Local Development

The application requires Python, PostgreSQL, and Git for local development.

After cloning the repository, create and activate a Python virtual environment and install the project dependencies.

python -m venv venv
source venv/bin/activate
pip install -r requirements.txt

Create a local PostgreSQL database and configure the development environment to use it.

Apply the database migrations:

python manage.py migrate

Create a Wagtail administrator account if needed:

python manage.py createsuperuser

The development server can then be started with:

python manage.py runserver

The Wagtail administration interface is available at /admin/ in the local development environment.

Settings

Django settings are separated by environment.

Shared application configuration is maintained in the base settings, while development and production settings provide environment-specific behavior.

The development environment uses local alternatives for services that do not need to be exercised during routine development. For example, uploaded files can use filesystem storage rather than Amazon S3, and outgoing email can use Django’s console email backend rather than Amazon SES.

Production credentials are not required for normal local development.

Dependencies

Python dependencies are maintained in the project’s dependency configuration and committed to source control.

Dependencies are added deliberately rather than automatically introducing a package for functionality that can be implemented clearly within the application.

When dependencies are updated, application tests are run before the changes are deployed. Framework and library upgrades are treated as application changes and move through the same review and deployment process as other code changes.

Testing

Automated tests are used to verify application behavior and reduce the risk of regressions as the site changes.

Tests create their own predictable data and do not depend on copies of the production database. Where application behavior depends on an external service, that dependency can be mocked or isolated so tests do not make requests to production systems.

Tests are run locally during development and as part of the source-control workflow before changes are deployed.

The complete test suite can be run with:

python manage.py test

Tests are intended to verify application behavior rather than implementation details wherever practical. This allows internal code to change without requiring unrelated tests to be rewritten.

Front-End Development

The site’s front end uses Bootstrap with a relatively small amount of custom CSS and JavaScript.

Custom styles and scripts are maintained directly in the application’s static files. The project does not currently require Sass compilation, a JavaScript bundler, or a Node-based front-end build process.

Reusable presentation is primarily implemented through Django templates and Wagtail content blocks. Changes to shared components should generally be made in the component template or stylesheet rather than repeated on individual pages.

Front-end changes should be reviewed at multiple viewport sizes and with keyboard navigation. Changes affecting interactive components should also be checked for appropriate focus behavior and accessible state information.

Documentation

Technical documentation is maintained with Sphinx in the docs/ directory of the repository.

Documentation should be updated as part of the same change that alters the behavior it describes. This is particularly important for architectural decisions, configuration, deployment procedures, external services, and other information that may not be apparent from reading the application code.

To build the documentation locally:

cd docs
make html

Generated documentation can be rebuilt from a clean state with:

make clean
make html

The generated HTML is served with the application at /docs/.

Development Practices

Changes are developed in Git branches rather than directly on the main branch.

A typical change follows a small number of steps:

  1. Create a branch for the change.

  2. Implement the change locally.

  3. Add or update tests where appropriate.

  4. Update documentation when behavior or architecture has changed.

  5. Run the test suite.

  6. Push the branch to GitHub and create a pull request.

Temporary Heroku Review Apps can be created from pull requests when a change benefits from testing in a deployed environment. They are useful for review and integration testing but are not required for every change.

After a change has been reviewed and merged, the deployment workflow takes over. Staging, production promotion, and environment-specific deployment behavior are documented separately in Deployment.

Working Principles

Local development should be safe to perform without access to production data or production credentials.

Code, tests, and documentation are treated as parts of the same application. A change is not fully represented in source control if the behavior changes but the relevant tests or documentation are knowingly left behind.

Development tooling is added when it solves a recurring problem. The project does not require every tool that might be useful on a larger application, and keeping the local development environment understandable is itself a maintenance consideration.