Developer docs

Custom settings

Custom theme settings are a powerful tool that allows theme developers to configure custom settings that appear in Ghost Admin — making it easy for site owners to make stylistic choices without needing to edit theme files.

Overview

Custom theme settings are specified by the theme developer in the package.json file at the config.custom key, and there are five types of custom theme settings available:

  • select
  • boolean
  • color
  • image
  • text
{
    "config": {
        "custom": {
            "typography": {
                "type": "select",
                "options": ["Modern sans-serif", "Elegant serif"],
                "default": "Modern sans-serif"
            },
            "cta_text": {
                "type": "text",
                "default": "Sign up for more like this",
                "group": "post"
            }
        }
    }
}

Once defined in the package.json file, custom settings can be accessed in Handlebars templates using the @custom object.

<body class="{{body_class}} {{#match @custom.typography "Elegant serif"}}font-alt{{/match}}">
    ...
    <section class="footer-cta">
        {{#if @custom.cta_text}}<h2>{{@custom.cta_text}}</h2>{{/if}}
        <a href="#portal/signup">Sign up now</a>
    </section>
</body>

Themes are limited to a total of 15 custom settings. See the usage guidelines for details on the most effective ways to use custom settings.

Setting keys/names

The key given to each setting is used as the display name in Ghost Admin, and as the property name on the @custom object.

{
    "config": {
        "custom": {
            "cta_text": {
                "type": "text",
                "default": "Sign up for more like this",
                "group": "post"
            }
        }
    }
}

In this example, the "cta_text" key is displayed to site owners as CTA Text and can be referenced in Handlebars templates using @custom.cta_text.

Text Custom Setting

Setting keys must be all lowercase with no special characters and in snake_case where each space is represented by an _.

Changing a setting’s key when releasing a new theme version is a breaking change for site owners who upgrade from an older version. The setting with the old key is removed, losing any value entered by the site owner, and a new setting with the current key is created with its default value.

Setting groups

Custom theme settings are grouped into one of three categories in the Admin UI:

  • Site-wide
  • Homepage
  • Post

Setting groups

By default, all custom settings appear in the Site-wide category. Custom settings that are specific to the homepage or post display are defined with an optional "group" property with the value "homepage" or "post".

{
    "config": {
        "custom": {
            "typography": {
                "type": "select",
                "options": ["Modern sans-serif", "Elegant serif"],
                "default": "Modern sans-serif"
            },
            "feed_layout": {
                "type": "select",
                "options": ["Dynamic grid", "Simple grid", "List"],
                "default": "Dynamic grid",
                "group": "homepage"
            },
            "cta_text": {
                "type": "text",
                "default": "Sign up for more like this",
                "group": "post"
            }
        }
    }
}

Settings should be organized into groups that will make sense for site owners based on your usage of the setting in the theme.

Setting types

Each of the five custom setting types has particular fields and requirements.

All custom settings require a valid "type" — an unknown type causes a theme validation error.

Select

Presents a select input with options defined by the theme developer.

Select settings are used to offer site owners multiple predefined options in combination with the match helper:

"feed_layout": {
    "type": "select",
    "options": ["Dynamic grid", "Simple grid", "List"],
    "default": "Dynamic grid"
}
{{#match @custom.feed_layout "Dynamic grid"}}
    //
{{/match}}

Select Custom Setting

Validation

  • options is required and must be an array of strings
  • default is required and must match one of the defined options

Boolean

Presents a checkbox toggle.

"recent_posts": {
    "type": "boolean",
    "default": true
}

Boolean Custom Setting

Validation

  • default is required and must be either true or false

Boolean settings can simply be used with the {{#if}} helper:

{{#if @custom.recent_posts}}
    //
{{/if}}

Color

Presents a color picker.

"button_color": {
    "type": "color",
    "default": "#15171a"
}

Color Custom Setting

Validation

  • default is required and must be a valid hexadecimal string

Use the color setting value in the theme by accessing the custom setting directly.

<style>
    :root {
        {{#if @custom.button_color}}
        --button-bg-color: {{@custom.button_color}};
        {{/if}}
    }
</style>

Image

Presents an image uploader. When output in themes, the value will be blank or a URL.

"cta_background_image": {
    "type": "image"
}

Image Custom Setting

Validation

  • default is not allowed

Use the image setting value in the theme by directly accessing the setting, or use with the {{img_url}} helper. You can pass in dynamic image sizes, if you would like to output the image in question at a resized resolution based on your theme config.

<section class="footer-cta" {{#if @custom.cta_background_image}}style="background-image: url({{@custom.cta_background_image}});"{{/if}}>
    ...
</section>

// or
<img src="{{img_url @custom.cta_background_image size="large"}}" />

Text

Presents a text input. The value may be blank or free-form text.

"cta_text": {
    "type": "text",
    "default": "Sign up for more like this."
}

Text Custom Setting

Validation

  • default is optional

Remember to allow a use case with no text. For example, this link will only be displayed if text has been provided:

{{#if @custom.cta_text}}
    <a href="#/portal/signup">{{@custom.cta_text}}</a>
{{/if}}

Fallback settings

Regardless of the Ghost version, themes providing custom settings shouldn’t look broken, and should provide a fallback when necessary.

Creating fallbacks for text settings

The default text for a text setting should be specified in package.json instead of adding it in the theme code as a fallback. This allows your theme to handle blank strings in the correct way:

"cta_text": {
    "type": "text",
    "default": "Sign up now."
}
{{#if @custom.cta_text}}
    <h2>{{@custom.cta_text}}</h2>
{{/if}}

The only exception is when the theme must have text for a specific setting. In this situation, the default should be added in the theme as a fallback with an {{else}} statement:

<h2>
  {{#if @custom.copyright_text_override}}
		{{@custom.copyright_text_override}}
	{{else}}
		{{@site.title}} © {{date format="YYYY"}}
	{{/if}}
</h2>

Guidelines for theme developers

Custom settings should compliment the primary use case of the theme

Ghost Themes should always have a very clear use case and the implementation of custom settings should compliment that use case. For example, a theme that is designed for newsletters may have custom settings to make visual changes to button colors and typography, but shouldn’t include custom settings to turn the theme into a magazine layout.

Simple visual changes — give site owners the ability to create a great visual impact without altering the primary use-case of the theme. For example, changing colors, fonts and images.

Complex layout settings — using custom settings to alter the primary use case of the theme results in complicated code that is harder to manage in the future.

Custom settings should have a very clear visual impact

Custom settings are designed to allow site owners to make meaningful customizations to their theme, without needing to edit theme files or inject code.

The total number of settings is limited to 15!

Use your custom settings wisely to give publishers the tools they need to define the best visual fit for their brand.

Visual brand settings — use custom settings to make brand adjustments that have a visual impact, such as changing the color of all buttons, changing the default CTA text on the homepage, or offering a dark mode toggle.

Repeated settings — avoid using custom settings to make micro-adjustments to single elements of a theme, such as individual buttons.

Functional settings — avoid using custom settings to change the way a theme functions, such as changing the pagination style, or removing the primary tag from posts — these are functional settings that should be determined based on the primary use case of the theme.

Using custom settings for external integrations

It’s possible to use custom settings to enable third-party integrations within your theme, such as commenting systems or website analytics. To use custom settings for this purpose, site owners should be asked to enter a simple piece of information such as a tracking ID, rather than adding HTML code into a custom text setting.

✅ Enter a Disqus shortname into a custom setting, and enabling the comment system only when the shortname is provided

✅ Enter a tracking ID into a custom setting, and enabling Google Analytics only when the ID is provided

❌ Ask users to add an embed code into custom settings to make an integration function.