PagibleAI JSON:API Navigation

Optimize your site's performance by retrieving your complete navigation structure—including breadcrumbs, sub-navigation menus, and mega menus - alongside your page content in a single, efficient request. The navigation items, represented as "navs," are streamlined versions of your pages. 

These "navs" exclude resource-intensive elements like content, configuration details, and meta fields, ensuring faster loading times. Furthermore, you have the flexibility to apply a distinct set of sparse fields to "navs" compared to full "pages," allowing for precise control over the data you retrieve and display, thus enhancing both speed and customization.

Complete navigation

Here's how to efficiently retrieve all the data you need to construct your site's navigation: breadcrumbs and multi-level menus, in a single request. Simply include ancestors and menu in the include parameter of your API request.

https://pagible.com/cms/pages/13?include=ancestors,menu

The ancestors parameter provides the data needed for breadcrumb navigation, while menu delivers the structure required for building comprehensive (mega) menus.

Breadcrumb

To create a breadcrumb navigation, you need to fetch all items from the current page up to the root page (the ancestors):

https://pagible.com/cms/pages/13?include=ancestors

Then, they are referenced in the relationships of the current page added in the included section of the response:

{
  "meta": {
    "baseurl": "https://pagible.com/storage/"
  },
  "jsonapi": {
    "version": "1.0"
  },
  "links": {
    "self": "https://pagible.com/cms/pages/13"
  },
  "data": {
    "type": "pages",
    "id": "13",
    "attributes": {
      "parent_id": 11,
      "lang": "en",
      "path": "json-rest-api",
      "name": "JSON REST API",
      "title": "PagibleAI JSON REST API",
      "theme": "",
      "type": "docs",
      "to": "",
      "domain": "",
      "has": true,
      "cache": 5,
      "createdAt": "2025-08-17T06:09:14.000000Z",
      "updatedAt": "2025-08-21T12:54:20.000000Z",
    },
    "relationships": {
      "ancestors": {
        "data": [
          {
            "type": "navs",
            "id": "1"
          },
          {
            "type": "navs",
            "id": "11"
          }
        ]
      }
    },
    "links": {
      "self": "https://pagible.com/cms/pages/13"
    }
  },
  "included": [
    {
      "type": "navs",
      "id": "1",
      "attributes": {
        "parent_id": null,
        "lang": "en",
        "path": "",
        "name": "Home",
        "title": "Pagible AI CMS - Next level content management!",
        "to": "",
        "domain": "",
        "has": true,
        "createdAt": "2025-07-29T09:00:58.000000Z",
        "updatedAt": "2025-08-22T09:28:04.000000Z"
      },
      "links": {
        "self": "https://pagible.com/cms/pages/1"
      }
    },
    {
      "type": "navs",
      "id": "11",
      "attributes": {
        "parent_id": 1,
        "lang": "en",
        "path": "documentation",
        "name": "Docs",
        "title": "Documentation",
        "to": "",
        "domain": "",
        "has": true,
        "createdAt": "2025-08-16T20:46:38.000000Z",
        "updatedAt": "2025-08-20T08:43:58.000000Z"
      },
      "links": {
        "self": "https://pagible.com/cms/pages/11"
      }
    }
  ]
}

The ancestors array within relationships reflects the hierarchical structure, listing items from the root of the site down to the parent of the current page. It essentially traces the path from the homepage to the page one level above the current one.

Children

To get all children of the requested page for navigation, add children to the include GET parameter:

https://pagible.com/cms/pages/1?include=children

The page child items are available in the included section of the JSON:API response:

