Schemas
A collection's schema declares its fields and, optionally, which fields map onto filterable index columns. The schema validates writes and drives fast list filtering.
Shape
type CollectionSchema = {
title?: string;
fields: Field[];
indexes?: {
title?: string; // field name to surface as the entry title
summary?: string; // field name to surface as a short summary
slug?: string; // field name to use as the slug for ?slug= filtering
};
};
type Field = {
name: string;
type:
| "string" // short single-line text
| "text" // long plain text
| "richtext" // HTML or markdown string, stored verbatim
| "number"
| "boolean"
| "object" // nested JSON object
| "array" // JSON array
| "relation"; // entry id (or ids) referencing another entry
};
Field types
| Type | Stores | Notes |
|---|---|---|
string |
short text | headlines, slugs, titles |
text |
long text | plain body copy |
richtext |
HTML/markdown string | stored verbatim, Floggy does not parse or sanitize it |
number |
number | |
boolean |
boolean | |
object |
JSON object | nested structured data |
array |
JSON array | lists, repeated blocks |
relation |
entry id string, or array of ids | references another entry, validated lazily |
Floggy validates field presence and type on write. It does not interpret the meaning of a field. richtext is a string you render yourself.
The indexes mapping and why it exists
Entry data is stored as one JSON document. Filtering a list by reading and scanning every document does not scale. indexes maps up to three data fields onto dedicated columns so list queries filter without touching the JSON body.
{
"title": "Landing pages",
"fields": [
{ "name": "slug", "type": "string" },
{ "name": "headline", "type": "string" },
{ "name": "summary", "type": "text" },
{ "name": "body", "type": "richtext" }
],
"indexes": {
"title": "headline",
"summary": "summary",
"slug": "slug"
}
}
With this mapping:
GET /entries?slug=black-fridayfilters on the indexedslugcolumn, fast, no JSON scan.- List responses can surface
titleandsummarywithout returning the full body (?full=1returns the wholedata).
Only title, summary, and slug are indexable. Point them at whichever of your fields carry that role. Changing an index mapping re-indexes existing entries.
Relations
A relation field stores the referenced entry's id (or an array of ids) as plain strings. Validation is lazy: Floggy does not block a write when a referenced entry does not exist, and it does not cascade deletes. Resolve relations in your own reads by fetching the referenced entries.
{
"name": "author",
"type": "relation"
}
Store the target entry id in that field, then look it up when you render.
Example: landing-page schema
{
"title": "Landing pages",
"fields": [
{ "name": "slug", "type": "string" },
{ "name": "headline", "type": "string" },
{ "name": "subhead", "type": "string" },
{ "name": "summary", "type": "text" },
{ "name": "body", "type": "richtext" },
{ "name": "hero", "type": "object" },
{ "name": "features", "type": "array" },
{ "name": "published", "type": "boolean" },
{ "name": "author", "type": "relation" }
],
"indexes": {
"title": "headline",
"summary": "summary",
"slug": "slug"
}
}
An SEO engine writes entries against this shape; your site filters by slug, reads the indexed headline/summary for list views, and pulls the full body on the page.
Next
- API reference - the list filters (
?slug,?tag,?q,?full) that indexes power. - Quickstart - create a collection with this schema.