Configuration
Pages
Configure page layouts and content blocks
Overview
Pages define what content is displayed for each route. Each page specifies which blocks to render in different areas (main content, side panel, header, footer).
import type { Config } from "@envisioning/app";
const pages: Config["navigation"]["pages"] = [
{
id: "technologies",
menuId: "techs",
label: { en: "Technologies" },
content_blocks: ["entitiesList"],
context: {
schemaKey: "entities",
plurality: "many",
},
},
];Properties Reference
| Property | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique page identifier |
menuId | string | Yes | Associated menu item ID |
label | I18n | Yes | Page display label |
content_blocks | string[] | Record<DisplayMode, string[]> | Yes | Main content block IDs |
rightContent_blocks | string[] | No | Side panel block IDs |
leftContent_blocks | string[] | No | Full-page left content |
headerContent_blocks | string[] | No | Header block IDs |
footerContent_blocks | string[] | No | Footer block IDs |
footerPanel_blocks | string[] | No | Panel footer blocks |
preview_blocks | string[] | No | Preview blocks (hover/preview mode) |
context | object | No | Data context configuration |
sortOptions | array | No | Available sort options |
groupOptions | array | No | Grouping options |
showFavorite | boolean | No | Show favorite button in top bar |
textContent | string | No | Template for text/markdown content |
Page Types
Static Pages
Pages without data context display static content:
{
id: "about",
menuId: "about",
label: { en: "About" },
headerContent_blocks: ["coverImage"],
content_blocks: ["spacerSm", "aboutText", "evLogo"],
textContent: `{{data.project.about}}`,
}List Pages (Many Items)
Display multiple items from a schema object:
{
id: "technologies",
menuId: "techs",
label: { en: "Technologies" },
context: {
schemaKey: "entities",
plurality: "many",
},
content_blocks: ["entitiesList"],
footerPanel_blocks: ["panelSearch"],
showFavorite: true,
sortOptions: [
{ title: "Title", sortCriteria: { title: 1 } },
{ title: "TRL", sortCriteria: { "trl.value": 1 } },
],
groupOptions: [
{ label: { en: "Collection" }, joinKey: "collection" },
{ label: { en: "TRL" }, joinKey: "trl" },
],
}Detail Pages (Single Item)
Display a single item's details:
{
id: "technology",
menuId: "techs",
label: { en: "Entity" },
context: {
schemaKey: "entities",
plurality: "one",
},
content_blocks: [
"spacerMd",
"contextSummary",
"trlChart",
"contextDescription",
],
footerPanel_blocks: ["techsPagination"],
preview_blocks: ["entity-preview-item"],
showFavorite: true,
}Content Blocks
Simple Block List
content_blocks: ["entitiesList", "spacer", "pagination"]Display Mode-Aware Blocks
Different blocks for list vs card view:
content_blocks: {
list: ["entitiesList"],
cards: ["entitiesCards"],
}Page Areas
| Area | Description |
|---|---|
headerContent_blocks | Full-width header area |
content_blocks | Main content area |
rightContent_blocks | Side panel (when in panel mode) |
leftContent_blocks | Left column (when in full-page mode) |
footerContent_blocks | Full-width footer area |
footerPanel_blocks | Panel footer (search, pagination) |
preview_blocks | Hover preview card content |
Context Configuration
The context object tells the page which data to load:
context: {
schemaKey: "entities", // Schema object key
plurality: "many" | "one" // List or detail view
}plurality: "many"- Lists all items, providescontext._itemsarrayplurality: "one"- Single item, providescontextwith item data
Sort Options
Define how users can sort list pages:
sortOptions: [
{
title: "Title",
sortCriteria: { title: 1 }, // 1 = ascending
},
{
title: "TRL",
sortCriteria: { "trl.value": 1 },
fixed: { collection: 1 }, // Optional: always sort by collection first
},
]| Property | Type | Description |
|---|---|---|
title | string | Display label |
sortCriteria | Record<string, 1 | -1> | Sort fields (1 = asc, -1 = desc) |
fixed | Record<string, 1 | -1> | Optional fixed sort applied first |
Group Options
Define how users can group list pages:
groupOptions: [
{
label: { en: "Collection" },
joinKey: "collection",
},
{
label: { en: "TRL" },
joinKey: "trl",
},
]Text Content (AI/Export)
The textContent field provides a text representation of the page for AI assistants and exports:
{
id: "technology",
textContent: `{{context.summary}}
Collection: {{context.collection.title}}
{%- for ass in context.assessment %}
Assessment for {{ass.country.code}}:
- TRL: {{ass.metric1.value}}
- Cost: {{ass.metric2.value}}
{%- endfor%}`,
}Uses Nunjucks templating syntax.
Complete Example
export const pages: Config["navigation"]["pages"] = [
// Home page
{
id: "home",
menuId: "home",
label: { en: "Home" },
headerContent_blocks: ["coverImage"],
content_blocks: ["spacerSm", "scopeItem", "homeIntro"],
textContent: `{{data.project.description}}`,
},
// List page
{
id: "technologies",
menuId: "techs",
label: { en: "Technologies" },
context: {
schemaKey: "entities",
plurality: "many",
},
content_blocks: { list: ["entitiesList"], cards: ["entitiesCards"] },
footerPanel_blocks: ["panelSearch"],
showFavorite: true,
sortOptions: [
{ title: "Title", sortCriteria: { title: 1 } },
{ title: "TRL", sortCriteria: { "trl.value": 1 } },
],
groupOptions: [
{ label: { en: "Collection" }, joinKey: "collection" },
],
},
// Detail page
{
id: "technology",
menuId: "techs",
label: { en: "Technology" },
context: {
schemaKey: "entities",
plurality: "one",
},
content_blocks: [
"spacerMd",
"contextSummary",
"dash",
"trlChart",
"contextDescription",
],
footerPanel_blocks: ["techsPagination"],
preview_blocks: ["entity-preview-item"],
showFavorite: true,
},
// About page
{
id: "about",
menuId: "about",
label: { en: "About" },
content_blocks: ["aboutText", "evLogo"],
textContent: `{{data.project.about}}`,
},
];