Plug-in devs: include page setting?

For a while there’s been some confusion around the best way to create new standalone pages in a plug-in and link them from a blog’s navigation (Hugo menu). While @sod’s new Search Space plug-in is in beta, I thought this might be a good opportunity to revisit this question and see if anyone has feedback about improvements we could make.

To summarize, a plug-in can create new pages, and when it does it has the option to automatically include it in a menu using Hugo front matter, or leave it up to the user to create a page redirect. Including the page automatically is restrictive, but pages that redirect somewhere don’t have a good UI currently. (It requires adding the full URL as the page content.)

I can think of a few ways to solve this:

  • Improve the page/redirect UI. Maybe we should do this anyway.
  • Add a plug-in setting that will show a checkbox to include the page the plug-in provides in the menu.
  • Add a plug-in setting that exposes which pages it will create, and let provide some kind of UI for the user to choose from that when updating the navigation. Might be similar to how WordPress links to named pages in a menu.

Other ideas?


Also wanted to tag @amit because I think the Post Stats plug-in could also benefit from whatever we do here.

Oh, yes, I’m all for this! :blush: @manton and I talked about this over mail back in February. I’m including my initial letter here for a bit of background and my proposal for how this could work.

Hey Manton,

Here are my thoughts spurred by the discussion about pages from plug-ins in the menu. It makes sense to ship pages to the end-user for many plug-ins, like my own Surprise me!, Search page by renowned Manton Reece, and Amit’s Posts Stats.

Generally, people like stuff that “just works”. So I would gladly just tuck the Surprise me! page in the menu for them. Except I don’t, because:

  • What if the blog is in another language, and the owner wants to change the page name?
  • Or maybe they want to rearrange the order of the menu.
  • Some people don’t want that thing in the menu at all.

So instead, I just ship the page, and it’s up to the person installing the plug-in to add the page to the menu if they want. The problem is that’s not intuitive, and one might end up causing infinite redirect.

Maybe it could work like this? For example, plug-in developers adds the following frontmatter to their page:

title: "Surprise me!"
url: "/surprise-me/"
menu: "main"

The page automatically shows up in the page list and can be rearranged:

When the user taps on the page, they end up on an almost ordinary edit page:

This edit page differs from an ordinary edit page in a handful of ways:

  • The user is informed that this page is special, provided by the Surprise me! plug-in.
  • Because of that, the page can’t be deleted.
  • It can, however, be hidden from the menu.
  • It’s also possible to change the title…
  • and the path (technically, that’s the slug in the pages front matter).
  • For some plug-ins, it even makes sense to allow additional user content.

So in a way, it’s pretty similar to how special pages like About, Photos, and Replies work today. But sprinkled with more features. :blush:

1 Like

Here follows Manton’s feedback and my replies.

Not sure if it should remove the page or keep it, but we can work that out.

My gut tells me the page should disappear from the list. But it could be a soft delete. When someone troubleshoots a plug-in or starts from scratch (uninstalls everything), it’s nice if the old page bounces back. Especially if the person had additional content on the page.

But it might break expectations in some cases. Maybe these pages should have a Reset button instead of a delete button? When tapped, you delete the page from the database (is that how it works?) and create a new entry.

I’m also reworking the Archive and Photos pages so they are more similar to other pages, not using output formats, so all these might be good to release at the same time.

Could Archive and Photos be content of the default theme or a first-part plug-in? Maybe that’s what meant by rework. :blush: That way, you don’t need different implementations, and users will get the same experience for every special page in

Yeah, this is a much-needed improvement. I have got a lot of feedback about showing/hiding pages (those of plug-ins and non-plug-ins). So, we know there’s scope for improvement.

Specifically for plug-ins, I believe the plugin.json is the best place for such a setting as this information is for to identify a new page being added. Something on the lines of say.

"pages": [
] can then parse the page for details and populate it in the pages list. A user can then reorder or hide it. I like the flow proposed by @sod around this.

I think if I understand this right, it’s related to some challenges I’ve had in my theme that led to this template code that I barely remember writing in some kind of fugue state:

  {{ range $menuitem := .Site.Params.Menu }}
        <a class="{{ if eq .URL $url }}active{{ end }}"
           href="{{ index $menuitem "url" }}">
          {{ index $menuitem "name" }}
		{{ end }}
    {{ with site.Menus.main }}
      {{ range . }}
        <a class="{{ if eq .URL $url }}active{{ end }}" href="{{ .URL }}">
          {{ .Name }}
      {{ end }}
    {{ end }}

I did this to support generated pages while allowing my site config to set other menu items:

 "menu": [
        "name": "Now",
        "url": "/categories/now"
        "name": "Books",
        "url": "/bookshelf"
        "name": "Photos",
        "url": "/categories/photoblogging"
         "name": "Archive",
         "url": "/archive"

I have never loved this solution, and I also seem to remember trying to not override things quite this way, but having trouble plugging into where wanted me to store this information.

Overall, I think there should be something similar to the setup for custom JS or custom CSS:

{{- if isset .Site.Params "customjs" -}}
  {{- range .Site.Params.customJS }}
      <script src="{{ $.Site.BaseURL }}{{ . }}"></script>
  {{- end }}
{{- end }}

So a plugin can supply something that is merged into .Site.Params.customPages and perhaps there’s something else like .Site.Params.Pages for MB generated pages. This makes both sets of data easy to add to and easy to access for theme developers to support.

As a non-technical person who will not create a plugin but will always use interesting ones, I prefer this option.

Thanks y’all! And thanks @sod for digging up that email… I knew we talked about this somewhere, but forgot it was in email.

1 Like

I wonder if a “pages” field in the config.json would be necessary, since could just look at any file in “/contents”… If there wasn’t a “menu” field in the front matter, would ignore it for the purposes of the UI. It does require more parsing and fiddling with front matter than normally needs to do, though.

1 Like

Sure, it’s just cleaner if explicitly declared in plugin.json (dev focused) - of course, I didn’t mean in config.json, the user settings.

Thanks. Sorry, that was my typo… I meant plugin.json too.