Elevating Gatsby Markdown Content Editing with TinaCMS

Gatsby has revolutionized the static site generation landscape, offering developers a flexible and powerful way to build websites. When combined with a headless CMS like TinaCMS, you can achieve a seamless content editing experience without sacrificing the performance benefits of a static site.

In this comprehensive guide, we‘ll dive deep into three methods for integrating TinaCMS with Gatsby to enable effortless Markdown content editing:

  1. remarkForm Higher Order Component – The go-to for Page Queries
  2. useLocalRemarkForm Hook – Ideal for Static Queries in functional components
  3. RemarkForm Render Props Component – Perfect for class components

Along the way, we‘ll explore the technical nuances, use cases, and expert tips for getting the most out of this powerful combination.

Why TinaCMS and Gatsby?

Before we jump into the technical details, let‘s consider why you might choose TinaCMS with Gatsby.

Gatsby excels at generating blazing-fast static websites by leveraging React, GraphQL, and the Jamstack architecture. It allows you to source content from a variety of origins, including Markdown files.

However, editing Markdown directly isn‘t always ideal for content creators. They may prefer a more user-friendly interface. This is where a headless CMS like TinaCMS shines.

TinaCMS provides an intuitive editing overlay that allows users to modify content directly on the page. It‘s open-source, lightweight, and developer-friendly. When paired with Gatsby, you get the best of both worlds: the performance of a static site and the ease of content editing.

As Nolan Phillips, co-founder of TinaCMS, explains:

"Gatsby and TinaCMS are a perfect match. Gatsby‘s component-based architecture makes it easy to integrate TinaCMS‘ editing capabilities, while TinaCMS‘ lightweight approach ensures your site remains fast and flexible."

Understanding Gatsby Queries

To understand which TinaCMS integration method to use, you first need to grasp Gatsby‘s two types of GraphQL queries:

  1. Page Queries – Can accept variables, but only work on page components.
  2. Static Queries – Don‘t accept variables, but can be used in any component.

The query type determines which TinaCMS approach you can use. Here‘s a quick comparison:

TinaCMS Integration Page Query Compatible Static Query Compatible
remarkForm HOC Yes No
useLocalRemarkForm Yes Yes
RemarkForm Yes Yes

As a general rule, use Static Queries with the useStaticQuery hook when possible for simplicity. If you need dynamic variables, use a Page Query.

Knowing this, let‘s explore each TinaCMS integration method.

1. remarkForm Higher Order Component

The remarkForm Higher Order Component (HOC) is the primary way to connect TinaCMS to a Page Query data source. Here‘s an example:

// 1. Import the `remarkForm` HOC
import { remarkForm } from ‘gatsby-tinacms-remark‘

const BlogTemplate = ({ data }) => {
  const { markdownRemark } = data
  return (
    <article>

      <div dangerouslySetInnerHTML={{ __html: markdownRemark.html }} />
    </article>
  )
}

// 2. Wrap your component with `remarkForm`
export default remarkForm(BlogTemplate)

// 3. Add the required ...TinaRemark fragment to your Page Query
export const query = graphql`
  query($slug: String!) {
    markdownRemark(fields: { slug: { eq: $slug } }) {
      html
      frontmatter {
        title
      }
      ...TinaRemark
    }
  }
`

Why use remarkForm? It provides the quickest setup for Page Query components. Remember, it won‘t work with Static Queries.

Advanced remarkForm Usage

remarkForm also accepts an optional config object for customizing the form:

export default remarkForm(BlogTemplate, {
  fields: [
    {
      label: "Title",
      name: "frontmatter.title",
      component: "text",
    },
    {
      label: "Body",
      name: "rawMarkdownBody",
      component: "markdown",
    },
  ],
})

This allows granular control over the fields displayed in the TinaCMS sidebar.

2. useLocalRemarkForm Hook

For Static Queries or a hook-based approach, useLocalRemarkForm is ideal:

// 1. Import the useLocalRemarkForm hook 
import { useLocalRemarkForm } from ‘gatsby-tinacms-remark‘
import { useStaticQuery } from ‘gatsby‘

const BlogPost = () => {
  // 2. Query your data with useStaticQuery
  const data = useStaticQuery(graphql`
    query {
      markdownRemark(fields: { slug: { eq: "my-post" } }) {
        html
        frontmatter {
          title
        }
        ...TinaRemark
      }
    }
  `)

  // 3. Call useLocalRemarkForm and pass in the data
  const [markdownRemark] = useLocalRemarkForm(data.markdownRemark)

  return (
    <article>

      <div dangerouslySetInnerHTML={{ __html: markdownRemark.html }} /> 
    </article>
  )
}

The useLocalRemarkForm hook returns a tuple with your Markdown data and the TinaForm object (useful for advanced customization).

While this example uses a hardcoded slug, you can easily switch to a Page Query for dynamic data.

3. RemarkForm Render Props Component

For class components, the RemarkForm render props component is the way to go:

import { RemarkForm } from ‘gatsby-tinacms-remark‘

class BlogPost extends React.Component {
  render() {
    return (
      <RemarkForm
        remark={this.props.data.markdownRemark}
        render={({ markdownRemark }) => (
          <article>

            <div
              dangerouslySetInnerHTML={{ __html: markdownRemark.html }}
            />
          </article>
        )}
      />
    )
  }
}

