DEV Community

Ayush Saran
Ayush Saran

Posted on • Edited on

Using 11ty and DecapCMS for 'non-blog' static websites -pt 1 Menus

While there are plenty of examples for using 11ty and Decap CMS in blog settings, I struggled to find a way to make it work for a non-blog static website.

Leaving these tips out on the internet for anybody else looking to do the same.

Making Menus editable in DecapCMS

To make menus that you can edit and update in DecapCMS you need to start with a collection in your config.yml file for DecapCmS [found under admin/config.yml]

mine looked like this:

collections:
  - name: Menus
    label: Menus
    files:
      - file: _data/mainMenu.json
        label: Main Navigation
        name: main-navigation
        extension: "json"
        format: "json"
        fields:
          - label: Primary Menu Items
            name: nav_items
            widget: list
            fields:
              - { label: Label, name: label, widget: string }
              - { label: Path, name: path, widget: string }
Enter fullscreen mode Exit fullscreen mode

The menu items are saved in a JSON file (mainMenu.json) as an object

{
  "nav_items": [
    {
      "label": "Products",
      "path": "/products"
    },
    {
      "label": "Solutions",
      "path": "/solutions"
    },
    {
      "label": "Success Stories",
      "path": "/successStories"
    },
    {
      "label": "Resources",
      "path": "/resources"
    },
    {
      "label": "About",
      "path": "/about"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

The file is placed in the '_data' directory in the root of the 11ty folder. This makes it accessible in templates as a Global Data File. See 11ty - Global Data Files

Then inside your template you can access this array and loop over the entries to output your links. I use EJS in my template, it looks like this:

   <ul class="menu">
        <!-- Load Nav items from mainMenu.json file -->
        <% for (let i=0; i < mainMenu.nav_items.length; i++) { %>
            <li><a href="<%= mainMenu.nav_items[i].path %>">
                    <%= mainMenu.nav_items[i].label %>
                </a></li>
            <% } %>
    </ul>
Enter fullscreen mode Exit fullscreen mode

You can also use this for Mega Menus, with nested lists

collections:
 - file: _data/footerMenu.json
        label: Footer Links
        name: footer-navigation
        extension: "json"
        format: "json"
        fields:
          - label: Footer Menu Items
            name: nav_items
            widget: list
            fields:
              - { label: Label, name: label, widget: string }
              - label: Links
                name: links
                widget: list
                fields:
                  - { label: Label, name: label, widget: string }
                  - { label: Path, name: path, widget: string }
Enter fullscreen mode Exit fullscreen mode

Notice the nested 'fields:' arrays in two levels

Then loop over them like this:

 <% for (let i=0; i < footerMenu.nav_items.length; i++) { %>
            <ul class="footer-links">
                <li class="title">
                    <h5>
                        <%= footerMenu.nav_items[i].label %>
                    </h5>
                </li>
                <% for (let j=0; j < footerMenu.nav_items[i].links.length; j++) { %>
                    <li><a href="<%= footerMenu.nav_items[i].links[j].path %>">
                            <%= footerMenu.nav_items[i].links[j].label %>
                        </a></li>
                    <% } %>
            </ul>
            <% } %>
Enter fullscreen mode Exit fullscreen mode

Top comments (0)