Skip to content

Custom Fields

Custom fields allow extending task (or other entity) data with user-defined attributes beyond the built-in title, description, status, and priority.

Model

CustomField
├── entityType (e.g. "task", "project")
├── name, type, config (JSON)
└── values (CustomFieldValue[])

CustomFieldValue
├── entityId (references the entity instance)
├── fieldId (references the CustomField definition)
└── value (JSON)

Field Types

TypeConfigValue Format
textstring
number{ min?, max? }number
select{ options: string[] }string (one of options)
dateISO date string
checkboxboolean

API Endpoints

Field Definitions

MethodPathDescription
GET/api/custom-fields/:entityTypeList fields for entity type
POST/api/custom-fieldsCreate field definition
PATCH/api/custom-fields/:idUpdate field definition
DELETE/api/custom-fields/:idDelete field definition

Field Values

MethodPathDescription
GET/api/custom-field-values/:entityIdGet values for entity
POST/api/custom-field-values/:entityIdSet values (upsert)

Frontend

Custom Fields Store

typescript
const store = useCustomFieldsStore()

await store.fetchFields(entityType)
await store.createField({ entityType, name, type, config })
await store.updateField(id, { name, type, config })
await store.deleteField(id)

await store.fetchValues(entityId)
await store.setValues(entityId, [{ fieldId, value }])

CustomFieldEditor Component

The CustomFieldEditor.vue component renders a dynamic form based on field definitions:

  • text → text input
  • number → number input with min/max
  • select → dropdown from configured options
  • date → date picker
  • checkbox → toggle switch

Key Implementation Details

  • Field names must be unique per entity type (enforced by @@unique([entityType, name]))
  • Values are stored as JSON, allowing flexible types
  • Deleting a field cascades to delete all its values
  • Custom fields are displayed on the task detail sidebar