This module is smaller than the usual five-file pattern. It has two files:
program-folders.routes.ts, which holds the handlers and an inline createService(prisma) that talks to Prisma directly, and program-folders.schema.ts with the Zod schemas.
The ProgramFolder row
Endpoints
GET /v1/web/program-folders
Lists the studio’s folders.
Auth: web lane, any role.
string
One of
TRAINING, NUTRITION, COMBINED. Omit to return folders of every type.order ascending, then createdAt ascending. There is no pagination. data is the array itself.
Response:
UNAUTHORIZED with no studio context. VALIDATION (422) for an unknown type.
POST /v1/web/program-folders
Creates a folder. Returns 201.
Auth: web lane, any role.
string
required
One of
TRAINING, NUTRITION, COMBINED.string
required
Folder name. Minimum length 1. There is no uniqueness check, so two folders can share a name.
string
Any string. Not validated as a colour. Falls back to the column default
#4f46e5 when omitted.integer
Sort position. Coerced with
z.coerce.number().int(). Falls back to 0 when omitted.ProgramFolder row.
VALIDATION for a bad body. UNAUTHORIZED with no studio context.
PATCH /v1/web/program-folders/:id
Renames, recolours or reorders a folder. Only the fields sent are written. type cannot be changed.
Auth: web lane, any role.
string
required
The folder id.
string
Minimum length 1.
string
Any string.
integer
Sort position.
ProgramFolder row, same shape as the create response.
Errors: NOT_FOUND (folder not found) when the id does not exist or belongs to another studio. VALIDATION for a bad body.
DELETE /v1/web/program-folders/:id
Deletes a folder. Returns 204 with no body.
Auth: web lane, any role.
string
required
The folder id.
ProgramTemplate.folderId relation is declared with onDelete: SetNull, so those templates become unfiled.
Errors: NOT_FOUND (folder not found).