export const query = graphql`
  query($slug: String!) {
    markdownRemark(fields: { slug: { eq: $slug } }) {
      html
      frontmatter {
        title
      }
      ...TinaRemark
    }
  }
`

RemarkForm works with both Static and Page Queries since you pass the data directly via the remark prop.

Performance and Security Considerations

When integrating a CMS into your static site, performance and security are crucial. Fortunately, TinaCMS is designed with these in mind.

On the performance front, TinaCMS is lightweight and doesn‘t add significant overhead to your build process. It lazy-loads the editing interface, so it doesn‘t impact your site‘s initial load time.

From a security standpoint, TinaCMS runs entirely in the browser and doesn‘t require a backend server. This reduces the attack surface. However, it‘s still crucial to set up proper authentication and authorization to control who can edit your content.

TinaCMS integrates with various authentication providers and offers granular role-based access control. Spend time setting up these permissions properly.

Comparing TinaCMS to Alternatives

TinaCMS isn‘t the only headless CMS option for Gatsby. Other popular choices include Contentful, Strapi, and Sanity. So why choose TinaCMS?

The key differentiator is the developer experience. TinaCMS is designed to be developer-friendly and adaptable to your stack. It doesn‘t prescribe a specific backend or database.

As Scott Gallant, co-founder of TinaCMS, puts it:

"We built TinaCMS to be the most flexible and developer-friendly CMS possible. It‘s not an all-in-one solution, but rather a set of tools you can adapt to your needs."

This flexibility is powerful. You can use TinaCMS with your existing Markdown setup or even connect it to a third-party API if needed.

Real-World Example: Markdown Blog with TinaCMS and Gatsby

Let‘s walk through a real-world example: adding TinaCMS to a Gatsby Markdown blog for easy content editing.

1. Set up your Gatsby site and install dependencies

First, create a new Gatsby site and add the necessary dependencies:

gatsby new my-blog
cd my-blog
npm install gatsby-transformer-remark gatsby-source-filesystem gatsby-tinacms-remark gatsby-plugin-tinacms

2. Configure Gatsby to source Markdown files

In gatsby-config.js, add the following:

plugins: [
  {
    resolve: ‘gatsby-source-filesystem‘,
    options: {
      path: `${__dirname}/src/content/posts`,
      name: ‘posts‘,
    },
  },
  ‘gatsby-transformer-remark‘,
]

This tells Gatsby to source Markdown files from src/content/posts.

3. Create a Markdown post

Add a new Markdown file at src/content/posts/hello-world.md:

---
title: Hello World
date: ‘2023-05-23‘
---

This is my first blog post!

4. Create a blog post template

Create a new file at src/templates/blog-post.js:

import { graphql } from ‘gatsby‘
import { remarkForm } from ‘gatsby-tinacms-remark‘

const BlogPostTemplate = ({ data }) => {
  const { markdownRemark } = data
  return (
    <article>

      <div dangerouslySetInnerHTML={{ __html: markdownRemark.html }} />
    </article>
  )
}

export default remarkForm(BlogPostTemplate)

export const query = graphql`
  query($slug: String!) {
    markdownRemark(fields: { slug: { eq: $slug } }) {
      html
      frontmatter {
        title
        date
      }
      ...TinaRemark
    }
  }
`

This template uses the remarkForm HOC to connect to TinaCMS.

5. Create pages programmatically

In gatsby-node.js, add the following:

exports.createPages = async ({ actions, graphql, reporter }) => {
  const result = await graphql(`
    query {
      allMarkdownRemark {
        edges {
          node {
            fields {
              slug
            }
          }
        }
      }
    }
  `)

  if (result.errors) {
    reporter.panicOnBuild(‘Error creating pages‘)
    return
  }

  result.data.allMarkdownRemark.edges.forEach(({ node }) => {
    actions.createPage({
      path: node.fields.slug,
      component: require.resolve(‘./src/templates/blog-post.js‘),
      context: {
        slug: node.fields.slug,
      },
    })
  })
}

This code queries all Markdown files and creates a new page for each one using the blog-post template.

6. Enable the TinaCMS plugin

Finally, add the TinaCMS plugin to gatsby-config.js:

plugins: [
  // ...
  ‘gatsby-plugin-tinacms‘,
]

That‘s it! Run gatsby develop and navigate to http://localhost:8000/hello-world. You should see your blog post with the TinaCMS editing controls.

This is just a basic example, but it demonstrates the power and simplicity of integrating TinaCMS with Gatsby.

The Future of TinaCMS

As the Jamstack ecosystem evolves, so too does TinaCMS. One exciting development is the move towards visual page building.

The upcoming TinaCMS Inline Blocks feature will allow content editors to construct pages using predefined components. This brings the power of page builders to the headless CMS world.

Other planned enhancements include real-time collaboration, version control integration, and an improved media management experience.

Conclusion

TinaCMS and Gatsby form a powerful duo for creating static sites with a premium content editing experience. Whether you choose the remarkForm HOC, useLocalRemarkForm hook, or RemarkForm render props component depends on your needs, but all offer a seamless integration.

By understanding the nuances of Gatsby‘s data layer and TinaCMS‘ capabilities, you can craft a setup that‘s tailored to your project‘s requirements.

The future of web development is exciting, and tools like TinaCMS and Gatsby are leading the charge. Embrace the possibilities and happy coding!

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *