One of the things I've taken for granted working with WordPress is the ability to implement multiple menus, and for each of those menus to have the capacity for sub-menus, sub-sub-menus, and so on.

Often these are drop-down style "superfish" menus. Some sites have "Mega-menus" which is another story and in a WordPress context is better achieved with a plugin that can organize that sort if thing.

Ghost has a bare-bones navigation module. It's a single menu with a single level. You can drag items around to re-order them, but there is no sub-menu involved.

Ghost Navigation Admin Interface

Googling for a sub-menu solution leads to a 2013 entry on the Ghost blog, when the navigation module was first released, that says: "Until now, you had to code navigation menus for Ghost directly into your theme - which was kind of a pain."

The implication being that the only way to do any menus before then was by hard-coding it into a theme. Hmmm. I don't like the idea of hard-coding the menu into a template file. That really is a pain.

But Ghost does provide an editor that makes it easy to create a page for which the content is a straight-up HTML list, and the handlebars templates make it pretty easy to grab a specific page's contents and insert them where needed. The implication is that you could have your theme look for certain page slugs where the content is the menu HTML and render them as a menu when they exist. Then changing the menu becomes a matter of simply editing the page rather than changing the template.

I tried it out and, with a little reading up on handlebars, had it working in about 20 minutes on my development installation.

The templating turns out to be fairly easy. For a main navigation it's simply:

{{#get "posts" filter="page:true+slug:main-nav" as |main_menu|}}

In the above snippet, we're saying:

Line 1: "We want to get an entry from the site's posts that has been set to a page, and where main-nav is the slug (the identifier string, usually the same as the page title in all lowercase and dashes replacing spaces). When you have that page, let's call it main_menu."

Line 2: "Using the main_menu data, insert the page contents." (Which we know is the menu's HTML).

Line 3: "We're done using the stuff from that page we got."

If you wanted a second menu, say a footer menu, create a second page with that second menu's list HTML and give it a different name, footer-menu, and pop the same snippet (with the appropriate slug) into whichever template file (probably default.hbs) that's handling your site footer. Same if you have a sidebar, or wherever.

That works. But it still feels like a bit of a hack. Ordinary users shouldn't have to worry about HTML. Even better would be to dig into the Ghost navigation module and extend it. But that's a project for another day!