Docs menu
Getting started
IntroductionInstallationProject structureBuilding pages
RoutingPagesLayoutsStylingMarkdownContent and dataIslandsGoing live
SEO and headDeployingFormsGuides
Build a brochure siteAdvanced
Running as a serverReference
ReferenceBuilding pages
Content and data
Data modules, content collections, and how to choose between a template, Markdown and data.
There are two ways to keep content out of your templates. Both live in src/content/, but
any folder works for the first.
Data modules
A plain Imba file exporting values. The simplest option, and the right one for short, structured data you edit yourself:
# src/content/business.imba
export const business =
name: 'Acme Studio'
phone: '0117 496 0000'
export const plans = [
{name: 'Basic', monthly: 95}
{name: 'Plus', monthly: 165}
]
import {business, plans} from '../content/business'
Data modules can compute values, import each other and hold translations
({en: 'Hello', fr: 'Bonjour'}), which collections can't.
Collections
Each folder in src/content/ is a collection, each .md, .json or .yaml file in it
an entry. For many similar items with real text, like services, case studies or these docs:
<!-- src/content/services/web-design.md -->
---
title: Web design
order: 1
priceFrom: 1200
---
We design **and** build, so nothing gets lost in the hand-over.
Read them anywhere on the server, even at the top of a file:
import {getCollection, getEntry} from '@milktop/imba-pages/content'
for s in getCollection('services')
<a href="/services/{s.id}"> s.data.title
let service = getEntry('services', 'web-design')
Each entry is:
| Field | Value |
|---|---|
id |
The file name without extension: web-design |
collection |
services |
data |
The front matter (Markdown), or the whole file (JSON/YAML) |
html |
The rendered Markdown body |
headings |
The body's headings, {depth, text, id} |
A typical setup: one dynamic page per entry, src/pages/services/[slug].imba, with
paths from getCollection('services') and the body shown with
<Markdown html=entry.html>.
Checks and order
src/content/config.imba can list required fields and a sort order. A missing field stops
the build with the file name, instead of quietly rendering a blank:
export const collections =
services:
required: ['title', 'priceFrom']
sort: 'order'
Without sort, entries are in file-name order. Imba has no type checking, so this is the
main safety net for content.
Good to know
- Collections are server-only: an island can't call
getCollection. Pass it the entries it needs as props. - In
dev, editing or adding a content file updates the site without a restart. - Only local files for now. To use a CMS or API, fetch it in a page's
load.
Template, Markdown or data?
The same question comes up in Astro (.astro or .md). In short: Markdown is for
documents, templates are for designed pages, data files are for lists.
- Markdown when the page is mostly running text in a standard layout: privacy and terms pages, an "our story" page, blog posts, case studies, docs.
- A template (
.imba) when the page is designed section by section, or built from data: a home page, pricing, a menu, contact with opening hours. - A data module for short structured lists: prices, team, opening hours, nav links.
- A collection for many similar items with real text, shown by one template.
Four questions usually settle it:
- Would it look fine as a printed document? Markdown.
- Does it need layout specific to this page? Template.
- Is it a list of structured things? Data, shown by a template.
- Will someone non-technical edit it? Lean towards Markdown.
Often it's both: a template that owns the design, showing Markdown for the writing, like the service pages in the brochure example.