Program folders group program templates in the template library. Each folder belongs to one studio and one program type, and carries a name, a colour and a sort order. 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.
Folders are ordered by order ascending, then createdAt ascending. There is no pagination. data is the array itself. Response:
Errors: 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.
Response: the created ProgramFolder row.
Errors: 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.
The service loads the folder scoped to the studio first, then updates it. Response: the updated 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.
Templates inside the folder are kept. The ProgramTemplate.folderId relation is declared with onDelete: SetNull, so those templates become unfiled. Errors: NOT_FOUND (folder not found).