Page Models
A page model defines the schema for routable content — any piece of content that has a URL. When you create a page model, you're declaring the fields, path structure, and layout capabilities for a type of page on your site. SleekCMS uses that model to generate the editing interface for content creators and the API shape for developers.
This page covers how page models work, the two routing modes, dynamic blocks for composable layouts, and how to think about structuring page content.
What Is a Page Model
A page model is a content type definition where each instance produces a page with its own URL. This is what distinguishes pages from entries — entries are structured data without routes, while pages are the routable layer of your site.
When you create a page model, you configure three things:
A path — The URL structure for pages of this type. This determines where the page lives on your site and how its route is generated.
Fields — The data structure for the page's content. These can include text fields, images, reference fields pointing to entries, and structural fields like groups and collections.
Dynamic block fields — Optional fields that let content editors compose the page layout from a set of allowed block types. This is how you give editors layout flexibility while maintaining structural control.
The result is a reusable schema. A "Blog Post" page model might define a title, author reference, publish date, featured image, and a dynamic block field for body sections. Every blog post created from that model shares the same structure, the same editing interface, and the same API shape.
Path and Routing
Every page model has a path that determines the URL structure for its pages. SleekCMS supports two routing modes, and the one you choose depends on whether the model produces a single page or many pages.
Static Pages
A static page model produces exactly one page at a fixed path. You define the path in the model, and there is only ever one content instance for that model.
Common examples include a homepage (/), an about page (/about), a contact page (/contact), or a pricing page (/pricing). These are pages where you don't need multiple instances — there's one about page, not a collection of them.
When you set a page model's path to /about, SleekCMS creates one editable page at that path. In the site builder, this generates about/index.html. Through the content API, you fetch it with getPage('/about').
Page Collections
A page collection model produces multiple pages under a shared path prefix, with each page differentiated by a slug. This is the model type for blogs, product catalogs, case studies, documentation — any content type where you need many pages with the same structure but different content.
When you create a page collection, you define a base path and add a slug field to the model. SleekCMS generates routes automatically by combining the base path with each page's slug value.
For example, a blog page model with the path /blog and posts slugged hello-world and getting-started produces two routes: /blog/hello-world and /blog/getting-started. Each new blog post a content editor creates automatically gets its own route based on its slug.
The Slug Field
The slug field is a special text field that controls the URL segment for each page in a collection. When an editor creates a new page from a collection model, they provide a slug value — typically a URL-friendly version of the title.
Slugs must be unique within a collection. SleekCMS uses them for route generation, and duplicate slugs would produce conflicting URLs. Slugs are also what you pass to the content API to retrieve a specific page: getPage('/blog/hello-world').
Choosing Between Static and Collection
The decision is straightforward. If there will only ever be one instance of this page type, use a static page. If editors will create multiple pages with the same structure, use a collection.
| Scenario | Model Type | Path Example |
|---|---|---|
| Homepage | Static | / |
| About page | Static | /about |
| Blog posts | Collection | /blog/:slug |
| Product pages | Collection | /products/:slug |
| Case studies | Collection | /work/:slug |
| Contact page | Static | /contact |
Structuring Page Fields
Page model fields define what content editors fill in when they create or edit a page. The fields you add to a page model determine both the editing experience in the admin UI and the data shape in the API response.
Common Field Patterns
Most page models start with a core set of fields that cover the page's primary content and metadata.
Title and slug — Nearly every page model includes a title field. Collection models also include the slug field for route generation.
SEO and metadata — Fields for meta title, meta description, and Open Graph image give content editors control over how pages appear in search results and social media previews. Grouping these into a dedicated field group keeps the editor interface organized.
Featured media — Hero images, banner videos, or thumbnail images that represent the page visually. These are typically image or media fields.
Reference fields — Links to entries like authors, categories, or tags. A blog post model might reference an author entry (one-to-one) and multiple category entries (one-to-many). References keep shared data centralized rather than duplicated across pages.
Organizing with Groups
When a page model has many fields, groups help organize them into logical sections in the editor. You might group SEO fields together, put hero section fields in their own group, or separate primary content from sidebar content. Groups affect the editing interface layout but don't change the data structure — they're purely organizational.
Dynamic Blocks in Pages
Dynamic block fields are where page models become composable. A dynamic block field is a special field type that lets editors build a page's layout by adding, removing, reordering, and hiding block instances from a set of allowed block types.
How It Works
When you add a dynamic block field to a page model, you configure which block types editors are allowed to use. An editor creating a page then assembles the layout by choosing from those blocks — adding a hero section, then a features grid, then a testimonial carousel, then a call-to-action banner.
Each block instance in the dynamic field is an independent content section with its own fields, defined by the block model. The page becomes a stack of sections, where each section's structure is governed by its block model but the overall composition is up to the editor.
Layout Governance
Dynamic blocks give editors significant flexibility, but you control the boundaries. The allowed block types list is your governance mechanism — editors can only add blocks you've explicitly permitted on that page model.
This means you can create tightly controlled page models where editors choose from just two or three section types, or more open-ended models with a large library of blocks. The balance between flexibility and consistency is yours to set per page model.
When to Use Dynamic Blocks
Dynamic blocks are ideal when editors need to compose pages with varying layouts — landing pages, marketing pages, long-form content with mixed media sections. They're less necessary for pages with a fixed, predictable structure. A simple "About" page with a fixed set of fields doesn't need dynamic blocks. A landing page that might have anywhere from three to twelve sections in different orders does.
Not every page model needs a dynamic block field. Use them when the layout varies across instances; use fixed fields when every page of that type has the same structure.
Page Models and the Site Builder
If you're using the integrated site builder, each page model is bound to an EJS template. The template defines how the page's content renders to HTML. When the builder compiles your site, it processes each page record through its model's template and produces a static HTML file.
For static pages, the builder generates one HTML file at the model's path. For page collections, it generates one file per record using the slug to differentiate output paths.
Dynamic block fields render by delegating to each block's own template. The page template includes the dynamic block field, and the builder iterates through the block instances, rendering each one with the appropriate block template and injecting the output into the page. This is how composable layouts work at the template level — the page template orchestrates, and block templates handle the individual sections.
→ Site Builder → Model Templates
Page Models and the Content API
If you're consuming content through the API rather than the site builder, page models define the JSON shape of your API responses.
Fetching a static page returns its fields as a JSON object. Fetching pages from a collection returns an array of objects, each with the same field structure. The getPage() method retrieves a single page by exact path, while getPages() retrieves all pages under a path prefix. The getSlugs() method returns the slug values for a collection, which is useful for generating static routes in frameworks like Next.js or Astro.
// Static page
const about = client.getPage('/about');
// Single collection page
const post = client.getPage('/blog/hello-world');
// All collection pages
const posts = client.getPages('/blog');
// Slugs for static generation
const slugs = client.getSlugs('/blog');
// ['hello-world', 'getting-started', 'advanced-techniques']
Dynamic block fields appear in the API response as an array of block objects, each with a type identifier and its field data. Your frontend code can iterate over these blocks and render the appropriate component for each type.
→ Content API → @sleekcms/client
What's Next
- Entry Models — Structured, non-routable content for shared data like authors, categories, and settings.
- Block Models — Reusable, composable content components for dynamic page sections.
- Content Field Types — The full set of field types available in page, entry, and block models.
- Dynamic Blocks — Deep dive into configuring and using dynamic block fields.
- Content Editing — The editing experience for content creators working with page models.