This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is the Python Ireland (https://python.ie) website, built with Django 6.0 and Wagtail CMS 7.3. It manages content for the Python Ireland community including meetups and sponsors. The PyCon Ireland 2026 website is in a separate repository.
This project requires Python 3.13.11 (or any Python 3.13.x). All code must be compatible with Python 3.13. When developing locally without Docker, ensure you are using Python 3.13.x. Tool versions (Python, uv, Task) are pinned in mise.toml for mise users.
The project follows a modular Django app structure within the pythonie/ directory:
- core: Base Wagtail pages (HomePage, SimplePage) with StreamField content blocks. Implements PageSegment snippets and mixins (MeetupMixin, SponsorMixin) for common functionality.
- meetups: Manages Meetup.com integration for Python Ireland meetups. Includes a management command
updatemeetupsto sync with Meetup API. - sponsors: Sponsor management with SponsorshipLevel relationships.
Multiple settings files in pythonie/pythonie/settings/:
base.py: Shared settings, usesdj_database_urlfor database configurationdev.py: SQLite database, local Redis, DEBUG=Truetests.py: Test-specific settings with SQLite and mock Redisproduction.py: Heroku production settingspgdev.py: PostgreSQL development settings
Always specify settings module: --settings=pythonie.settings.dev (or tests, production, etc.)
- Development (default): SQLite at
pythonie/db.sqlite3 - Docker/Tests: PostgreSQL 17 in docker-compose
- Production: PostgreSQL 17 on Heroku via
DATABASE_URLenvironment variable
Important: When using Heroku CLI tools locally (e.g., task database:reset), ensure you have PostgreSQL 17 installed locally. This simplifies database reset operations and ensures compatibility with production.
- Django 6.0
- Wagtail 7.3 (CMS framework)
- Redis (caching, configured via
REDISCLOUD_URL) - WhiteNoise (static file serving)
- boto3/django-storages (S3 integration)
- Delorean/python-dateutil (date handling)
# Setup (creates and populates a .venv automatically)
uv sync --all-groups
# Database
uv run python pythonie/manage.py migrate --settings=pythonie.settings.dev
uv run python pythonie/manage.py createsuperuser --settings=pythonie.settings.dev
# Run server
uv run python pythonie/manage.py runserver --settings=pythonie.settings.dev
# Access admin at http://127.0.0.1:8000/admin/Uses Task for most operations. Requires docker-compose with services: web, postgres, redis.
# Build docker image
task docker:build
# or: make docker-build
# Run development server
task run
# or: docker compose run --rm --service-ports web python pythonie/manage.py runserver 0.0.0.0:8000
# Shell access
task shell
# or: docker compose run --rm web /bin/bash
# Django shell
task django:shell-plus
# Database migrations
task django:make-migrations
task django:migrate# Run all tests (local)
uv run python pythonie/manage.py test pythonie --settings=pythonie.settings.tests --verbosity=2
# Run all tests (docker)
make docker-tests
# or: task tests
# Run single test
uv run python pythonie/manage.py test pythonie.meetups.test_meetups --settings=pythonie.settings.tests# Format code with ruff
task code:format
# or: toast code:format
# or: uv run ruff format pythonie
# Lint code and fix issues
task code:lint
# or: toast code:lint
# or: uv run ruff check --fix pythonie
# Check code formatting and linting without changes
task code:check
# or: toast code:checkprek (a Rust drop-in replacement for pre-commit) runs the hooks defined in .pre-commit-config.yaml. It is not a project dependency: like uv, it must already be installed on the machine. It is pinned in mise.toml (mise install); without mise, use brew install prek or uv tool install prek. CI installs it with j178/prek-action.
# Install the git hook (once per clone)
prek install
# Run every hook on the whole repository (also run by the CI prek job)
prek run --all-files
# Emergency bypass: skip one hook, or all of them
SKIP=django-missing-migrations git commit -m "..."
git commit --no-verify -m "..."Hooks: pre-commit-hooks (whitespace, EOF, YAML/TOML/JSON, merge conflicts, large files, debug statements, private keys), uv-lock, django-upgrade (--target-version 6.0), and local hooks for ruff check/format, manage.py check and missing migrations. The ruff and Django hooks are local hooks running uv run --frozen, so ruff is pinned in one place only (pyproject.toml); there is no ruff-pre-commit rev to keep aligned. The Django hooks unset DATABASE_URL so they never reach a remote database. Vendored assets under pythonie/core/static/{css,fonts,js} are excluded. Renovate updates the hook revisions (pre-commit manager, enabled in renovate.json).
Uses uv for fast Python package management. Dependencies are declared in pyproject.toml ([project.dependencies] + [dependency-groups]) and locked in uv.lock (committed). Heroku's Python buildpack detects uv.lock and installs natively via uv sync against the slug's system Python — never add a requirements.txt at the repo root, the buildpack aborts the build if it finds more than one package-manager file (requirements.txt, poetry.lock, uv.lock) at once. .python-version (not runtime.txt, which is deprecated) pins the Python version for the buildpack.
# Recompute the lock file
task dependencies:compute
# or: toast deps:compute
# Check outdated packages
task dependencies:outdated
# Upgrade all dependencies
task dependencies:upgrade
# Upgrade only Wagtail
task dependencies:upgrade:wagtail
# Upgrade specific package
task dependencies:upgrade:package PACKAGE=django
# Check for security vulnerabilities
task dependencies:security
# Show dependencies tree
task dependencies:tree# Pull production database to local
task database:pull
# Push local database to production
task database:push
# Reset local with fresh production copy
task database:reset
# View Heroku backups
task heroku:database:backups
# Create new backup
task heroku:database:run-backup# View logs in real-time
task heroku:logs
# Restart the application
task heroku:restart
# Django shell on Heroku
task heroku:shell
# Bash shell on Heroku
task heroku:bash
# Run migrations on Heroku
task heroku:migrate
# Show environment variables
task heroku:config
# Show dyno status
task heroku:ps
# Show deployment history
task heroku:releases
# Rollback to previous release
task heroku:rollback
# Maintenance mode
task heroku:maintenance:on
task heroku:maintenance:offAll page types inherit from wagtail.models.Page. The page tree structure:
- HomePage (root, can have child HomePage or SimplePage)
- SimplePage
Pages use StreamFields for flexible content blocks (heading, paragraph, video, image, slide, html).
Django commands MUST include --settings=pythonie.settings.<module>. The default in manage.py is pythonie.settings which won't work without proper environment setup.
Development expects Redis at 127.0.0.1:6379 or via REDISCLOUD_URL environment variable. Configure via pythonie.settings.configure.configure_redis().
Key variables (see development.env / production.env):
DJANGO_SECRET_KEY: Required for productionDJANGO_SETTINGS_MODULE: Settings module pathDATABASE_URL: PostgreSQL connection (Heroku format)REDISCLOUD_URL: Redis connectionMEETUP_KEY: Meetup.com API keyPGDATABASE,PGUSER,PGPASSWORD,PGHOST: PostgreSQL credentials for DockerHEROKU_APP: Heroku application name (set in Taskfile.yaml)
Static files collected via WhiteNoise with CompressedManifestStaticFilesStorage. SCSS compiled via django-compressor and django-libsass.
Tests use pythonie.settings.tests which configures SQLite and mock Redis. Run with --verbosity=2 or --verbosity=3 for detailed output.
The project is hosted on Heroku using the heroku-24 stack with PostgreSQL 17.
After upgrading Wagtail to a new version, you must:
- Rebuild the Docker image:
task docker:build - Run migrations:
task django:migrate - Clear and recollect static files:
docker compose run --rm web python pythonie/manage.py collectstatic --clear --noinput - Clear your browser cache (Ctrl+Shift+R or Cmd+Shift+R) - this is critical as Wagtail admin JavaScript files are cached and stale cache can cause the admin sidebar menu to disappear with errors like
wagtailConfig is undefined.
Django 5.1 removed DEFAULT_FILE_STORAGE and STATICFILES_STORAGE settings. The project now uses the STORAGES API:
- base.py: Defines default storage (FileSystemStorage) and staticfiles (WhiteNoise)
- production.py: Overrides default storage to use S3 (
storages.backends.s3boto3.S3Boto3Storage)
If you see 404 errors for images after upgrading Django, ensure STORAGES is properly configured instead of the deprecated settings.
All documentation and code comments must be written in English to ensure all contributors can collaborate effectively.
When creating git commits, do not include any mention of Claude, Claude Code, or AI assistance in commit messages. Commit messages should focus solely on describing the changes made, without attribution to the tool used to make them.