Skip to main content

Use TakeShape with Hugo

Adding TakeShape to your Hugo project couldn't be easier! With this doc, we'll take you through it step-by-step.

Getting an API Key#

You'll need to generate an API Key for your project, check out our docs that describe that process.

Getting your Project ID#

You can find your project’s ID in the lower-left corner of the dashboard in the web client.

Connecting your project#

If you already know your Project ID, and have access to an API Key with dev permissions (see our API Key docs for more information), then you're ready to get started!

Hugo has many ways to import data into its files and templates, but one of the simplest is with JSON. Add a JSON file to the data directory at the root of your project, and you'll be able to access that data in your templates with Hugo's variables.

The code to request data from a JSON file looks like this:

example.html
<h1>{{.Site.Data.YourJSONFileNameHere.SomeProperty}}</h1>

In order to get data from TakeShape, we're going to write a JavaScript file that makes an API call to your TakeShape project, and then creates JSON files from the response.

Protecting your project information#

To protect your project ID and API key from accidental exposure, we'll use environment variables. To use environment variables, you'll have to install the dotenv node package.

Go to the terminal in your project directory and enter npm i dotenv. With this installed, you can add environment variables to the script we're about to make.

Now in the root of your project directory, create a file called .env.

Inside, you will define your API Key and Project ID as variables like this:

.env
PROJECT_ID=YourProjectIdHere
API_KEY=YourApiKeyHere

Now you're ready to import data from TakeShape into your Hugo project.

Creating your TakeShape import script#

Installing the required node modules#

In order to add TakeShape to your Hugo build process, you need to run Hugo with NPM. If you don't already have it, check out this resource for installing and configuring NPM.

In the root directory of your Hugo project, run the npm init command to generate a package.json file.

Now create a JavaScript file in any directory of your project. You may name it what you want. For the purposes of this example, we'll create a buildscripts folder in the root directory, and add a file to it called takeshape.js

We are going to write a JSON file to the data directory of our Hugo project, so we'll next need to import Node's fs module.

takeshape.js
const fs = require('fs');

Next, we'll make a request to TakeShape to get the data we want. This request can be any valid query you've defined in your TakeShape Schema. Read our Schema docs for more information.

The endpoint for your project's API will be the standard TakeShape API endpoint, formatted as shown below:

https://api.takeshape.io/project/YOUR-PROJECT-ID}/v3/graphql

All you have to do is insert your Project ID into it. But remember not to paste this url directly into your code! You don't want to expose your Project ID to the public. Instead, we'll put the ID into the URL with environment variables.

If you want to use environment variables, install dotenv and add the code to configure it to the top of your script as shown below:

takeshape.js
require('dotenv').config();
const fs = require('fs');

You'll also need the node-fetch package in order to make fetch requests from your node script. Simply enter npm i node-fetch in your console. Then require it at the top of your script.

takeshape.js
require('dotenv').config();
const fs = require('fs');
const fetch = require('node-fetch');

Making the request to TakeShape#

You will need to make an asynchronous function for your code to run the fetch request to your project's API endpoint. Within this function, add a try/catch block to wrap your async code, and then use a string template to construct your API endpoint, using your project's ID as an environment variable.

takeshape.js
require('dotenv').config();
const fs = require('fs');
const fetch = require('node-fetch');
const getTakeShapeData = async () => {
try {
const takeShapeEndpoint = `https://api.takeshape.io/project/${process.env.PROJECT_ID}/v3/graphql`;
} catch (err) {
console.log("TakeShape pre build script failed!", err);
}
}
getTakeShapeData();

Next, we'll make a POST request to your API endpoint, and store the result. In the headers, set your Authorization to be a string template with the word Bearer, a space, and then your API key. In the body, you need to have a property of query in order for TakeShape to process your request. In the query property, pass a string that contains your query.

For this example, we'll assume you're accessing a database of books.

