Introducing Click to Edit

Build your own branded short links with GraphQL & Serverless Functions

Learn how to use Hygraph GraphQL Queries & Mutations to power a simple link shortener project in this tutorial.
Jamie Barton

Written by Jamie 

Nov 22, 2021
Hygraph URL Shortener

Marketing teams for years have been using short URLs to track click origins, and of course, to shorten those long winded slug based URLs.

You've most likely seen something like https://bit.ly/graphcms. The issue with these links is that the .ly extension is rather confusing for those not familiar with it, and it's "off brand".

Thankfully we can use Serverless Functions to deploy our own code to a custom (sub)domain that is closer to our brand. These custom Serverless functions can check if the link exists, track a "visit", redirect to the destination URL, and of course do absolutely anything else in between.

⚡️ We'll be using Hygraph to model our GraphQL schema, and automatically provide a Query & Mutation API we can use.

📝 While Hygraph has great content editing features, I want to focus this tutorial on the APIs powering that, and how you can use the API directly to add new content entries, and relate them to other models.

#1. Create a new Project

Let's begin by creating a new Hygraph project. You'll need to give it a name, pick a region where the data will be stored, and click Create to confirm.

The Hygraph (formerly GraphCMS) project creation interface showing the initial setup for a new headless CMS project, featuring hosting region selection on a world map to ensure low latency for a branded short link service

We'll begin by creating a Link model that will be used to send visitors to the required destination.

Once you've created the model, add the following fields:

The Hygraph headless CMS schema builder interface showing the configuration of a 'Link' content model. The model defines essential fields for a branded short link service, including a required 'Destination URL' and a unique 'Short URL' string field

#3. Create a Visit model

Now create the model Visit. This will be used to track every click to our Link we created earlier.

Once you've created the model, add a relation to the Link model we created earlier:

The Hygraph headless CMS schema builder interface showing the addition of a two-way reference field named 'Link,' establishing a relational connection between models to track data associations for a branded short link service

The relation will be a Many (Visit) to one (Link) relation. A Link has many Visits. You'll also want to make this a two way reference - we'll need this for a follow up guide on analytics later.

A technical screenshot of the Hygraph interface showing the configuration of a many-to-one relationship and two-way reference between the Visits and Link models, allowing a single branded short link to track multiple unique visitor analytics

If you save, and visit the Link model schema once more, you should see the reverse relation to visits:

The completed Link content model in the Hygraph schema builder, displaying fields for 'Destination URL', 'Short URL', and a hidden Visits two-way reference field to manage relational data for a custom branded short link service

At this point it's probably worth creating some example links you can use during the next steps.

The Hygraph headless CMS content editor interface showing the creation of a new branded short link entry. The form is populated with a Destination URL and a custom Short URL slug, ready to be finalized using the 'Save & publish' action

You can also schedule links to be published at a later time with Scheduled Publishing.

The Hygraph headless CMS interface featuring the Scheduled Publishing modal, allowing users to automate the launch of branded short links by selecting a specific date, time, and timezone for automated content publication

When we invoke a Serverless function, we'll want to pass the shortUrl from the URL the user is visiting, e.g. https://go.example.com/wtf and pass that onto a GraphQL query so we can fetch the destinationUrl if it exists.

Hygraph automatically creates queries for the model + fields we defined above.

The query will look something like this:

query GetLinkByShortUrl($shortUrl: String!) {
link(where: { shortUrl: $shortUrl }) {
id
destinationUrl
}
}

Let's test this out with the Hygraph API Playground. Make sure to pass the variable shortUrl:

The Hygraph API Playground demonstrating a successful GraphQL query named GetLinkByShortUrl. The interface shows the query execution using query variables to retrieve a destination URL from a headless CMS for a custom branded short link service

Success! Our query is returning the destinationalUrl. We'll use this later.

Every time someone invokes our Serverless function, and fetches a valid Link, we also want to track this link has been visited. We'll need to pass it the ID of the link we want to "connect".

Hygraph automatically creates mutations for the model + fields we defined above.

The mutation will look something like this:

mutation CreateNewVisitForLink($linkId: ID!) {
createVisit(data: { link: { connect: { id: $linkId } } }) {
id
}
}

Let's again test this out inside the Hygraph API Playground. Don't forget to pass the linkId:

The Hygraph API Playground demonstrating a successful GraphQL mutation named CreateNewVisitForLink. The interface illustrates using a relational connect operation to associate a new visit entry with a specific branded short link using its unique linkId

Success! The GraphQL mutation successfully connected the visit to the link. You can verify this by querying for all links, and their visits, or by viewing the entry within the Content Editor:

