Skip to content

Quickstart

The fastest path from git clone to a workspace you can actually click around. Two routes: the demo seed (recommended for evaluation) and the API tutorial (recommended for learning the data model).

You should already have completed Installation — the stack is up via docker compose up -d.

Section titled “Route A — seed the demo project (recommended)”

The seed_demo_project management command bootstraps a coherent “Platform Migration” project with phases, work packages, baselines, resources, eight closed sprints, an active sprint mid-window, a planned sprint, a retro with a promoted action item, and board WIP overload. With --with-personas it also creates six demo logins.

Terminal window
docker compose exec api python manage.py seed_demo_project --with-personas

That’s it. Sign in at http://localhost:5173 as any of the personas (password: demo):

UsernamePersonaWhat to look at first
mayaScrum MasterThe Sprints workspace — burndown, capacity, backlog, retro all populated
rajProject ManagerThe Schedule view — critical path lit up, milestones, baseline overlay
sarahResource ManagerThe Capacity preflight panel surfaces an over-allocated member
dianaPMO DirectorThe Multi-team Sprints lens shows both projects
carlosExecutiveThe Overview page with forecast confidence intervals
tomSenior EngineerThe Board with the WIP overload chip and his assigned cards

Re-running the command clears the prior demo and re-seeds, so you can refresh after pulling new features.

If you want to learn the data model rather than evaluate the UI, build a project with two tasks and a dependency, trigger CPM, and read the result back. The examples below use curl and jq.

If you haven’t already, see Admin password setup. The default is to run python manage.py create_admin which generates a secure random password and writes it to /tmp/trueppm_admin_password.

Terminal window
curl -s -X POST http://localhost:8000/api/token/ \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "<your password>"}' \
| jq .access
export TOKEN="<paste access token here>"
Terminal window
CALENDAR=$(curl -s -X POST http://localhost:8000/api/v1/calendars/ \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Standard 5-day week"}')
CALENDAR_ID=$(echo $CALENDAR | jq -r .id)
Terminal window
PROJECT=$(curl -s -X POST http://localhost:8000/api/v1/projects/ \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"name\": \"My First Project\", \"start_date\": \"2026-04-01\", \"calendar\": \"$CALENDAR_ID\", \"methodology\": \"HYBRID\"}")
PROJECT_ID=$(echo $PROJECT | jq -r .id)

The methodology field controls default tab visibility — see Project methodology preset.

Terminal window
TASK_A=$(curl -s -X POST http://localhost:8000/api/v1/tasks/ \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"project\": \"$PROJECT_ID\", \"name\": \"Design\", \"duration\": 5}")
TASK_B=$(curl -s -X POST http://localhost:8000/api/v1/tasks/ \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"project\": \"$PROJECT_ID\", \"name\": \"Build\", \"duration\": 10}")
TASK_A_ID=$(echo $TASK_A | jq -r .id)
TASK_B_ID=$(echo $TASK_B | jq -r .id)
Terminal window
curl -s -X POST http://localhost:8000/api/v1/dependencies/ \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"predecessor\": \"$TASK_A_ID\", \"successor\": \"$TASK_B_ID\", \"dep_type\": \"FS\", \"lag\": 0}"

CPM recalculates automatically via Celery after each write. Wait a moment, then:

Terminal window
curl -s "http://localhost:8000/api/v1/tasks/?project=$PROJECT_ID" \
-H "Authorization: Bearer $TOKEN" \
| jq '.results[] | {name, early_start, early_finish, total_float, is_critical}'

Expected output:

{"name": "Design", "early_start": "2026-04-01", "early_finish": "2026-04-07", "total_float": 0, "is_critical": true}
{"name": "Build", "early_start": "2026-04-08", "early_finish": "2026-04-21", "total_float": 0, "is_critical": true}

Both tasks are critical because there is only one path through the network.

Terminal window
curl -s -X POST "http://localhost:8000/api/v1/projects/$PROJECT_ID/members/" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"user": "<user-id>", "role": 1}'

Role values: Owner=4, Admin=3, Scheduler=2, Member=1, Viewer=0.

Navigate to http://localhost:5173. The Schedule view (Gantt-style) renders the timeline with critical path lit up; the Board, Sprints, and supporting views are all wired against the live API.