How to use gatsby-source-takeshape to build a portfolio

Ibrahima Ndaw

JavaScript enthusiast, Full-stack developerβš›οΈ & bloggerπŸ“

Gatsby is a React-based framework for creating websites and apps. It helps you build blazing-fast static and dynamic sites. Gatsby allows you to integrate third-party services such as Content Management Systems (CMS). In this tutorial, I will show you how to use TakeShape as a CMS in your Gatsby site using gatsby-source-takeshape by building a Portfolio app. Let's get started!

What is TakeShape?

TakeShape is a set of services that powers Jamstack projects of any size or complexity. In this tutorial, I will use TakeShape’s GraphQL API and Editor UI as a CMS to manage portfolio content. This will allow us to query data from out Gatsby app.

Prerequisites

This tutorial assumes that you have basic experience with Gatsby and GraphQL. 

Setting up

To create a new Gatsby site, you need to open your command-line-interface (CLI) and run this command:

npx gatsby new gatsby-shape-gallery

This command will generate a new Gatsby project with the default starter. You can alternatively install the gatsby CLI and use the gatsby command to create a new project. 

To use TakeShape with Gatsby, we need to install the gatsby-source-takeshape plugin to be able to interact with the GraphQL API. Browse to the project folder and run this command in your CLI:

yarn add gatsby-source-takeshape

Or

npm install gatsby-source-takeshape

Now let's structure the project as follows:

β”œβ”€β”€ src
   β”œβ”€β”€ components
   |  β”œβ”€β”€ header.js
   |  β”œβ”€β”€ layout.css
   |  β”œβ”€β”€ layout.js
   |  β”œβ”€β”€ Project.js
   |  └── seo.js
   β”œβ”€β”€ images
   β”œβ”€β”€ pages
   |  β”œβ”€β”€ 404.js
   |  └── index.js
   β”œβ”€β”€ routes.js
   └── templates
      └── project-template.js
β”œβ”€β”€ gatsby-browser.js
β”œβ”€β”€ gatsby-config.js
β”œβ”€β”€ gatsby-node.js
└── gatsby-ssr.js

Here's break down the project’s file structure:

  • components/Project.js is the component that renders a single project.
  • routes.js contains a helper function that creates a slug for the path of each project, making it more user-friendly.
  • project-template.js is a template that allows the display of a full project.

With this in place, we can now create some projects on the TakeShape platform so we have data to work with.

Create the projects using TakeShape