The Hygraph content editor interface verifying a successful GraphQL mutation by showing a newly created 'Visit' entry associated with a branded short link. This illustrates the completed relational data connection between site visits and their corresponding destination URLs in a headless CMS

#7. Configure a new code project

Inside of a new directory, initialize NPM, and add our 2 dependencies:

mkdir cmsly
cd cmsly
npm init -y
npm install -E graphql-request graphql

Next create the file [shortUrl].js inside of the folder api:

mkdir api
touch api/[shortUrl].js

Then inside of here instantiate a new GraphQLClient using graphql-request we installed earlier.

import { GraphQLClient, gql } from "graphql-request";
const hygraph = new GraphQLClient(process.env.HYGRAPH_ENDPOINT, {
headers: {
Authorization: `Bearer ${process.env.HYGRAPH_TOKEN}`,
},
});

In order for this to work, you'll need to obtain your HYGRAPH_ENDPOINT, and create a new Permanent Auth Token (as HYGRAPH_TOKEN ) and set this inside of the file .env:

HYGRAPH_ENDPOINT=
HYGRAPH_TOKEN=

You can configure this inside of your Project API Access settings:

The Hygraph project settings interface showing the API Access configuration screen. The Content API endpoint URL for the master environment is highlighted, providing the necessary connection string to integrate external serverless functions with the headless CMS

The Permanent Auth Token should also have restricted access:

The Hygraph interface showing the Permanent Auth Token Permissions setup. The configuration displays granular API access control for the Link model, specifically enabling Read and Update permissions to ensure secure data handling between the headless CMS and serverless functions

#8. Implement logic into Serverless function

We'll now move use the gql import we defined above to encapsulate our GraphQL query and mutation we wrote earlier.

const GetLinkByShortUrlQuery = gql`
query GetLinkByShortUrl($shortUrl: String!) {
link(where: { shortUrl: $shortUrl }) {
id
destinationUrl
}
}
`;
const CreateNewVisitForLinkMutation = gql`
mutation CreateNewVisitForLink($linkId: ID!) {
createVisit(data: { link: { connect: { id: $linkId } } }) {
id
}
}
`;

We'll then check the shortUrl passed into the query from the page request, which we can use to kick off our query. The reason we used square brackets [] around the filename shortUrl this is because we'll be hosting our Serverless function with Vercel, and they treat this as a dynamic route.

export default async function handler(req, res) {
const { shortUrl } = req.query;
try {
const {
link: { id: linkId, destinationUrl },
} = await hygraph.request(GetLinkByShortUrlQuery, { shortUrl });
await hygraph.request(CreateNewVisitForLinkMutation, {
linkId,
});
res.status(301).redirect(destinationUrl);
} catch (err) {
console.log(err)
res.status(404).end("Not Found");
}
}

Finally create the file vercel.json in the root of your project and add the following:

{
"rewrites": [{ "source": "/:shortUrl*", "destination": "/api/:shortUrl*" }]
}

This will allow us to redirect all traffic from /:shortUrl to our Serverless function at /api/:shortUrl.

#9. Deploy to Vercel

We now need to deploy this to Vercel. Go ahead and create an account, login, and install the CLI.

Once you're logged into the CLI, you'll want to run vc --prod to deploy your code to production.

If you then open the Vercel project settings to configure the domain, you can add an existing domain or new one and set it as the production domain for your project!

The Vercel Project Settings interface showing the configuration of a custom production domain for a branded short link service. The screen displays the 'go.notrab.dev' domain with a valid configuration and successful assignment to the main Git branch for live deployment

You should now have your very own branded short URL service deployed to your (sub)domain!

Finished product preview

#10. Add Preview URLs

If you've a lot of links you quickly want to visit, you can tell Hygraph what the final URL will look like for each of your links.

Inside of the Settings for the Link model, add a preview URL similar to the below (giving it whatever "Name" you want):

The Hygraph model settings interface showing the configuration of Preview URLs, illustrating how to create a dynamic URL template using the {shortUrl} field to enable instant content previews for a custom branded short link service

Then when viewing a Link content entry in the CMS you can quickly visit it using the button on the right:

The Hygraph content editor interface showing the sidebar Preview panel, which features an 'Open in URL' button to instantly test and verify the live redirect of a newly created branded short link based on the configured URL template

#Try it yourself

All of the code is available on GitHub, or you can deploy yourself using the button below!

Deploy with Vercel

Blog Author

Jamie Barton

Jamie Barton

Jamie is a software engineer turned developer advocate. Born and bred in North East England, he loves learning and teaching others through video and written tutorials. Jamie currently publishes Weekly GraphQL Screencasts.

Share with others

Sign up for our newsletter!

Be the first to know about releases and industry news and insights.