{
  "meta": {
    "baseurl": "https://pagible.com/storage/"
  },
  "jsonapi": {
    "version": "1.0"
  },
  "links": {
    "self": "https://pagible.com/cms/pages/1"
  },
  "data": {
    "type": "pages",
    "id": "1",
    "attributes": {
      "parent_id": null,
      "lang": "en",
      "path": "",
      "name": "Home",
      "title": "Pagible AI CMS - Next level content management!",
      "theme": "",
      "type": "",
      "to": "",
      "domain": "",
      "has": true,
      "cache": 5,
      "createdAt": "2025-07-29T09:00:58.000000Z",
      "updatedAt": "2025-08-22T09:28:04.000000Z",
    },
    "relationships": {
      "children": {
        "data": [
          {
            "type": "navs",
            "id": "9"
          },
          {
            "type": "navs",
            "id": "11"
          },
          {
            "type": "navs",
            "id": "7"
          }
        ]
      }
    },
    "links": {
      "self": "https://pagible.com/cms/pages/1"
    }
  },
  "included": [
    {
      "type": "navs",
      "id": "9",
      "attributes": {
        "parent_id": 1,
        "lang": "en",
        "path": "demo",
        "name": "Demo",
        "title": "Demo",
        "to": "https://pagible.demo.aimeos.org/cmsadmin",
        "domain": "",
        "has": false,
        "createdAt": "2025-08-06T14:27:08.000000Z",
        "updatedAt": "2025-08-06T14:28:32.000000Z"
      },
      "links": {
        "self": "https://pagible.com/cms/pages/9"
      }
    },
    {
      "type": "navs",
      "id": "11",
      "attributes": {
        "parent_id": 1,
        "lang": "en",
        "path": "documentation",
        "name": "Docs",
        "title": "Documentation",
        "to": "",
        "domain": "",
        "has": true,
        "createdAt": "2025-08-16T20:46:38.000000Z",
        "updatedAt": "2025-08-20T08:43:58.000000Z"
      },
      "links": {
        "self": "https://pagible.com/cms/pages/11"
      }
    },
    {
      "type": "navs",
      "id": "7",
      "attributes": {
        "parent_id": 1,
        "lang": "en",
        "path": "code",
        "name": "Source Code",
        "title": "PagibleAI CMS Source Code",
        "to": "https://github.com/aimeos/pagible",
        "domain": "",
        "has": false,
        "createdAt": "2025-08-05T08:16:37.000000Z",
        "updatedAt": "2025-08-05T08:17:56.000000Z"
      },
      "links": {
        "self": "https://pagible.com/cms/pages/7"
      }
    }
  ]
}

Menu

Performance optimized

To retrieve the navigation for a complete menu up to the maximum tree level configured in ./config/cms.php, use include=menu:

https://pagible.com/cms/pages/1?include=menu

It can fetch multi-level trees in only one database request but requires rebuilding the tree structure by using the parent_id field of the included items:

function buildTree(nodes) {
  const map = {}; // id -> node
  const roots = [];

  // Create a map of id -> node, and prepare children arrays
  nodes.forEach(node => {
    map[node.id] = { ...node, children: [] };
  });

  // Link children to parents
  nodes.forEach(node => {
    if (node.parent_id === null) {
      roots.push(map[node.id]);
    } else {
      if (map[node.parent_id]) {
        map[node.parent_id].children.push(map[node.id]);
      }
    }
  });

  return roots;
}

const ids = response.data?.relationships?.menu?.data?.map(el => el.id) || [];
const nodes = response.included.filter(item =>
  item.type === "navs" && ids.includes(item.id)
);

const home = buildTree(nodes).shift();
home?.children.forEach(level1 => {
    level1.children.forEach(level2 => {
        // ...
    }
}

The response from the server in this case is similar to:

{
  "meta": {
    "baseurl": "https://pagible.com/storage/"
  },
  "jsonapi": {
    "version": "1.0"
  },
  "links": {
    "self": "https://pagible.com/cms/pages/1"
  },
  "data": {
    "type": "pages",
    "id": "1",
    "attributes": {
      "parent_id": null,
      "lang": "en",
      "path": "",
      "name": "Home",
      "title": "Pagible AI CMS - Next level content management!",
      "theme": "",
      "type": "",
      "to": "",
      "domain": "",
      "has": true,
      "cache": 5,
      "createdAt": "2025-07-29T09:00:58.000000Z",
      "updatedAt": "2025-08-22T09:28:04.000000Z",
    },
    "relationships": {
      "menu": {
        "data": [
          {
            "type": "navs",
            "id": "9"
          },
          {
            "type": "navs",
            "id": "11"
          },
          {
            "type": "navs",
            "id": "14"
          },
          {
            "type": "navs",
            "id": "13"
          }
        ]
      }
    },
    "links": {
      "self": "https://pagible.com/cms/pages/1"
    }
  },
  "included": [
    {
      "type": "navs",
      "id": "9",
      "attributes": {
        "parent_id": 1,
        "lang": "en",
        "path": "demo",
        "name": "Demo",
        "title": "Demo",
        "to": "https://pagible.demo.aimeos.org/cmsadmin",
        "domain": "",
        "has": false,
        "createdAt": "2025-08-06T14:27:08.000000Z",
        "updatedAt": "2025-08-06T14:28:32.000000Z"
      },
      "links": {
        "self": "https://pagible.com/cms/pages/9"
      }
    },
    {
      "type": "navs",
      "id": "11",
      "attributes": {
        "parent_id": 1,
        "lang": "en",
        "path": "documentation",
        "name": "Docs",
        "title": "Documentation",
        "to": "",
        "domain": "",
        "has": true,
        "createdAt": "2025-08-16T20:46:38.000000Z",
        "updatedAt": "2025-08-20T08:43:58.000000Z"
      },
      "links": {
        "self": "https://pagible.com/cms/pages/11"
      }
    },
    {
      "type": "navs",
      "id": "14",
      "attributes": {
        "parent_id": 11,
        "lang": "en",
        "path": "customize-theme",
        "name": "Customize Theme",
        "title": "Customize PagibleAI Theme",
        "to": "",
        "domain": "",
        "has": false,
        "createdAt": "2025-08-17T06:35:16.000000Z",
        "updatedAt": "2025-08-21T09:28:06.000000Z"
      },
      "links": {
        "self": "https://pagible.com/cms/pages/14"
      }
    },
    {
      "type": "navs",
      "id": "13",
      "attributes": {
        "parent_id": 11,
        "lang": "en",
        "path": "json-rest-api",
        "name": "JSON REST API",
        "title": "PagibleAI JSON REST API",
        "to": "",
        "domain": "",
        "has": true,
        "createdAt": "2025-08-17T06:09:14.000000Z",
        "updatedAt": "2025-08-21T12:54:20.000000Z"
      },
      "links": {
        "self": "https://pagible.com/cms/pages/13"
      }
    }
  ]
}

JSON:API aligned

An alternative is to use a different configuration and this request:

https://pagible.com/cms/pages/1?include=menu,menu.children

To make this work, you need to change these settings in the ./config/cms.php file:

  • jsonapi_maxdepth to 2
  • menu_maxdepth to 1

Then, you will get a list in included too but the sub-items are referenced in the relationships field and the json-api-model JS library automatically create a tree structure from the response:

import { Store } from 'json-api-models';

const models = new Store();
models.sync(response);

const home = models.findAll().shift();
home?.menu?.forEach(child1 => {
    child1.children.forEach(child2 => {
        // ...
    }
}

The response from the server to feed into the json-api-model library would be similar to:

{
  "meta": {
    "baseurl": "https://pagible.com/storage/"
  },
  "jsonapi": {
    "version": "1.0"
  },
  "links": {
    "self": "https://pagible.com/cms/pages/1"
  },
  "data": {
    "type": "pages",
    "id": "1",
    "attributes": {
      "parent_id": null,
      "lang": "en",
      "path": "",
      "name": "Home",
      "title": "Pagible AI CMS - Next level content management!",
      "theme": "",
      "type": "",
      "to": "",
      "domain": "",
      "has": true,
      "cache": 5,
      "createdAt": "2025-07-29T09:00:58.000000Z",
      "updatedAt": "2025-08-22T09:28:04.000000Z",
    },
    "relationships": {
      "menu": {
        "data": [
          {
            "type": "navs",
            "id": "9"
          },
          {
            "type": "navs",
            "id": "11"
          },
          {
            "type": "navs",
            "id": "14"
          },
          {
            "type": "navs",
            "id": "13"
          }
        ]
      }
    },
    "links": {
      "self": "https://pagible.com/cms/pages/1"
    }
  },
  "included": [
    {
      "type": "navs",
      "id": "9",
      "attributes": {
        "parent_id": 1,
        "lang": "en",
        "path": "demo",
        "name": "Demo",
        "title": "Demo",
        "to": "https://pagible.demo.aimeos.org/cmsadmin",
        "domain": "",
        "has": false,
        "createdAt": "2025-08-06T14:27:08.000000Z",
        "updatedAt": "2025-08-06T14:28:32.000000Z"
      },
      "relationships": {
        "children": {
          "data": []
        }
      },
      "links": {
        "self": "https://pagible.com/cms/pages/9"
      }
    },
    {
      "type": "navs",
      "id": "11",
      "attributes": {
        "parent_id": 1,
        "lang": "en",
        "path": "documentation",
        "name": "Docs",
        "title": "Documentation",
        "to": "",
        "domain": "",
        "has": true,
        "createdAt": "2025-08-16T20:46:38.000000Z",
        "updatedAt": "2025-08-20T08:43:58.000000Z"
      },
      "relationships": {
        "children": {
          "data": [
            {
              "type": "navs",
              "id": "13"
            },
            {
              "type": "navs",
              "id": "14"
            }
          ]
        }
      },
      "links": {
        "self": "https://pagible.com/cms/pages/11"
      }
    }
    {
      "type": "navs",
      "id": "13",
      "attributes": {
        "parent_id": 11,
        "lang": "en",
        "path": "json-rest-api",
        "name": "JSON REST API",
        "title": "PagibleAI JSON REST API",
        "to": "",
        "domain": "",
        "has": true,
        "createdAt": "2025-08-17T06:09:14.000000Z",
        "updatedAt": "2025-08-21T12:54:20.000000Z"
      },
      "links": {
        "self": "https://pagible.com/cms/pages/13"
      }
    },
    {
      "type": "navs",
      "id": "14",
      "attributes": {
        "parent_id": 11,
        "lang": "en",
        "path": "customize-theme",
        "name": "Customize Theme",
        "title": "Customize PagibleAI Theme",
        "to": "",
        "domain": "",
        "has": false,
        "createdAt": "2025-08-17T06:35:16.000000Z",
        "updatedAt": "2025-08-21T09:28:06.000000Z"
      },
      "links": {
        "self": "https://pagible.com/cms/pages/14"
      }
    }
  ]
}

Parent

The parent navigation node of the current page is included if you use include=parent:

https://pagible.com/cms/pages/1?include=parent

Then, the response contains a single navigation node if there's a parent:

{
  "meta": {
    "baseurl": "https://pagible.com/storage/"
  },
  "jsonapi": {
    "version": "1.0"
  },
  "links": {
    "self": "https://pagible.com/cms/pages/13"
  },
  "data": {
    "type": "pages",
    "id": "13",
    "attributes": {
      "parent_id": 11,
      "lang": "en",
      "path": "json-rest-api",
      "name": "JSON REST API",
      "title": "PagibleAI JSON REST API",
      "theme": "",
      "type": "docs",
      "to": "",
      "domain": "",
      "has": true,
      "cache": 5,
      "createdAt": "2025-08-17T06:09:14.000000Z",
      "updatedAt": "2025-08-21T12:54:20.000000Z",
   },
    "relationships": {
      "parent": {
        "data": {
          "type": "navs",
          "id": "11"
        }
      }
    },
    "links": {
      "self": "https://pagible.com/cms/pages/13"
    }
  },
  "included": [
    {
      "type": "navs",
      "id": "11",
      "attributes": {
        "parent_id": 1,
        "lang": "en",
        "path": "documentation",
        "name": "Docs",
        "title": "Documentation",
        "to": "",
        "domain": "",
        "has": true,
        "createdAt": "2025-08-16T20:46:38.000000Z",
        "updatedAt": "2025-08-20T08:43:58.000000Z"
      },
      "links": {
        "self": "https://pagible.com/cms/pages/11"
      }
    }
  ]
}

Subtree

Fetching a sub-tree starting from the current node is similar to fetching the menu but the pages are returned starting from the current node, not from the root node:

https://pagible.com/cms/pages/1?include=subtree

The response is like this:

{
  "meta": {
    "baseurl": "https://pagible.com/storage/"
  },
  "jsonapi": {
    "version": "1.0"
  },
  "links": {
    "self": "https://pagible.com/cms/pages/1"
  },
  "data": {
    "type": "pages",
    "id": "1",
    "attributes": {
      "parent_id": null,
      "lang": "en",
      "path": "",
      "name": "Home",
      "title": "Pagible AI CMS - Next level content management!",
      "theme": "",
      "type": "",
      "to": "",
      "domain": "",
      "has": true,
      "cache": 5,
      "createdAt": "2025-07-29T09:00:58.000000Z",
      "updatedAt": "2025-08-22T09:28:04.000000Z",
   },
    "relationships": {
      "subtree": {
        "data": [
          {
            "type": "navs",
            "id": "9"
          },
          {
            "type": "navs",
            "id": "11"
          },
          {
            "type": "navs",
            "id": "17"
          },
          {
            "type": "navs",
            "id": "14"
          }
        ]
      }
    },
    "links": {
      "self": "https://pagible.com/cms/pages/1"
    }
  },
  "included": [
    {
      "type": "navs",
      "id": "9",
      "attributes": {
        "parent_id": 1,
        "lang": "en",
        "path": "demo",
        "name": "Demo",
        "title": "Demo",
        "to": "https://pagible.demo.aimeos.org/cmsadmin",
        "domain": "",
        "has": false,
        "createdAt": "2025-08-06T14:27:08.000000Z",
        "updatedAt": "2025-08-06T14:28:32.000000Z"
      },
      "links": {
        "self": "https://pagible.com/cms/pages/9"
      }
    },
    {
      "type": "navs",
      "id": "11",
      "attributes": {
        "parent_id": 1,
        "lang": "en",
        "path": "documentation",
        "name": "Docs",
        "title": "Documentation",
        "to": "",
        "domain": "",
        "has": true,
        "createdAt": "2025-08-16T20:46:38.000000Z",
        "updatedAt": "2025-08-20T08:43:58.000000Z"
      },
      "links": {
        "self": "https://pagible.com/cms/pages/11"
      }
    },
    {
      "type": "navs",
      "id": "17",
      "attributes": {
        "parent_id": 11,
        "lang": "en",
        "path": "install-pagibleai-cms",
        "name": "Install PagibleAI",
        "title": "Install PagibleAI CMS",
        "to": "",
        "domain": "",
        "has": false,
        "createdAt": "2025-08-20T22:44:16.000000Z",
        "updatedAt": "2025-08-21T07:16:38.000000Z"
      },
      "links": {
        "self": "https://pagible.com/cms/pages/17"
      }
    },
    {
      "type": "navs",
      "id": "14",
      "attributes": {
        "parent_id": 11,
        "lang": "en",
        "path": "customize-theme",
        "name": "Customize Theme",
        "title": "Customize PagibleAI Theme",
        "to": "",
        "domain": "",
        "has": false,
        "createdAt": "2025-08-17T06:35:16.000000Z",
        "updatedAt": "2025-08-21T09:28:06.000000Z"
      },
      "links": {
        "self": "https://pagible.com/cms/pages/14"
      }
    }
  ]
}