Getting started¶
This page takes you from a fresh clone to a running development server with sample data and a working login. Two paths are covered:
- A Dev Container (VS Code or GitHub Codespaces) that runs the setup script for you.
- A local setup that runs
scripts/dev-setup.shdirectly on your machine.
Both paths end the same way: a Django dev server on port 8000, a Mailpit inbox on port 8025, and three test users you can log in as.
Prerequisites¶
| Tool | Why it is needed | Notes |
|---|---|---|
| Git | Clone the repository. | Any recent version. |
| Python 3.14 | Runtime for Django and the management commands. | Installed and managed by uv; see below. |
| uv | Creates the virtualenv, installs dependencies, runs tools | The setup script installs it if it is missing. |
| Docker | Production-like local stack (Postgres + Nginx) only. | Optional. Not needed for the standard dev flow. |
You do not need to install Python or uv by hand
scripts/dev-setup.sh installs uv if it is not already on your PATH, then uses it to create the
.venv and install everything else (including the Tailwind CSS and Mailpit binaries). On a
supported machine, the only hard prerequisite is Git.
Docker is only required for the production-like full stack described in Docker full stack. The day-to-day workflow on this page uses SQLite and runs everything on the host.
Path 1: Dev Container (VS Code or Codespaces)¶
The repository ships a Dev Container definition in
.devcontainer/devcontainer.json.
It is based on the mcr.microsoft.com/devcontainers/python:3.14-bookworm image and runs the setup
script automatically once the container is created:
Because RUN_SERVER defaults to true, the container finishes by starting the dev server. To use
it:
- Install the Dev Containers extension.
- Open the cloned repository folder in VS Code.
- When prompted, choose Reopen in Container (or run the Dev Containers: Reopen in Container command).
- Wait for
postCreateCommandto finish. The script runs the full setup and starts the server on port 8000 and Mailpit on port 8025.
- On the GitHub repository page, choose Code -> Codespaces -> Create codespace.
- Wait for the container to build and
postCreateCommandto finish. - Forwarded ports for 8000 (the app) and 8025 (Mailpit) appear in the Ports panel.
Customizing the container run
The Dev Container runs the script with all defaults. To change behaviour (for example, to skip fake
data or pull real Pretalx talks), open a terminal in the container and re-run scripts/dev-setup.sh
with the environment flags from the table below.
Path 2: Local setup¶
If you prefer to run on the host directly, clone the repository and run the setup script. The README's recommended first run keeps things fast and offline:
This generates sample data locally and never reaches out to Pretalx or Google Sheets, so it works without any API tokens.
What the script does¶
scripts/dev-setup.sh
runs these stages in order:
- Dependencies. Install
uvif missing, create the.venv, runuv sync --group dev --group test, and install the pre-commit hooks withprek install. It also setsDJANGO_READ_VARS_FILEbased on whetherdjango-vars.envexists (see Configuration). - Tailwind CSS. Download the standalone Tailwind binary into
.venv/bin(or symlink one already on yourPATH) and ensure theassets/cssandstatic/cssfolders exist. - Mailpit. Download the Mailpit binary into
.venv/bin(or symlink one on yourPATH). Mailpit is the local mail catcher used to read login codes. - Database migrations. Run
makemigrationsandmigrate. - Superuser. Create the admin superuser from
DJANGO_SUPERUSER_EMAIL/DJANGO_SUPERUSER_PASSWORD(defaultsadmin@example.com/admin). - Test users. When
GEN_TEST_USERS=true(the default), createuser1@example.com,user2@example.com, and a staff moderatormod@example.com. - Noto Sans font. When
DOWNLOAD_FONT=true, downloadNotoSans.ttfintoassets/fontsfor social card generation. - Sample data. When
GEN_FAKE_DATA=true, create the sample events (pyconde-pydata-2025,pyconde-pydata-2026,pydata-berlin-2026) and generate fake talks, rooms, and speakers for each withgenerate_fake_talks. - Pretalx sync. When
PRETALX_SYNC=true, ensure theDEFAULT_EVENTexists and runimport_pretalx_talks(requiresPRETALX_API_TOKEN). - Livestreams. When
IMPORT_STREAMS=true, runimport_livestream_urlsfrom Google Sheets (requires the sheet to be configured). - Event assignment. When
GEN_TEST_USERS=true, assign each test user to a random active event so they have something to see after logging in. - Services. Build (or watch, in debug mode) the Tailwind CSS, start Mailpit, and, when
RUN_SERVER=true, start the Django dev server. - Static files. Run
collectstaticat the end (unless skipped).
Mailpit ports in local dev
The script starts Mailpit on SMTP port 1026 by default, not the usual 1025. Port 1025 is often
held by tools like Proton Mail Bridge, which would make Django's login-code emails hang. The script
exports EMAIL_HOST and EMAIL_PORT so Django points at the right Mailpit instance, leaving the
committed django-vars.env (where EMAIL_PORT=1025 is correct for production) untouched. Override
MAILPIT_SMTP_PORT / MAILPIT_UI_PORT if those ports are taken. The Mailpit web UI stays on port
8025.
Setup flags¶
All flags are environment variables read at the top of the script. Pass them on the command line to override the defaults:
| Flag | Default | Effect |
|---|---|---|
RUN_SERVER |
true |
Start the Django dev server when setup finishes. |
DJANGO_PORT |
8000 |
Port the dev server binds to. |
GEN_FAKE_DATA |
true |
Generate sample events, talks, rooms, and speakers. |
FAKE_DATA_COUNT |
50 |
Number of fake talks generated per event. |
GEN_TEST_USERS |
true |
Create user1, user2, and the mod moderator, and link to events. |
PRETALX_SYNC |
false |
Import real talks from Pretalx (needs PRETALX_API_TOKEN). |
IMPORT_STREAMS |
false |
Import livestream URLs from Google Sheets. |
DOWNLOAD_FONT |
true |
Download Noto Sans for social card rendering. |
NO_AVATARS |
false |
Skip speaker avatar downloads during a Pretalx sync. |
IMAGE_FORMAT |
webp |
Image format passed to the Pretalx importer. |
SKIP_STEPS |
empty | Skip stages by name (see below). |
DEBUG |
false |
When true, run Tailwind in --watch mode instead of a one-off build. |
VENV_DIR |
.venv |
Location of the virtual environment. |
DJANGO_SUPERUSER_EMAIL |
admin@example.com |
Email for the created superuser. |
DJANGO_SUPERUSER_PASSWORD |
admin |
Password for the created superuser. |
SKIP_STEPS matches stage names as a substring, so you can skip one or several at once. Recognized
names: deps, tailwind, mailpit, django, and collectstatic. For example:
# Refresh data without reinstalling dependencies or rebuilding Tailwind.
SKIP_STEPS="deps tailwind" GEN_FAKE_DATA=true scripts/dev-setup.sh
Re-running for a clean slate
The script is safe to run again. For a fully clean rebuild, remove generated state first while keeping the virtualenv and the Pretalx cache:
Test users created¶
| Login method | Role | |
|---|---|---|
user1@example.com |
Email code | Regular attendee. |
user2@example.com |
Email code | Regular attendee. |
mod@example.com |
Email code | Staff moderator (is_staff=True). |
admin@example.com |
Password (admin) |
Superuser with admin and staff access. |
Regular and staff users are passwordless: they sign in with a one-time code emailed to them. Only the superuser has a password. See Authentication for the full picture.
First login walkthrough¶
Once setup has finished and the server is running:
- Open the app at http://127.0.0.1:8000.
- Enter
user1@example.com(oruser2@example.com) and submit the login form. If an event picker is shown, choose any active event. - Open Mailpit at http://localhost:8025. You will see the login-code email.
- Copy the code from the email and paste it into the confirmation form to finish signing in.
To reach the Django admin instead:
- Open http://127.0.0.1:8000/admin/.
- Sign in with
admin@example.comand passwordadmin.
Login code emails go to Mailpit, not a real inbox
In development, all outgoing mail is captured by Mailpit. Codes never leave your machine. Never use
the insecure default secret key or the admin/admin credentials in a real deployment.
What next¶
- Configuration for the full environment variable reference and the
django-vars.env/docker/.envsync rule. - Authentication for how passwordless login, Discord OAuth, and admin passwords fit together.
- Development for day-to-day commands, iterating with the setup flags, and the management commands.