Swimlanes
A swimlane is a category that groups board cards by responsibility — Strategy, Engineering, Mechanical, Driver, Logistics, Hospitality, Auto. Every account has its own catalogue; the seed installs seven defaults that cover the majority of race-stand workflows.
Swimlanes are referenced by name from the
board cards swimlane
column and from
issue rule actions — so renaming a lane is a
catalogue-level operation, not a per-card update.
Source:
- API route:
apps/api/src/routes/swimlanes.ts - Schema:
swimlanestable inapps/api/src/db/schema.ts
The seven default lanes
make seed installs:
| Position | Name | Color | Typical owner |
|---|---|---|---|
| 0 | Strategy | #0070F3 (blue) | Race engineer / strategist |
| 1 | Engineering | #22C55E (green) | Performance / data engineer |
| 2 | Mechanical | #F59E0B (amber) | Mechanic / pit crew |
| 3 | Driver | #7B61FF (purple) | Driver coach |
| 4 | Logistics | #94A3B8 (slate) | Truck / paddock |
| 5 | Hospitality | #FFD700 (gold) | Sponsor / guest ops |
| 6 | Auto | #E10600 (red) | Auto-fired rules — see Issue Rules |
The seven lanes mirror HH-DM's stock list. They're wired into the seeded Issue Rules (rules write into Strategy / Engineering / Mechanical / Auto, depending on the trigger).
Position ordering
Lanes carry an integer position. The board card form's lane
dropdown, the kanban column rail, and the Admin grid all sort
by position ascending, breaking ties alphabetically by name.
When you create a new lane via POST /swimlanes without a
position, the server places it at the end of the list:
const position = body.position ?? existing.length;
Reordering is a series of PATCH /swimlanes/:id calls that
update position. The admin UI's drag-handle ribbon does this
transparently; ad-hoc API consumers should make sure to keep
positions unique within an account.
How board cards reference a lane
board_cards.swimlane is a plain text column — it stores the
lane name, not its UUID. This intentionally mirrors HH-DM's
behaviour: lane names are stable enough that a card surviving a
rename is the wrong default. If you rename "Mechanical" to "Pit
Crew", existing cards keep swimlane: "Mechanical" until you
re-categorise them.
Same convention applies to issue rule action bodies — they reference the lane by name:
{
"action": {
"type": "card",
"swimlane": "Strategy",
"priority": "high",
"titleTemplate": "Yellow flag on lap {{lapNumber}}"
}
}
Authoring lanes
Today the catalogue is managed via the API directly. Wire shape
(see /swimlanes for the
full reference):
# Create
curl -X POST http://localhost:6161/swimlanes \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "name": "Catering", "color": "#10B981" }'
# Update
curl -X PATCH http://localhost:6161/swimlanes/<id> \
-H "Authorization: Bearer $TOKEN" \
-d '{ "position": 0 }'
# Delete
curl -X DELETE http://localhost:6161/swimlanes/<id> \
-H "Authorization: Bearer $TOKEN"
Constraints: name ≤ 60 chars; color ≤ 20 chars (typically a
hex string); position is a non-negative int.
What's coming
- Per-lane WIP limits — soft caps on the number of "in progress" cards per lane.
- Per-lane default assignee — auto-set the assignee when a card is created in a given lane (e.g. cards in Mechanical default to the on-call mechanic).
- Lane-scoped permissions — restrict who can move a card
out of
Autointo a real lane after triage.