Guides

List Nodes

List nodes repeat their children for each item in a data source. They are the primary way to display collections of content -- blog listings, team grids, product catalogs, and any other repeatable layout.

Meno has a single unified List node type with two source modes:

  • Collection lists pull items from a CMS collection.

  • Prop-based lists iterate over an array passed as a component prop.


Adding a List Node

  1. Select the element where you want the list to appear.

  2. Open the Command Palette (Cmd+E on macOS, Ctrl+E on Windows/Linux).

  3. Choose Add CMS List (for collection source) or Add List (for prop source).

  4. The new list node appears as a child of the selected element.


Configuring a Collection List

  1. Select the list node in the structure tree.

  2. In the Properties panel on the right, set Source Type to collection.

  3. Set Source to the collection name (e.g. posts, team, products).

  4. Optionally set Limit to cap the number of items shown.

  5. Optionally configure Sort (field and order) and Filter conditions.

  6. Build the item template by adding child elements inside the list node. Use {{item.fieldName}} template expressions to insert each item's data.

By default, the item variable is the singularized form of the collection name. For a collection named posts, the variable is post, so you can write {{post.title}} instead of {{item.title}}. To customize this, set the Item Variable field.


Configuring a Prop-Based List

  1. Select the list node.

  2. Set Source Type to prop.

  3. Set Source to the prop name that holds the array (e.g. items, features).

  4. Add child elements and use {{item.fieldName}} to reference each array element's properties.

This is useful when a reusable component receives its data as a prop rather than querying the CMS directly.


Template Variables

Inside a list's children, these template expressions are available:

Variable

Description

{{item.field}}

Value of a field on the current item

{{itemIndex}}

Zero-based index of the current item

{{itemFirst}}

true if this is the first item

{{itemLast}}

true if this is the last item

When using a named context (the itemAs property or auto-singularized name):

Variable

Description

{{post.title}}

Named access (collection "posts", auto-singularized)

{{postIndex}}

Index using the named prefix

{{postFirst}}

First-item flag using the named prefix

{{postLast}}

Last-item flag using the named prefix

The legacy item/itemIndex/itemFirst/itemLast variables are always available alongside the named versions for backward compatibility.


List Properties Reference

Shared Properties (Both Source Types)

Property

Type

Description

sourceType

"prop" or "collection"

Data source mode

source

string

Prop name or collection name (required)

itemAs

string

Variable name for templates (default: "item" for prop, singularized collection name for collection)

tag

string or false

Container HTML element (default: "div"). Set to false for no wrapper (fragment mode)

limit

number

Maximum items to render

offset

number

Skip the first N items

Collection-Only Properties

Property

Type

Description

items

string or string[]

Specific item IDs, or a template expression like "{{post.relatedIds}}"

filter

object or object[]

Filter conditions (see below)

sort

object or object[]

Sort configuration (see below)

excludeCurrentItem

boolean

Exclude the current CMS item from results (useful for "related posts" sections)

emitTemplate

boolean

Emit a <template> element for client-side rendering by MenoFilter

Filter Conditions

Each filter condition is an object with:

Field

Description

field

The item field to compare

operator

One of: eq, neq, gt, gte, lt, lte, contains, in (default: eq)

value

The value to compare against

Sort Configuration

Field

Description

field

The item field to sort by

order

"asc" or "desc" (default: "asc")


Container Tag Options

The list node wraps its output in a container element. Choose the tag that matches your semantic intent:

Tag

Use case

div

Generic container (default)

ul

Unordered list (children become <li>)

ol

Ordered list

section

Thematic section

nav

Navigation links

article

Self-contained content

false

No wrapper -- items render as siblings (fragment mode)


List vs. CMS Template Pages

These two features serve different purposes:

Feature

List Node

CMS Template Page

What it does

Loops through items inline

Generates one HTML page per item

Where it lives

Any page, any position

pages/templates/ directory

Typical use

Blog listing, team grid, product catalog

Individual blog post page, product detail page

Output

One section within a page

Separate .html files

You usually need both: a List node on a listing page (e.g. /blog) to show all posts, and a template page (e.g. pages/templates/blog-post.json) to render each individual post at /blog/{slug}.


Under the Hood

Collection List JSON

{
  "type": "list",
  "sourceType": "collection",
  "source": "posts",
  "tag": "div",
  "limit": 10,
  "sort": { "field": "publishDate", "order": "desc" },
  "filter": { "field": "published", "operator": "eq", "value": true },
  "style": {
    "base": {
      "display": "grid",
      "gridTemplateColumns": "repeat(3, 1fr)",
      "gap": "24px"
    }
  },
  "children": [
    {
      "type": "node",
      "tag": "article",
      "children": [
        {
          "type": "node",
          "tag": "img",
          "attributes": {
            "src": "{{post.cover}}",
            "alt": "{{post.title}}"
          }
        },
        {
          "type": "node",
          "tag": "h3",
          "children": "{{post.title}}"
        },
        {
          "type": "node",
          "tag": "p",
          "children": "{{post.excerpt}}"
        }
      ]
    }
  ]
}

Prop-Based List JSON

{
  "type": "list",
  "sourceType": "prop",
  "source": "features",
  "itemAs": "feature",
  "tag": "ul",
  "children": [
    {
      "type": "node",
      "tag": "li",
      "children": [
        {
          "type": "node",
          "tag": "strong",
          "children": "{{feature.title}}"
        },
        {
          "type": "node",
          "tag": "span",
          "children": "{{feature.description}}"
        }
      ]
    }
  ]
}

Nested Lists

Lists can be nested. A parent list's context is preserved in child lists through the named context system:

{
  "type": "list",
  "sourceType": "collection",
  "source": "categories",
  "children": [
    {
      "type": "node",
      "tag": "h2",
      "children": "{{category.name}}"
    },
    {
      "type": "list",
      "sourceType": "collection",
      "source": "posts",
      "filter": {
        "field": "category",
        "operator": "eq",
        "value": "{{category._id}}"
      },
      "children": [
        {
          "type": "node",
          "tag": "p",
          "children": "{{post.title}} in {{category.name}}"
        }
      ]
    }
  ]
}

In the inner list, both {{post.*}} and {{category.*}} are available.

Related Items (Exclude Current)

On a blog post template page, show related posts excluding the current one:

{
  "type": "list",
  "sourceType": "collection",
  "source": "posts",
  "excludeCurrentItem": true,
  "filter": {
    "field": "category",
    "operator": "eq",
    "value": "{{cms.category}}"
  },
  "limit": 3,
  "sort": { "field": "publishDate", "order": "desc" },
  "children": [
    {
      "type": "node",
      "tag": "a",
      "attributes": { "href": "{{post._url}}" },
      "children": "{{post.title}}"
    }
  ]
}

Next Steps

Building the future of digital experiences, one website at a time

© 2026 Company. All rights reserved.