Nodes
The unified content primitive and how to edit one.
What a node is
Everything you publish in Squilla — a page, a blog post, a recipe, a doc article, a portfolio entry — is a node. There's no separate pages, posts, recipes table; one content_nodes table holds them all, distinguished by their node_type. Custom fields live in JSONB columns with a GIN index, so adding a new kind of content is metadata-only — no SQL migration.
The columns that matter
node_type— which schema applies (page,post,recipe, etc.)status—draftorpublishedlanguage_code— which language this row is intranslation_group_id— links translations of the same logical contentslug,title,excerptfeatured_image— thumbnail / OG image, an object{url, alt, ...}blocks_data— array of{type, fields}content blocksfields_data— the node-type-level custom fieldstaxonomies— attached terms keyed by taxonomy slugseo_settings— meta title / description overridelayout_slug— optional per-node layout override
The edit screen
Find the list at /admin/nodes/<type> (e.g. /admin/nodes/page). Click any row to open the edit screen, or hit "New" to create one.
Anatomy
The edit screen is a familiar two-column layout:
- Top bar — title, slug (auto-generated from title, editable, validated unique within type+language), status toggle, language switcher, Save button
- Main column — the block editor and any node-type-level custom fields, plus a tab for layout-block (partial) field overrides if the active layout uses partials with fields
- Sidebar — featured image, excerpt, taxonomies, translations, layout override, SEO panel
The block editor
The main column hosts the block editor. Click Add block to open the block library — a searchable picker of every block registered by the active theme, by extensions, and any custom blocks you've built in /admin/blocks. Click a block to insert it.
Per-block actions
- Up / Down arrows — move a block up or down in the stack
- Duplicate — clone with the same field values
- Delete — remove from the node
- Collapse — hide field details, keep the block in place
Each block renders its own field_schema as a form: text, richtext, image picker, repeater, and so on. Fields are validated client-side against the schema (required, type) before save.
Sidebar panels
Featured image
Opens the media library modal. Pick or upload an image. Used as thumbnail in lists, OG image for social shares, and accessible via .node.featured_image in templates.
Excerpt
Plain text summary. Used in archive listings, search results, and as the default og:description when no SEO override is set.
Taxonomies
One multi-select per taxonomy attached to the node type. Selecting a term stores it as {slug, name} object in taxonomies.<taxonomy_slug>.
Translations
Lists existing translations linked via translation_group_id. Click Add translation, choose a language, and a fresh node is cloned into the same group. See the Multi-language page for details.
Layout override
By default a node uses its node-type's default layout. Override here when this specific node needs a different layout (e.g. a landing page using a wide layout while regular pages use the default).
SEO
Meta title and meta description. Empty falls back to title and excerpt respectively.
fields_data: — blocks INSIDE blocks_data use fields:. Mismatching either silently drops the data. The save endpoint warns at runtime, but the admin UI handles this for you when you stay inside the editor.