Cloudinary Blog

Dynamically Fetch Data in Jamstack Sites With Hasura

By Obinna Ekwuno
How to Dynamically Fetch Data in Jamstack Sites With Hasura

The Jamstack web-development architecture yields many benefits, including high performance and security. Plus, thanks to its APIs, which function as software as a service (SaaS), no back-end infrastructure is required for web applications.

The rise of platforms as a service (a type of SAAS) has rewarded the front end with a lot of autonomy. Even though Jamstack front ends are mostly associated with static site generators like Next.js, Gatsby, and Nuxt.js, I strongly believe that any application that contains a self-sustainable front end and that leverages APIs for specific purposes qualifies as a Jamstack front end. So, it can be a simple project coded with HTML, CSS, and logic.

Many front-end developers relish building stand-alone applications but must answer several questions at the outset, such as where to get the related data and how to authenticate it. Above all, if a PostgreSQL database already exists, how to connect it to the new Jamstack front end? is a silver bullet of a solution.

Understanding Hasura

As defined on GitHub, Hasura is a superfast GraphQL server that “gives you instant, real-time GraphQL APIs over Postgres, with webhook triggers on database events and remote schemas for business logic.” You want to give the front end all the autonomy it needs, e.g., where to source data and how to structure and handle that data.

Data in Jamstack applications can usually originate from any source, e.g., one or multiple content management systems, assuming that you’re using a framework like Gatsby or connecting to an existing database like Postgres with Hasura.

Below is a demo that shows you how to use Hasura to connect and fetch data to an application built with HTML.

Setting Up Hasura

  1. Create a Hasura account and sign in.
  2. Click Try a free database with Heroku.

Sign up for Hasura

Next, click the DATA tab at the top and then click Create Table.

GraphQL Schema

Assign types to your parameters, that is, define the data you want your queries to return on the front end and the data types.

GraphQL data

Connecting Hasura to Applications With Utility Functions

Now connect the database to the sample application with the following:

  • Two environment variables, which link your Hasura account and database with your application so that you can query for data from there.
  • A utility function, which enables interactivity in the application.
  • A serverless function. For an explanation of this function type, see the post Serverless Functions Deliver Dynamism to Static Sites.

Do the following:

  1. Log in to Hasura cloud and go to
  2. Note the values of the two environment variables: HASURA_API_URL and HASURA_ADMIN_SECRET.

    Copy to clipboard
    HASURA_API_URL = xxxxxx
  3. Create a functions directory in the root of the application with a folder called utils.js, in which in turn create a file called hasura.js that contains the code below. Be sure to replace HASSURA_API_URL and HASURA_ADMIN_SECRET with their values.

Copy to clipboard
const fetch = require('node-fetch')
async function query({query,variables = {}}) {
    const result  =await fetch(process.env.HASURA_API_URL,{
        method: 'POST',
        headers: {
            'X-Hasura-Admin-Secret': process.env.HASURA_ADMIN_SECRET,
    .then((response)=> response.json());

    //To do: check for errors and show errors

exports.query = query

The above code posts queries to your Hasura workspace with the fetch API and then exports a query function with which you can extract data from your database.

Querying for Data in Components

Finally, connect a query to the application with a Netlify serverless function. In the functions directory, create a file called add-project.js with the code below, which imports the query function that enables you to write the GraphQL query generated in Hasura.

Copy to clipboard
const { query } = require("./util/hasura");
exports.handler = async (event) => {
    const result = await query({
        query: `
        query {
          projects {


Extracting Data in a Form With the Serverless Function

You can now use the serverless function to get data from a form. See the code below. Once the body is posted, it sends several parameters (id, title, etc.) to the serverless function for a response.

Copy to clipboard
async function handleSubmit(event) {
    event.preventDefault(); // stops the submit from firing before the function runs 
  const data = new FormData(; //formdata API
  const result = await fetch('/.netlify/functions/add-project', {
    method :'POST',
      body: JSON.stringify({
        id: data.get('id'),
        title: data.get('title'),
        tagline: data.get('tagline'),
        project: data.get('project'),
  }).then((response) => {
        ).innerText = `Response: ${response.status}`;

Getting Uniform Images From the Form

For a consistent display, you’d want the images in the forms to have the same resolutions before being stored in your Cloudinary account’s Media Library in Cloudinary-generated URLs. Toward that end, leverage the Cloudinary capability called incoming transformations, which modifies images during or after their upload.

Do the following:

  1. From your Cloudinary account’s dashboard, grab your Cloudinary name, API key, and API secret and store them as environment variables in a file called .env (see the example below) in the project’s root directory.

    Copy to clipboard
  2. Create a utility function with the code below. Be sure to replace LOUDINARY_NAME, CLOUDINARY_API_KEY, and CLOUDINARY_API_SECRET with their values.

Copy to clipboard
const cloudinary = require("cloudinary").v2;
const dotenv = require("dotenv");

  cloud_name: process.env.CLOUDINARY_NAME,
  api_key: process.env.CLOUDINARY_API_KEY,
  api_secret: process.env.CLOUDINARY_API_SECRET

// When doing a signed upload, you'll use a function like this one:
exports.handler = async event => {
  const { project } = JSON.parse(event.body);
  const res = await cloudinary.v2.uploader.upload(project, { width: 2000, height: 1000, crop: "limit" },
  function(error, result) { console.log(result, error); });
  return {
    statusCode: 200,
    body: JSON.stringify(res)

This function adds a preset, which limits the dimensions of an uploaded image to a maximum width of 2,000 pixels and a maximum height of 1,000 pixels.

You can apply more transformations to the uploaded images or generate assets derived from the originals with other Cloudinary features, such as eager transformation.

Opening the Door to Dynamism

With Hasura, you can build numerous dynamic capabilities for Jamstack sites. Let your creativity soar!

Recent Blog Posts

Shoppable Video Is Becoming Popular in E-Commerce

As pandemic restrictions necessitated, many shopping trips in 2020 took place outside the traditional brick-and-mortar store, or at least void of the physical aisle-browsing experience. Same-day curbside pickup became a safe and convenient alternative, and e-commerce transactions skyrocketed as consumers shopped online. In fact, Digital Commerce 360 estimates that, compared to 2019, e-commerce transactions grew by more than 40% last year.

Read more
Enhance Your Travel Site With Cloudinary in Anticipation of a Return to New Normal

Read more
The Benefits of Headless DAMs

Headless is not a buzzword anymore. In fact, the concept of headless architecture is gaining momentum due to the flexibility it offers for composing new experiences and for tackling the undue complexity of an ever-evolving technology stack. That’s because while the evolution of the martech landscape has enabled disruptive, digital innovations, the approach of buying point solutions for solving specific challenges can expose companies to the complicated nature of new technologies, systems, and platforms.

Read more

Building Display Ads With Transparent Video

By Afzaal Ahmad Zeeshan
Build Web Ads With Transparent Video to Attract User Engagement

Billions of views on the Internet every day drive one of the biggest industries on the planet: advertising. The sheer size of that market and the competitive nature of vying for consumer attention results in a constant need for innovation. Readers are jaded, and display ads are blind spots.

Read more
How Cloudinary's Media Optimizer Helps E-Businesses Deliver Superior Web Performance

As a technology company, Cloudinary owes its success to its ability to build solutions that address the most critical challenges you, our customers, face. The companies we serve run the gamut of digital businesses—retailers and direct-to-consumer brands, media and entertainment, travel and hospitality—which, coincidentally, all care about the same things.

Read more