DEV Community

Ryan Feigenbaum
Ryan Feigenbaum

Posted on • Originally published at ryanfeigenbaum.com on

Supercharge Your Ghost Theme with Custom Settings

Supercharge Your Ghost Theme with Custom Settings

For theme developers, custom settings are cool as shit. Before, if you wanted to give users customization options, it usually required them to edit Handlebars files, inject JS or CSS, or some unholy mixture of the two. Now, you can empower a user to customize their theme easily without having them touch a line of code.

Release 4.20.0 · TryGhost/Ghost

That's one small commit for Ghost, one giant leap for Ghost theme developers. 😂

What type of customization are we talking about?

The only limit is your imagination, really, but you can solve some common pain points for users right out of the gate.

  • Are you going for a more classy, subdued look or do you want the ecstatic irreverence of Lisa Frank? It's your choice–all from the comfort of a color-palette dropdown.
  • Do you not know better and want to enable comments on your site? Enter a bit of info and now you can hear random people's thoughts.
  • Want to get those follows? Easily add your socials to the navbar.
  • Not interested in Ghost's member functionality? Toggle it on, toggle it off.
  • Want this a little bigger or that a little smaller? Customized layouts are only a few clicks away.
  • And more...

OK, now I want to do it. Tell me how

Implementing custom settings requires two things:

  1. An entry in the theme's package.json file
  2. Reference to the setting in the theme file

Once these are in place, the user can make their customizations via the Design menu in the Ghost Admin.

Supercharge Your Ghost Theme with Custom Settings
Example of custom settings on the Ghost Admin page

To begin, add a custom key to the config object in your package.json file.

{
 "config": {
    "posts_per_page": 10,
    "image_sizes": {

    },
    "custom": {

    }
  }  
}    
Enter fullscreen mode Exit fullscreen mode

Custom settings in package.json

Within the custom object, you can then define the name of your custom setting. Names must be in snake_case with lowercase letters. Underscores (_) are replaced by spaces in the UI.

For each setting, you can specify one of five types and where appropriate a default value.

  1. select: choose from a list of predefined items
  2. boolean: true or false
  3. color: choose a color via a color picker
  4. image: upload an image
  5. text: enter an arbitrary bit of text

In addition to custom setting types, you can also specify a group. By default, custom settings will appear in the site-wide group. If the setting affects the entire site, like defining a color scheme, then this default works. However, you can also assign custom settings to only appear in the post or homepage toggle menus. A post setting might be the ability to switch on syntax highlighting, whereas a homepage setting might be the ability to specify the hero image's size.

When you put this all together, your entry in your package.json looks like this:

{
    "config": {
        "custom": {
            "color_scheme": {
                "type": "select",
                "options": ["Smart", "Material", "Gruvbox", "Dracula", "Nord"],
                "default": "Smart"
            },
            "cta": {
                "type": "text",
                "group": "homepage"
            },
            "syntax_highlighting": {
                "type": "boolean",
                "default": "false",
                "group": "post"
            },
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Custom settings example in package.json

Custom settings are great and all, but before you come up with a list of 1,001 options that will take your user a year to read, please note that custom settings are limited to 15.

Give me the custom settings data, please

So far, we've defined our custom settings, which will show them as options on the Design page. But how do we access this data in the theme?

Values are accessible via your theme's Handlebars markup. For example, let's say you had a text custom setting called cta that allows a user to write a custom call to action. In your theme file, you would access it with {{@custom.cta}}.

This @custom object is new to Ghost. You can access a specific custom setting key in your template to render the value or use the object with other Ghost Handlebars helpers for more complex logic.

Let's take a look at how you'd implement the three custom settings above in Handlebars.

Color Scheme

First, create a Handlebars partial that contains each of the color palettes you want to use. Here, I'm using a style tag in conjunction with CSS custom properties. It's custom custom, baby.

{{#match @custom.color_scheme "smart"}}
  <style>
    :root {
      --primary: #0d48a0;
      --surface: #e0e5eb;
      --text: #040506;
      }
  </style>
{{/match}}

{{#match @custom.color_scheme "material"}}
  <style>
    :root {
      --primary: #0277bd;
      --surface: #eee;
      --text: #111;
      }
 </style>
{{/match}}
Enter fullscreen mode Exit fullscreen mode

Partial file: color_scheme.hbs

You'll also notice the new #match helper. The default behavior, as used here, is to match the custom setting value to the specified string. So, if the user chooses the material theme, then the #match helper will show those CSS values only.

The final piece of the puzzle here is to load the color_scheme.hbs partial in the <head> tag of your default.hbs file.

Now the user can drastically change the look of their site with the flip of a switch, and you only have to build a single theme. Pretty cool.

CTA

The CTA custom setting will render the user-specified text wherever you invoke the value. Here, I'll use it on a custom homepage.

<section class="homepage-cta">
  <h1>{{@site.title}}</h1>
  {{#if @custom.cta}}
    <p>{{@custom.cta}}</p>
  {{/if}}
</section>
Enter fullscreen mode Exit fullscreen mode

home.hbs

The #if block checks whether the user entered custom text. If not, then the <p> isn't rendered at all.

Otherwise, the user can wordsmith till the cow's come home and their copy will be dutifully updated on the homepage with every save.

Syntax Highlighting

When including code in a post, it's nice if that code has syntax highlighting (where words are given different colors depending on their meaning). To implement this, you need to use a third-party library like Prism or highlight.js.

However, not all users need syntax highlighting, so it would be best to only load those libraries for users who opt in.

{{#contentFor "head"}}
  {{if @custom.syntax_highlighting}}
    <link rel="stylesheet" href="syntax-highlight.css"> 
    <script src="syntax-highlight.js" defer></script>
  {{/if}}
{{/contentFor}}
Enter fullscreen mode Exit fullscreen mode

post.hbs

The code here uses the contentFor helper in conjunction with the syntax highlighting custom setting to only load the syntax highlighting JS and CSS based on the user's needs. For those who don't need it, you save them from loading unnecessary libraries. 💪

Smart 2: Custom settings preview

I'll soon launch version 2 of my open-source Smart theme, filled to the brim with custom settings. (My partner, Maddie, is currently rocking version 1.)

Some of the things I'm bringing to the theme:

Custom Setting Purpose
Search key Enter your API key to enable search
Comments Enable Disqus comments
Hero size Control the size of the hero image
Members Add in extra member functionality or disable it entirely
Color schemes Choose from several color schemes 💅
Post width Define your default post width
Social media icons Add additional social media icons to the navbar
Custom CTA text Add custom text to the homepage

Custom settings open up the possibilities for Ghost theme development exponentially, improving the user and developer experience alike.

For inspiration on what you can do with custom settings, I recommend checking out the official Ghost repo to see some of the creative mischief they have already gotten up to (for example, with Wave, Alto, and the OG Casper).

OK, byeee 👋

Top comments (0)