To use TakeShape as a CMS, you will need to create an account (it's free). Once you are registered, start a new project.

Select Shape Portfolio as a pattern to seed the project with data and images.

Next, we need to generate the API keys that enable us to connect Gatsby to TakeShape. To do so, click on the dropdown menu and select 'API Keys'.

To generate the API keys, click on the New API Key button, set a name that suits you, and then make sure to select Dev on the Permissions field so the gatsby-source-takeshape plugin has the proper permissions. If you are seeing errors when you try to build you site, double check the API key permissions.
We now have the API keys required to retrieve data from TakeShape. In the next section we’ll build the Gatsby app.

Configuring gatsby-source-takeshape

First, we need to create a .env file to keep our credentials safe. If you’re committing your project to source control, like Github or Bitbucket, remember to add .env to your .gitignore  so you don’t accidentally add private keys to your repo.

.env


TAKESHAPE_PROJECT=<your-project-id>
TAKESHAPE_TOKEN=<your-api-key>

Replace the placeholder with your credentials. You can find the TAKESHAPE_PROJECT in the URL of your TakeShape project, or on the API Keys page in the endpoint URL.

gatsby-config.js

require(`dotenv`).config()

{
  resolve: `gatsby-source-takeshape`,
  options: {
    apiKey: process.env.TAKESHAPE_TOKEN,
    projectId: process.env.TAKESHAPE_PROJECT,
  },
},

We need to use environment variables to add the credentials to the config. You don't have to add a URL since the plugin handles everything automatically for you.

gatsby-node.js

const path = require(`path`)
const routes = require(`./src/routes`)

exports.createPages = async ({ actions, graphql }) => {
  const { data } = await graphql(`
    query {
      takeshape {
        projects: getProjectList {
          items {
            _id
            name
          }
        }
      }
    }
  `)

  data.takeshape.projects.items.forEach(({ _id, name }) => {
    actions.createPage({
      path: routes.projects(name),
      component: path.resolve(`./src/templates/project-template.js`),
      context: {
        projectId: _id,
      },
    })
  })
}

TakeShape uses the name of your content model (in this case β€œProject”) to create a GraphQL Type (projects) and then provide two GraphQL queries: one for retrieving all data (getProjectList) and another for getting a single object (getProject). 

At build time, Gatsby will query TakeShape to get the project list. Then, for each object, it will create a statically rendered page that allows the display of the full project with the template as a component.

We can now create the components and retrieve our data from TakeShape.

Creating the components

components/Project

import React from 'react'
import { Link } from 'gatsby'
import Img from 'gatsby-image'
import routes from '../routes'

const Project = ({ project }) => {
  const { name, coverImage, description } = project
  return (
    <Link to={routes.projects(name)} className='project-preview'>
      <Img
        className='project-preview--cover'
        style={{ width: '100%' }}
        fixed={coverImage.fixed}
        alt={description}
      />
      <h1 className='project-preview--title'>{name}</h1>
    </Link>
  )
}

export default Project

As you can see, we have a component that receives the fetched project as a parameter. With the project object available to our component, we’ll pull out the data we’d like to display and pass the name of the project to the routes helper method, which will create a slug.

templates/project-template.js

import React from 'react'
import { graphql } from 'gatsby'
import Img from 'gatsby-image'

import Layout from '../components/layout'
import SEO from '../components/seo'

const ProjectTemplate = ({ data }) => {
  const {
    takeshape: {
      project: { coverImage, name, description },
    },
  } = data
  return (
    <Layout>
      <SEO title={name} />
      <article className='project'>
        <header>
          {coverImage ? (
            <Img style={{ height: '22rem' }} fluid={coverImage.fluid} />
          ) : (
            ``
          )}
          <h1 className='project--title'>{name}</h1>
        </header>
        <div dangerouslySetInnerHTML={{ __html: description }} />
      </article>
    </Layout>
  )
}

export default ProjectTemplate

export const query = graphql`
  query($projectId: ID!) {
    takeshape {
      project: getProject(_id: $projectId) {
        name
        coverImage {
          description
          path
          fluid(maxWidth: 1200, maxHeight: 600) {
            ...GatsbyTakeShapeImageFluid
          }
        }
        description: descriptionHtml
      }
    }
  }
`

This query will return a single object from TakeShape. As previously mentioned, the id of the project will be provided to Gatsby automatically to generate individual pages. Next, we pass the fetched data to the ProjectTemplate component to display it.

We can now edit the index.js file to get the data from TakeShape when the page loads.

index.js

import React from 'react'
import { graphql } from 'gatsby'

import Layout from '../components/layout'
import SEO from '../components/seo'
import Project from '../components/Project'

const IndexPage = ({ data }) => {
  const {
    takeshape: {
      projects: { items },
    },
  } = data

  return (
    <Layout>
      <SEO title='Home' />
      <div className='project-container'>
        {items.map((project) => (
          <Project key={project._id} project={project} />
        ))}
      </div>
    </Layout>
  )
}

export default IndexPage

export const query = graphql`
  query {
    takeshape {
      projects: getProjectList {
        items {
          _id
          name
          startDate
          coverImage {
            description
            path
            fixed(width: 300, height: 200) {
              ...GatsbyTakeShapeImageFixed
            }
          }
        }
      }
    }
  }
`

As you can see, the query fetches all projects from TakeShape using GraphQL. Now we loop through the response data and for each project we use the Project component to display it.
With this in place, we can now test the app in the browser.

Testing the app

To preview the app in the browser, execute the following command on the CLI.

yarn start

For npm

npm start

Or when using Gatsby CLI

gatsby develop

Now let's visit on the browser http://localhost:8000/

And that's it! Our app is looking good!

We’ve built a nice looking portfolio site using Gatsby and TakeShape. You can find the finished code in this Github repo.

Conclusion

In this guide, we learned how to use TakeShape and Gatsby together with the gatsby-source-takeshape plugin to build a simple portfolio site. Give it try on your next project!

Resources

Check out these resources to dive deeper into the content of this tutorial:

TakeShape Docs

Gatsby TakeShape plugin

Gatsby Docs