Core Concepts
This page explains the building blocks of Forme. Understanding these concepts will help you model content effectively and use the API and SDK with confidence.
Content Models
A content model defines the shape of your content — similar to a database table schema or a TypeScript interface. Each model has:
- apiId — a unique identifier used in API calls (e.g.,
BlogPost,Navigation) - name — a human-readable display name
- type — one of three categories (see below)
- fields — an ordered list of field definitions
Model types
| Type | Purpose | Example |
|---|---|---|
| page | Routable content with its own URL | Blog post, landing page, product page |
| component | Reusable content blocks embedded in other entries | Hero banner, CTA section, testimonial card |
| data | Structured data without a URL | Site settings, navigation menu, author profile |
The type is metadata — it helps organize content in the Admin UI and enables future features like URL routing. All three types work identically in the API.
Field Types
Forme provides 10 field types. Every field has common properties:
| Property | Description |
|---|---|
apiId | Unique identifier within the model (e.g., title, heroImage) |
name | Human-readable label |
required | Whether the field must have a value (true/false) |
localized | Whether the field stores per-locale values (true/false) |
description | Optional help text shown in the Admin UI |
Available types
| Type | Stores | Key validations |
|---|---|---|
shortText | Single-line string (up to ~256 chars) | unique, minLength, maxLength, pattern (regex), in (enum list) |
longText | Multi-line plain text | unique, minLength, maxLength |
richText | Markdown content (CommonMark + GFM) | — |
number | Integer or decimal | unique, min, max, integerOnly |
boolean | true or false | — |
dateTime | ISO 8601 date/time string | — |
json | Arbitrary JSON value | — |
asset | Reference to an uploaded asset | allowedMimeTypes (e.g., ["image/png", "image/jpeg"]) |
reference | Reference to another entry | allowedModels (restrict to specific model apiIds), many (allow multiple references) |
array | List of primitive values (tags, etc.) | itemType (shortText or number), minItems, maxItems, unique, in (allowed values), allowCustomValues, itemMinLength, itemMaxLength, itemPattern |
The array field type stores a list of primitive values inline on the entry — use it for tags, keywords, categories, multi-select options, etc. For arrays of references to other entries, use reference with many: true instead (different storage shape, link semantics).
{
"tags": ["ai", "erp", "headless"]
}
Localized vs. unlocalized fields
When a field has localized: true, its value is stored as a locale map:
{
"title": { "en-US": "Hello World", "de-DE": "Hallo Welt" }
}
When localized: false (default), the value is stored directly:
{
"slug": "hello-world"
}
Entries
An entry is an instance of a content model — a blog post, a navigation menu item, or a product page. Every entry has:
- A reference to its content model
- A fields object containing the content values
- A status indicating its lifecycle stage
Entry lifecycle
Entries follow a draft/publish lifecycle:
┌──────────┐
create → │ draft │
└────┬─────┘
│ publish
▼
┌──────────┐
│ published│ ◄── unpublish returns to draft
└────┬─────┘
│ edit (after publishing)
▼
┌──────────┐
│ changed │ ── has unpublished changes
└────┬─────┘
│ publish (publishes the changes)
▼
┌──────────┐
│ published│
└──────────┘
| Status | Meaning | Visible in Delivery API? |
|---|---|---|
draft | Not yet published | No |
published | Live version matches latest edit | Yes |
changed | Has edits since last publish | Yes (shows last published version) |
Version history
Every publish creates a version snapshot. You can list an entry's version history via the Management API to see what was published and when.
Assets
Assets are files (images, documents, videos) managed through Forme. They follow the same draft/publish lifecycle as entries:
- Upload a file — creates a draft asset with metadata (filename, MIME type, size)
- Add metadata — title, description, alt text (localized if needed)
- Publish the asset — makes it available via the Delivery API
- Reference the asset from entries using an
assetfield type
Assets are stored in S3-compatible object storage. The Delivery API returns asset metadata including a download URL.
Locales
Forme supports content localization by default. Localization is configured at two levels:
1. Workspace locales
Your workspace has a set of available locales (e.g., en-US, de-DE, fr-FR). One locale is the default. Manage locales via the Management API or Admin UI Settings.
2. Field-level localization
Each field declares whether it is localized. Localized fields store values per locale. Unlocalized fields store a single value shared across all locales.
Locale resolution (query time)
When fetching content, you can pass a locale query parameter:
- Without
?locale=— localized fields return the full locale map:{ "en-US": "Hello", "de-DE": "Hallo" } - With
?locale=de-DE— localized fields are resolved to a single value using the fallback chain
Fallback chain
If content is missing for the requested locale, Forme walks the fallback chain:
Requested locale → Fallback locale → Default locale
For example, if de-DE has no content but its fallback is en-US (the default), the English content is returned. This is configured per locale when you create it.
Environments
Environments are isolated content branches within a workspace. Think of them like git branches for your content.
How environments work
- Every workspace starts with a production environment (the default)
- You can create additional environments (e.g.,
staging,feature-x) - Each environment has its own content models, entries, and assets
- API keys are scoped to a specific environment
Use cases
| Environment | Purpose |
|---|---|
production | Live content |
staging | Test changes before publishing to production |
feature-x | Experiment with content structure changes |
Content isolation
Environments are fully isolated — entries created in one environment are not visible in another. In M2, full-clone operations will allow you to copy content between environments.
API Keys
Forme uses two types of API keys for authentication:
| Key type | Prefix | Access | Use case |
|---|---|---|---|
| Secret Key | ce_secret_ | Management API (read + write) | Server-side operations, Admin UI, CI/CD |
| Read Key | ce_read_ | Delivery API (read-only, published content) | Frontend apps, static site generation |
Both keys are scoped to a specific workspace and environment. Pass them in the Authorization header:
Authorization: Bearer ce_secret_YOUR_KEY_HERE
Security: Secret Keys have full write access. Never expose them in client-side code. Use Read Keys for frontend applications.
Next steps
- Quickstart — put these concepts into practice
- Admin UI Guide — manage content through the browser interface
- SDK Getting Started — typed TypeScript client for all operations
- API Reference — authentication, pagination, and error handling details