Docs menu

Getting started

IntroductionInstallationProject structure

Building pages

RoutingPagesLayoutsStylingMarkdownContent and dataIslands

Going live

SEO and headDeployingForms

Guides

Build a brochure site

Advanced

Running as a server

Reference

Reference

Building 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:

  1. Would it look fine as a printed document? Markdown.
  2. Does it need layout specific to this page? Template.
  3. Is it a list of structured things? Data, shown by a template.
  4. 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.