In addition to providing your audience with a simple way to reach out to you, a contact page also protects your personal or company email from being exposed to spammers. Furthermore, a well designed contact form conveys what information you expect to be provided which hopefully results in more high quality requests.


This tutorial assumes that you already know how to get a Jamify site up and running. If this is not the case, please head over to our Getting Started tutorial.

You can either start from the base directory of your existing Jamify site or else clone the starter to create a playground for testing purposes. The latter approach is totally risk free and also great for this demo:

$ git clone jamify- contact
$ cd jamify-contact

The git clone command downloads the Jamify starter and puts it into a work directory named jamify-contact. The Jamify starter is a fully functional Gatsby site that is ready to source in all your content from a headless Ghost CMS. Without further configuration, it provides a demo site replicating the standard Ghost Casper theme.

Installing the Contact Page

With Jamify, adding a default contact page is as simple as adding a software package. Switch into your work directory and use the package manager yarn to add a contact page to your site:

$ yarn add gatsby-theme-ghost-contact

You could now run yarn develop in order to spin up the demo on localhost, but the contact page would be missing.

Why? As is the case with all Gatsby sites, you also need to add a little configuration to your gatsby-config.js:

// In your gatsby-config.js
plugins: [
        resolve: `gatsby-theme-ghost-contact`,

We will discuss more configuration settings below. For now, save these additions to gatsby-config.js and issue the development command:

$ yarn develop

Once the development build has finished, visit your demo site at http://localhost:8000. Now your site contains an additional menu item Contact which brings you to the newly added Contact page πŸ‘.

Looking at your Contact Page

Your contact page contains all the elements you would expect from a standard contact form: a title, a short introduction, a feature image and the contact form with a submit button.

As you can see, the contact page also integrates nicely into the existing page layout and contains a footer with some recent posts.

In addition to the standard form fields like name, email address and message area, we also provide an option field where your readers can select between different topics. If you do not want this field, it can be easily excluded by setting the form_topics field in the configuration to an empty array.

An invisible honey-spot field is also included, which provides some simple spam protection. If a bot fills out that field, the form data will never be sent to you.

Form validation

The form also performs some simple sanity checks, which ensure that you don't receive uncompleted data. These checks are hard-coded and cannot be changed, but they should be fairly reasonable.

  • Full Name: Number of characters must be in the range of 3 to 20.
  • Email: Must be a valid Email address.
  • Subject: A subject must be chosen, if configured.
  • Message: Number of characters must be in the range of 10 to 4000.

The subject validation does not apply, if you exclude this field as mentioned above.

Customizing your page

While you might be satisfied with most of the choices we made, a little customization is recommended in order to give your contact page a personal touch.

This is the fun part as you can do this with some simple configuration changes. I can't hold off in showing you a bit of customization here. Let's change the title, make the introduction a bit more elaborate and add another feature image from unsplash.

// In your gatsby-config.js
    resolve: `gatsby-theme-ghost-contact`,
    options: {
        pageContext: {
            title: `Contact Our Team`,
            custom_excerpt: `So you want to get in touch with us? Before you do, here are a few things you ought to know. We love to listen to your feedback and will get back to you as soon as we can, most likely within a few business days.`,
            feature_image: ``,

Putting these three simple changes into the configuration, and re-building your project with yarn clean; yarn develop yields the following results:

I'm sure you can't wait to make your own customizations!

Making the form functional

While you can fill out the form and press the Submit button, the message will not be sent anywhere.

The form must be connected to a back-end that listens for incoming requests, processes the data and performs some action, such as sending you and email notification or showing the requests in a dashboard.

You are free to select any back-end of your liking – no matter which one you choose, integrating with it should be straight forward. In the following, I'm going to present three popular options with increasing complexity.


This option is a great choice if you host your website with Netlify. If not, skip over to the next chapter. This is actually the easiest of the three options presented here as your contact form will be fully functional after your site has been deployed on their platform.

Important: You must submit the form from a Netlify deploy, testing it on localhost will not work!

If you do so, you will immediately start receiving messages with zero configuration!

How is this magic possible? Netlify analyses your forms during the deploy process and adds the needed configuration automatically during build time.

For this to work, the Jamify contact form has been designed to include all the necessary fields and attributes that Netlify is looking for. Read Netlify's form documentation, if you are interested to learn more about the details of this integration.


Getform is an external service which offers a free-plan as long as you only process one form and are satisfied with basic functionality. It is one of many service platforms which provide all the back-end handling for you, so it's a quick and convenient option.

Obviously, the drawback of Getform, Netlify and similar external services is that you give away sensitive visitors' data to a third party. If this is a concern (and it should be for production sites), look at the next option below.

Nonetheless, this is a perfect option for testing Jamify contact forms. To get started, register at the Getform website, create a new form on their dashboard, give it a name and take note of the generated action endpoint. The endpoint that was generated for this example has the following address:

Now you need to tell your Jamify form that it should connect to this endpoint. Guess what... this is just a simple configuration option that you need to add to gatsby-config.js:

// In your gatsby-config.js
    resolve: `gatsby-theme-ghost-contact`,
    options: {
        serviceConfig: {
            url: ``,
            contentType: `application/json`,
        pageContext: {

As you can see, I simply put the Getform endpoint into the url field and added the contentType within serviceConfig. That's all!

Rebuild the project, navigate to your Contact Page, enter some valid form data and press the Submit button. If everything works fine, you'll receive a message in your Getform dashboard:

If the Getform approach appeals to you, but are looking for other, similar services, Formspree may be an alternative for you.

Run your own micro-service

While the above options are perfectly suited for various test scenarios, production sites should be concerned about visitor's privacy. Your visitors may not like the idea that their names, email addresses and messages are visible to third parties like Getform, Netlify or Formspree.

Setting up your own service requires more skills, but it's the only option where you retain full control of your data. In order to give you a head start on this option and also to demonstrate that this is not as difficult as you might think, I'll show you a minimal implementation that actually works!

Start by cloning the following open-source repository which contains a basic contact form back-end written with Node.js and Express:

$ git clone jamify-svc
$ cd jamify-svc
$ sh

As I want the micro-service to send an email whenever someone submits the contact form, I am going to put an SMTP configuration into a file named .env which resides in the ghost-contact-form directory:
SMTP_PASS=strong password
.env file (replace variables with your own data)

You can inspect the micro-service code in ghost-contact-svc.js. With only 60 lines of code, the service listens on port 7000 for incoming POST requests on endpoint /v1/contact. If a request is received, the service performs some basic validations on the incoming data. Valid data will then be sent as an email to the address you provided in your .env configuration file.

Now you can fire up the service on the command line:

$ node ghost-contact-svc.js
Listening on http://localhost:7000

In production, you want to run this service behind a reverse proxy, such as Nginx. For now, you can test this service on localhost.

Leave the service up and running in one terminal window, so you can connect to it.

In another terminal, go to your work directory jamify-contact and add a serviceConfig similar to what you already saw earlier with Getform:

// In your gatsby-config.js
    resolve: `gatsby-theme-ghost-contact`,
    options: {
        serviceConfig: {
            url: `http://localhost:7000/v1/contact`,
            contentType: `application/json`,
        pageContext: {

Notice the new endpoint in the url field. Now its time to test your service.

Use Chrome for testing services on localhost. Unfortunately, Firefox sometimes issues CORS errors even though everything is setup correctly. This is only an issue on localhost and doesn't affect Firefox users on production sites where domain names are properly set.

Rebuild the Jamify contact page with yarn develop, hover over to the contact page, fill in the form and press Submit. If everything goes well, you'll see the message: Thank you, your message has been sent!

Now, checkout your EMAIL_TO inbox. You should have received a new message similar to the one below:

More resources

If you want to dig deeper into some of the topics presented here, there is more documentation available.

You can further customize your contact page with additional configuration options. A full description can be found in the readme of gatsby-theme-ghost-contact.

If you want even more flexibility, you can use component shadowing to overwrite only some parts of the theme. This is a great approach, if you want to fully customize the style or need more form fields. If this sounds still limiting, you can peak at the source code Β and make your own ghost-contact package.

When you decide to implement your own back-end, read this guide by DataFire on how to run your own service. Another nice overview about Building a Contact Form can be found on Gatsbyjs.

What you've learned

Congratulations πŸŽ‰ Not only have you added a contact page to your Jamify site, you also made some customizations to it to give it a personal look and feel.

Equally important, you learned about some commonly used back-end options and used them to make your contact page fully functional!

Do you want early access to Blogody, the brand new blogging platform that I am creating? Just sign-up on the new Blogody landing page and be among the first to get notified!