Nested menu structure

I am currently investigating if Storyblok is worth migrating to from our current outdated CMS.

Everything looks pretty good, but there is one thing that i can’t figure out. I don’t really see how you can make a parent/child menu structure. It looks like you can only add folders or content items, but you cannot nest these content items in a tree structure.

This could be solved by using a nestable component, but a nestable component for a big menu structure seems very difficult to maintain for content editors.

I would be suprised if there wasn’t a good solution for this, could someone please send me in the right direction ?

2 Likes

Hi,

i dealed with the same problem to build up a menu link structure with parent/child relationships.
I tried to explain it with some screenshots, but i have no permission to add any media or link to my post. I am sorry, for some reason the storyblok forum has very string permissions including very long waiting times until answers or posts get ‘approved’.

So describing it with text only, this is my solution:

  1. Go to components. Create a new component ‘navigationItem’. Choose nestable.

  2. Define the schema of that new navigationItem component. Add a name of type text input. A link of field type link and a block for children links.

  3. For the children Block edit schema and only allow specific components to be inserted. Select the navigationItem within the whitelist. Save schema.

  4. Next go to components. Create a new component navigation as content type, not nestable!

  5. Open this new content type component and define schema: add a block field type and name it for example navigationLinks.

  6. open this block and define schema. Here as well select “Allow only specific components to be inserted” and add the navigationItem to the whitelist.

  7. Next go to content and create a new content for example named navigation with content type navigation.

  8. Open this content type! Click on “Add block” of the navigation links block. One navigation item is added.

  9. when you open the navigationItem which is added you can define its values. Give it a name and a link. If this menu has child menu links, add them with the block, and so on. Now you can create a menu structure with endless nesting :wink:

  10. To show an example i created 2 menuItems. One of them with some children.

And this is the JSON output you get:

{
   "story":{
      "name":"navigation",
      "created_at":"2021-08-20T11:43:25.855Z",
      "published_at":null,
      "id":67383208,
      "uuid":"462d4130-0034-4e10-add3-07ca9842f2c4",
      "content":{
         "_uid":"c1a82981-c507-42a6-8f37-fa5e8d8c2190",
         "component":"navigation",
         "NavigationLinks":[
            {
               "_uid":"4dad47a0-6c71-4509-9021-f50d97d0c2d2",
               "link":{
                  "id":"cbeaa805-bb5d-4960-ba8b-35b40939b1c6",
                  "url":"",
                  "linktype":"story",
                  "fieldtype":"multilink",
                  "cached_url":"first-page"
               },
               "name":"My First Page",
               "children":[
                  
               ],
               "component":"navigationItem",
               "_editable":"\u003c!--#storyblok#{\"name\": \"navigationItem\", \"space\": \"123439\", \"uid\": \"4dad47a0-6c71-4509-9021-f50d97d0c2d2\", \"id\": \"67383208\"}--\u003e"
            },
            {
               "_uid":"3d09bf6c-a2c6-4536-880a-0467104ff5bc",
               "link":{
                  "id":"8250bb3d-34a3-4d69-8f13-6204ea8bc5d4",
                  "url":"",
                  "linktype":"story",
                  "fieldtype":"multilink",
                  "cached_url":"second-page"
               },
               "name":"My Second Page",
               "children":[
                  {
                     "_uid":"bd411504-3ed0-40ac-b471-f0faab8ecbff",
                     "link":{
                        "id":"501c4dfc-2b90-40b5-be77-0bec54107a07",
                        "url":"",
                        "linktype":"story",
                        "fieldtype":"multilink",
                        "cached_url":"first-child-page"
                     },
                     "name":"My First Child Page",
                     "children":[
                        
                     ],
                     "component":"navigationItem",
                     "_editable":"\u003c!--#storyblok#{\"name\": \"navigationItem\", \"space\": \"123439\", \"uid\": \"bd411504-3ed0-40ac-b471-f0faab8ecbff\", \"id\": \"67383208\"}--\u003e"
                  },
                  {
                     "_uid":"e801bd1d-3955-4eb6-885c-d634b45fa054",
                     "link":{
                        "id":"86cad6b4-2a6b-4e63-8cb0-5cbe00290e14",
                        "url":"",
                        "linktype":"story",
                        "fieldtype":"multilink",
                        "cached_url":"second-child-page"
                     },
                     "name":"My Second Child Page",
                     "children":[
                        
                     ],
                     "component":"navigationItem",
                     "_editable":"\u003c!--#storyblok#{\"name\": \"navigationItem\", \"space\": \"123439\", \"uid\": \"e801bd1d-3955-4eb6-885c-d634b45fa054\", \"id\": \"67383208\"}--\u003e"
                  }
               ],
               "component":"navigationItem",
               "_editable":"\u003c!--#storyblok#{\"name\": \"navigationItem\", \"space\": \"123439\", \"uid\": \"3d09bf6c-a2c6-4536-880a-0467104ff5bc\", \"id\": \"67383208\"}--\u003e"
            }
         ],
         "_editable":"\u003c!--#storyblok#{\"name\": \"navigation\", \"space\": \"123439\", \"uid\": \"c1a82981-c507-42a6-8f37-fa5e8d8c2190\", \"id\": \"67383208\"}--\u003e"
      },
      "slug":"navigation",
      "full_slug":"navigation",
      "sort_by_date":null,
      "position":-10,
      "tag_list":[
         
      ],
      "is_startpage":false,
      "parent_id":0,
      "meta_data":null,
      "group_id":"b7cb9903-9549-4d88-b659-d5f910f967f5",
      "first_published_at":null,
      "release_id":null,
      "lang":"default",
      "path":null,
      "alternates":[
         
      ],
      "default_full_slug":null,
      "translated_slugs":null
   },
   "cv":1629460332,
   "rels":[
      
   ],
   "links":[
      
   ]
}

I hope this was helpful somehow.
Best regards, Annick

2 Likes

Hello @t.rispens,

alternatively, you can use the links API which will give you the needed information for creating menu structures like the slug etc. Here is an example link object:

"7367d065-7499-411d-84c8-7141670e16c3": {
    "id": 18547341,
    "slug": "home",
    "name": "Home",
    "is_folder": false,
    "parent_id": 0,
    "published": true,
    "position": 10,
    "uuid": "7367d065-7499-411d-84c8-7141670e16c3",
    "is_startpage": false,
    "real_path": "/home"
}

When using the starts_with parameter you can get the link objects from the folder and its subfolders. More information is available here: Storyblok API Documentation

This article How to generate a Sitemap with a headless CMS? - Storyblok shows how you can create a sitemap. You can create similarly your own menu and filter in your implementation by the parent id for example to exclude items from the data that you retrieved from the links API.

Best regards
Hannes