Skip to main content

Custom fields at a glance

Open Saasframe ships with a universal custom-fields system. Administrators can add metadata to any entity without touching code, while developers can commit the same definitions to version control.

Custom fields definition screen

Point-and-click configuration​

  • Navigate to Backend → Entities and open the entity you want to extend.
  • Create new attributes, choose field types (text, select, reference, number, phone, etc.), and scope them per organization or tenant.
  • Custom fields appear instantly on CrudForm, DataGrid, and APIs generated by the query engine.

Code-first definitions​

Mirror the admin configuration by exporting entities from ce.ts within your module:

packages/inventory/src/modules/inventory/ce.ts
import { defineFields, cf } from '@saasframe/core/modules/dsl';

export const entities = [
{
id: 'inventory:item',
fields: defineFields([
cf.text('bin_location', { label: 'Bin Location' }),
cf.boolean('is_fragile', { label: 'Fragile' }),
]),
},
];

Run yarn saasframe entities install --module inventory --org <organizationId> to apply changes across environments. The admin UI will show the new fields alongside those created interactively.

Managing fieldsets via API​

When entities need different attribute “palettes” (e.g., catalog products with Fashion vs. Services fieldsets) you can configure the selector programmatically. Call the Entities API endpoint POST /api/entities/definitions.batch with two keys:

  • definitions: the field payloads just like in the CLI/UI.
  • fieldsets: an array of { code, label, icon?, description?, groups? } objects that matches customFieldEntityConfigSchema.
  • Optional singleFieldsetPerRecord toggles whether editors can pick multiple fieldsets per entity instance.
curl -X POST "$BASE_URL/entities/definitions.batch" \
-H "X-Api-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"entityId\": \"customers:person\",
\"definitions\": [
{ \"key\": \"preferred_contact_method\", \"kind\": \"enum\", \"configJson\": { \"options\": [\"email\", \"phone\", \"sms\"], \"fieldset\": \"customer_profile\", \"group\": { \"code\": \"preferences\" } } }
],
\"fieldsets\": [
{
\"code\": \"customer_profile\",
\"label\": \"Customers · Profile\",
\"icon\": \"lucide:user\",
\"groups\": [
{ \"code\": \"identity\", \"title\": \"Identity\" },
{ \"code\": \"preferences\", \"title\": \"Preferences\" }
]
}
],
\"singleFieldsetPerRecord\": true
}"

This request updates both the definitions and the curated list of fieldsets so CRUD forms immediately expose the new tab/dropdown. See Entities API → Field definitions for more parameters and scopes.