Important: Schema file naming
- Schema files must start with a capital letter and be PascalCase, e.g.,
Doctors.json
,Hospitals.json
.- The file name should match the
modelName
value inside the file, e.g.,Doctors.json
→"modelName": "Doctors"
.- Place your schema files in your configured schemas directory (e.g.,
examples/node/schemas/
).Following these conventions ensures consistent model registration and avoids case‑sensitive filesystem issues.
Define schemas in nextmin-node
This page is a practical, generic guide to write your own schemas. It explains the structure, lists all unique field params supported by the examples, and provides copy‑paste templates.
If you already have working schemas, you can skim to the Field parameters catalog and Full schema template.
Schema structure
A schema is a JSON object with these top‑level keys:
- modelName: string. The collection/model name.
- group: string. Used for grouping in UIs.
- extends: string. Inherit base fields/behavior from another model (e.g. “Users”).
- attributes: object. Field definitions keyed by field name.
- allowedMethods: flags to enable CRUD endpoints.
- access: public/authenticated/roles permissions.
Minimal schema example
{
"modelName": "Posts",
"group": "Content",
"attributes": {
"title": { "type": "string", "required": true },
"slug": { "type": "string", "required": true, "unique": true },
"published": { "type": "boolean", "default": false }
},
"allowedMethods": { "create": true, "read": true, "update": true, "delete": true },
"access": {
"public": { "read": true, "create": false, "update": false, "delete": false },
"authenticated": { "read": true, "create": true, "update": false, "delete": false },
"roles": {
"admin": { "read": true, "create": true, "update": true, "delete": true }
}
}
}
Full schema template (with all commonly used params)
Use this as a starting point and remove what you don’t need.
{
"modelName": "ExampleModel",
"extends": "Users", // optional: inherit from another model
"group": "ExampleGroup",
"attributes": {
// BASIC FIELD TYPES
"name": { "type": "string", "required": true },
"description": { "type": "string", "longtext": true },
"age": { "type": "number", "min": 0, "max": 120 },
"email": { "type": "email", "required": true, "unique": true },
"isActive": { "type": "boolean", "default": false, "index": true },
// ENUM
"status": { "type": "string", "enum": ["draft", "published", "archived"], "default": "draft" },
// MASKED INPUT (e.g., phone numbers)
"phone": { "type": "number", "mask": "+xxx-xxxx-xxxxxx" },
// RELATIONS (ObjectId)
"owner": { "type": "ObjectId", "ref": "Users", "show": "email" },
"tags": [{ "type": "ObjectId", "ref": "Tags", "show": "name", "pageSize": 100 }],
// SCHEDULE / RANGE FIELDS
"monday": { "type": "range", "timeOnly": true },
// FILE UPLOAD FIELDS (store uploaded file ids/paths as strings)
"image": [{ "type": "string", "fileTypes": "images/*", "maxFilesCount": 1, "maxFileSize": 2097152 }],
// ADDRESS AUTOCOMPLETE (paired field)
"address": { "type": "string", "populate": "latLng", "countryCodes": ["bd"], "limit": 8 },
"latLng": { "type": "string", "hidden": true }
},
"allowedMethods": { "create": true, "read": true, "update": true, "delete": true },
"access": {
"public": { "read": true, "create": false, "update": false, "delete": false },
"authenticated": { "read": true, "create": true, "update": false, "delete": false },
"roles": {
"admin": { "read": true, "create": true, "update": true, "delete": true },
"superadmin": { "read": true, "create": true, "update": true, "delete": true }
}
}
}
Field parameters catalog
Below are the unique parameters you can use inside attributes, grouped by purpose.
-
Core
- type: string | number | boolean | email | ObjectId | range | string (file) | string (address)
- required: boolean – value must be present on create/update.
- default: any – default value if not provided.
- hidden: boolean – stored in DB but hidden from general reads/forms.
- longtext: boolean – hints UI to use a textarea/editor for long strings.
-
Validation & indexing
- enum: string[] – allowed values for string fields.
- min, max: number – numeric bounds (e.g., Ratings.rating).
- unique: boolean – unique index constraint (e.g., Districts.slug).
- index: boolean – create a secondary index (e.g., Doctors.verified).
- mask: string – input mask for number-like fields (e.g., phones).
-
Relations (ObjectId)
- ref: string – target model name (e.g., “Hospitals”).
- show: string – which field to display in UI selects (e.g., “name”).
- pageSize: number – page size for relation pickers (e.g., 64, 2000).
- Arrays: wrap the field in
[ { ...params } ]
to allow multiple references.
-
Files (stored as strings)
- fileTypes: string – MIME pattern, e.g., “images/*”.
- maxFilesCount: number – limit number of files.
- maxFileSize: number – per-file size limit in bytes (2MB = 2097152).
- Arrays: represent multi-file inputs.
-
Address autocomplete pair
- address field:
{ type: "string", populate: "latLng", countryCodes: ["bd"], limit: 8 }
- latLng field:
{ type: "string", hidden: true }
- populate: string – name of the hidden field to auto-fill.
- countryCodes: string[] – restrict search to specific countries.
- limit: number – max suggestions.
- address field:
-
Schedule/range
- type: “range”, timeOnly: true – value format
{ start: "HH:mm", end: "HH:mm" }
.
- type: “range”, timeOnly: true – value format
Access and methods
- allowedMethods: enable or disable CRUD endpoints per model:
{
"allowedMethods": { "create": true, "read": true, "update": true, "delete": true }
}
- access: define who can do what. You can combine public, authenticated, and granular roles:
{
"access": {
"public": { "read": true, "create": false, "update": false, "delete": false },
"authenticated": { "read": true, "create": true, "update": false, "delete": false },
"roles": {
"admin": { "read": true, "create": true, "update": true, "delete": true },
"editor": { "read": true, "create": true, "update": true, "delete": false }
}
}
}
Notes:
- Public means unauthenticated requests.
- Roles are additive; if multiple apply, the most permissive per action wins.
Tips for designing your schema
- Prefer string IDs for files; use the file upload API to get permanent paths/IDs.
- For relations, always set both ref and show to get nice selects in UIs.
- Use unique for slugs or any natural key, and index for frequently filtered fields.
- Pair address + latLng as shown to enable geocoding while keeping coordinates hidden.
- If you need user-like fields, consider extends: “Users” as in Doctors.
- Keep pageSize modest (e.g., 64) for better performance in dropdowns.
That’s it. With the template and parameter catalog above, you have all you need to create your own schema from scratch.