Create Ghost Theme from scratch - Part 3: Search option

In the first part of my WordPress tutorial series, we learned how to install Ghost on a local machine and how to create and use a simple theme. In part two, we learned to set up navigation bar and pagination.

Create Ghost Theme from scratch - Part 3: Search option

In the first part of my Ghost tutorial series, we learned how to install Ghost on a local machine and how to create and use a simple theme. In part two, we learned to set up navigation bar and pagination.

In part three, we're going to learn how to add a search option to our theme.

Should I have a search option?

Search is an inevitable feature that every blog should have. It will be easy to find posts from a blog that has only a few posts. But for large websites or blogs with thousands of posts, it will be difficult for a user to find a post without search option.

Add search option to Ghost themes

In this post, I'll be using a free search library called ghost-search to add search option to our theme. You can download the library from the link given below.

HauntedThemes/ghost-search
A simple but powerful search library for Ghost Blogging Platform. - HauntedThemes/ghost-search

Step 1: Create a custom integration

Login to the Ghost admin dashboard and go to Integrations -> Add custom integration. Name the integration as Haunted Themes Search and copy the Content API Key.

Create a custom integration in Ghost

Step 2: Add Ghost content API

For the ghost search plugin to work, we should add Ghost content API JavaScript library to the theme just above the {{ghost_footer}} in default.hbs.

<script src="https://unpkg.com/@tryghost/content-api@1.3.3/umd/content-api.min.js"></script>

Step 3: Add search library

You can add search library to the theme either by adding it to the themes folder or using it from a CDM.

If you want to use CDN, just add the following link just above the {{ghost_footer}} in default.hbs.

<script src="https://cdn.jsdelivr.net/npm/ghost-search@1.0.1/dist/ghost-search.min.js"></script>

To add the library to your theme or you dont wat to use a CDN, create a folder named assets in the root directory of the theme. Then create a fonder named js under assets folder and place ghost-search.js there. This folder will hold all the JavaScript files of our theme.

I've add bootstrap.min.js, jquery.slim.js, popper.min.js (for bootstrap), ghost-content-api.min.js, and ghost-search.js (for ghost search) to the folder.

.
├── assets
│   ├── css
│   └── js
│       ├── bootstrap.min.js
│       ├── ghost-content-api-v1.js
│       ├── ghost-search.js
│       ├── jquery.slim.js
│       ├── main.js
│       └── popper.min.js

We can add reference to these files from the theme files with the help of {{asset}} helper. This helper makes sure that the relative path to an asset is always correct, regardless of how Ghost is installed.

{{asset 'path-to-the-asset'}}

Open deafult.hbs and add to following line just above {{ghost_footer}}.

<script src="{{asset 'js/ghost-search.js'}}"></script>

Here's my default.hbs file

<!doctype html>
<html lang="en">

<head>
    <title>{{meta_title}}</title>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
        integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">

    {{ghost_head}}

</head>

<body class="{{body_class}}">
<div class="m-5"></div>
    {{"navigation"}}

    {{!-- All the main content gets inserted here, index.hbs, post.hbs, etc --}}
    {{{body}}}

    <div class="card">
        <div class="card-footer text-muted">

            &copy; {{date format="YYYY"}} {{@site.title}}
        </div>
    </div>

    {{!-- Place search modal here --}}
    {{> "search"}}

    {{!-- Scripts --}}
    <script src="https://unpkg.com/@tryghost/content-api@1.3.3/umd/content-api.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/ghost-search@1.0.1/dist/ghost-search.min.js"></script>

    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
        integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
        crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
        integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
        crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
        integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
        crossorigin="anonymous"></script>
    {{!-- Uncomment to use offline
    <script src="{{asset 'js/ghost-content-api-v1.js'}}"></script>
    <script src="{{asset 'js/ghost-search.js'}}"></script>
    <script src="{{asset 'js/jquery.slim.js'}}"></script>
    <script src="{{asset 'js/popper.min.js'}}"></script>
    <script src="{{asset 'js/bootstrap.min.js'}}"></script> --}}

    {{ghost_foot}}
    
</body>

</html>

Note that I've  also added {{> "search"}} just above the scripts tag. We'll soon create create this file (search.hbs) under partials folder and will be used to display search results.

To add a Search box, open partials/navigation.hbs and modify it as shown below to add a search icon to the navigation bar.

<nav class="navbar navbar-expand-lg navbar-dark bg-primary fixed-top">
    <a class="navbar-brand" href="#">
        <img src="{{@site.logo}}" alt="{{@site.title}}" style="height: 30px; max-width: 150px;">
    </a>
    <button class="navbar-toggler hidden-lg-up" type="button" data-toggle="collapse" data-target="#collapsibleNavId"
        aria-controls="collapsibleNavId" aria-expanded="false" aria-label="Toggle navigation"></button>
    <div class="collapse navbar-collapse" id="collapsibleNavId">
        <ul class="navbar-nav mr-auto mt-2 mt-lg-0">
            {{#foreach navigation}}
            <li class="nav-item active">
                <a class="nav-item nav-link {{#if current}}active{{/if}}" href="{{url absolute="true"}}">{{label}}</a>
            </li>
            {{/foreach}}
        </ul>
        <div class="my-2 my-lg-0">
            <span data-toggle="modal" data-target="#modelId" class="fa fa-search"
                style="color: white; font-size: 25px;"></span>
        </div>
    </div>
</nav>

Step 5: Display search results

To display search results, create a new file name search.hbs under partials folder and add the following code to it.

<div class="modal fade" id="modelId" tabindex="-1" role="dialog" aria-labelledby="modelTitleId" aria-hidden="true">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">
                    Search
                </h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                {{!-- Search box --}}
                <input id="ghost-search-field" class="form-control" placeholder="Type here">
                
                {{!-- Area to display search result --}}
                <ul id="ghost-search-results"></ul>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
            </div>
        </div>
    </div>
</div>

It's just a bootstrap modal that will be displayed when the search icon is clicked.

The ghost-search library will, by default, show search results in the HTML element with id ghost-search-results.

Step 6: Initialize the library

You will need to initialize ghost-search to make the search functional. Add the following code to site footer from Ghost admin dashboard -> Code Injection -> Site footer.

<script type="text/javascript">
    let ghostSearch = new GhostSearch({
        key: 'place_the_content_api_key_generated_in_step_1_here',
        host: 'https://demo.ghost.io', //Replace with api url obtained in step 1
    })
</script>
We can also hardcode this in the theme. But, will not work with a different Ghost installation.

By default, ghost-search is showing the first 10 results and searches only based on title. Here's another example that displays search results based on title and content.

<script type="text/javascript">
    let ghostSearch = new GhostSearch({
        key: 'place_the_content_api_key_generated_in_step_1_here',
        host: 'https://demo.ghost.io', //Replace with api url obtained in step 1
        options: {
            keys: [
                'title',
                'plaintext'
            ],
            limit: 15,
            allowTypo: false
        },
        api: {
            resource: 'posts',
            parameters: { 
                fields: ['title', 'slug', 'plaintext'],
                formats: 'plaintext',
            },
        },
    })
</script>
Ghost theme with search

Happy coding. 👍


Share Tweet Send
0 Comments
Loading...