takeshape.js
const result = await fetch(takeShapeEndpoint, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.API_KEY}`,
accept: "application/json",
},
body: JSON.stringify({
query: `query {
getBookList {
items {
_id
author {
name
}
}
}
}`,
}),
});

Almost done! Convert the response from your request to JSON, then stringify the JSON.

takeshape.js
const resultJSON = await result.json();
const jsonString = JSON.stringify(resultJSON);

Finally, write this jsonString to a file in the data folder of your Hugo project. If anything fails here, you should throw an error so your overall try/catch block can catch it.

takeshape.js
fs.writeFile("./data/takeshape.json", jsonString, (err) => {
if (!err) {
return console.log("TakeShape pre build script succeeded!");
}
throw err;
});

If this process fails anywhere, the whole build will fail. This is because, as we mentioned earlier, you're going to integrate the data retreived from this request into your Hugo templates. If that data is not available at build time, the build will fail. This is why it's important to catch your possible errors here and either console.log() them or otherwise note them where they can be found.

Here is the entire script:

takeshape.js
const getTakeShapeData = async () => {
try {
const takeShapeEndpoint = `https://api.takeshape.io/project/${process.env.PROJECT_ID}/v3/graphql`;
const result = await fetch(takeShapeEndpoint, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.API_KEY}`,
accept: "application/json",
},
body: JSON.stringify({
query: `query {
getBookList {
items {
_id
author {
name
}
}
}
}`,
}),
});
const resultJSON = await result.json();
const jsonString = JSON.stringify(resultJSON);
fs.writeFile("./data/takeshape.json", jsonString, (err) => {
if (!err) {
return console.log("TakeShape pre build script succeeded!");
}
throw err;
});
} catch (err) {
console.log("TakeShape pre build script failed!", err);
}
}
getTakeShapeData()

Accessing your TakeShape data from your Hugo templates#

For a detailed breakdown of Hugo's templating language, please visit the Hugo docs.

To access the data received in the example code above, you would need a line of code similar to this:

homepage.html
{{$firstBook := index .Site.Data.takeshape.data.getBookList.items 0}}

Let's say we'd like to get the author of the first book in the list of books we've retreived from TakeShape. In the above code, we define $firstBook as a variable.

Because the books were returned in an array, we must use Hugo's index function, adding the position of the array that we would like to index at the end. This is why the code ends with a 0. We're accessing position 0 in the array.

The above code alone will not put the data we want into your HTML yet. It simply has assigned the book we want to a variable. To add any of its properties into our template, we must access them:

homepage.html
{{$firstBook := index .Site.Data.takeshape.data.getBookList.items 0}}
<h1>{{$firstBook.author.name}}</h1>

You will see the name of the author of the first book as an h1 on your homepage.

You're now free to access any TakeShape data you want from anywhere in your Hugo project!

To learn how to integrate this script into your build process, continue reading to the next section.

Adding your script to your build process#

In order to add TakeShape to your build process, you need to run Hugo with NPM. If you don't already have it, check out this resource for installing and configuring NPM.

In the root directory of your Hugo project, run the npm init command to generate your package.json file. Then open up the file in your favorite editor. We're going to edit the scripts section. Your package.json file may look like this:

package.json
{
"name": "takeshape-hugo-demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"preinstall": "npx npm-force-resolutions",
"start": "hugo server",
"build": "hugo -D",
"deploy": "hugo --minify"
},
"author": "",
"license": "ISC"
}

To start your Hugo server, configure the "start" property of the "scripts" object to be a string containing whatever console commands you need to run your dev server. To keep it simple, you could set that value to "hugo server", which is the default command.

Building your site is similar, except you'll edit the "build" property and set it to whatever commands you need to run in order to build. For simplicity, we'll use "hugo -D", the default command; but you should check the Hugo docs for more information on the different commands that are available to you.

The command you'll enter into the terminal to run your server is npm run start. To build your site, npm run build. This is equivalent to hugo server and hugo -D, except that NPM manages it, which allows us to specify pre- and post-scripts that need to be run.

In your package.json, in the scripts object, add two properties:

package.json
"prestart": "node ./buildscripts/takeshape.js",
"prebuild": "node ./buildscripts/takeshape.js",

The "prestart" and "prebuild" properties allow you to specify commands that must be executed immediately whenever npm run start or npm run build are called. These commands are executed prior to the commands defined in "start" and "build" respectively.

For this example, the commands we wish to execute before running our main "build" and "start" scripts is node, which should quickly execute a script we've created to pull information from TakeShape. You can name the script anything, and place it in any directory. Learn more about creating your script here.

Your Hugo build is ready!#

If you haven't already, be sure to read our docs on connecting a service to your project. You'll need a service to unlock the full power of using TakeShape's API Mesh to integrate multiple external API's into one elegant GraphQL API. After that, check out our docs on customizing your schema so you can craft your own queries and mutations.

Still confused? Ask for help!