Build a Custom Database
This guide implements a small project database. It assumes the Core Concepts and Schema Declarations mental model.
1. Create the declaration
import {
Enums,
bd,
collection,
createFormSchemaOrchestrator,
} from '@businessdash/sdk'
const ProjectStatus = Enums([
'planned',
'active',
'complete',
] as const)
const clients = collection('clients', {
visibility: 'private',
labelIdentifierFieldName: 'name',
fields: {
name: bd
.text()
.required()
.validate({ minLength: 2, maxLength: 120 }),
email: bd
.email()
.optional()
.formElement('email'),
},
})
const projects = collection('projects', {
visibility: 'private',
labelIdentifierFieldName: 'title',
fields: {
title: bd
.text()
.required()
.formElement('short_text')
.validate({ minLength: 3, maxLength: 160 }),
status: bd
.enum(ProjectStatus)
.default('planned')
.formElement('dropdown'),
budget: bd
.number()
.optional()
.formElement('currency')
.validate({ positive: true, round: 2 }),
client: bd
.relation()
.references('clients')
.onDelete('RESTRICT')
.required(),
},
})
export const definition = createFormSchemaOrchestrator([
clients,
projects,
])
export default definition.databaseSchema
export const projectFormTree = definition.uiFormTree
This implementation uses direct collections. SchemaBoundary is unnecessary
unless the application needs feature tags, and no step or group is required.
2. Inspect the compiled artifact
npx bd print-data-model
Confirm:
- both collections are present,
idfields were injected with the intended primary-key strategy,projects.clientresolved to the client collection,- field types, validation metadata, and form-element intent are correct.
3. Compare with Live
npx bd view-data-model --diff
npx bd sync-data-model --dry-run
The first command compares source with the promoted model. The second prints the migration proposal without creating a draft.
Review any:
- removals,
- type changes,
- visibility changes,
- identity changes that look like drop-and-add instead of rename.
4. Push a draft
npx bd sync-data-model \
--note "Add clients and projects"
Promote the draft in:
Site Builder → Site Data → Database
The key proposes the change; a person controls promotion.
5. Seed records after promotion
Place convergent record files in bd-records/, then run:
npx bd sync-records --dry-run
npx bd sync-records
Relationship links use the record's separate relations object. Continue to
Relationship Data for that
two-pass workflow.
Extend this implementation
| Need | Continue to |
|---|---|
| Add another stored type | Primitive Builders |
| Add defaults, indexes, or metadata | Field Modifiers |
| Add or debug constraints | Validation |
| Choose input components | Form Elements |
| Add fixed choices | Enums |
| Add richer relations | Relationships and Extensions |
| Add steps, conditions, or repeaters | Unified Form Orchestration |
| Review every CLI command | Collections and CLI Changes |