Back to home

Next.js Shortened URL Automation

Published: Nov 4, 2021

Last updated: Nov 4, 2021

This post will demonstrate how to create a shortened URL for your Next.js website.

It will follow a similar process that I am using for shortened URLs on my personal blog website, although this example will be in JavaScript as opposed to TypeScript (which my blog is written in).

The final code can be found on my GitHub repo "okeeffed/hello-nextjs-url-shortener".

Prerequisites

  1. Basic familiarity with Create Next App.
  2. create-next-app installed.
  3. Basic familiarity with Next.js.

Getting started

We will let create-next-app create the project directory hello-url-shortener for us:

$ npx create-next-app hello-url-shortener # ... creates Next.js app for us $ cd hello-url-shortener

At this stage, a working Next.js app is ready for us.

Let's create a couple more folders and files to host our script.

# Create a content folder to host markdown files $ mkdir scripts $ touch scripts/urlShortener.js # Create a folder for some pages - we will be verbose since this is more a demonstration $ mkdir -p pages/content $ touch pages/content/pageA.js pages/content/pageB.js

We will need to install the following dependencies:

npm i --save-dev md5 recursive-readdir

We will use md5 to generate hashes and recursive-readdir to read the contents of the /pages/content directory.

Note: this example will demonstrate shortening for two verbose URLs, but you should tweak the script to generate the relevant output to your project. If you are using dynamic content (like I am for my blog), then you need to ensure that you are referencing the data for those paths to know what paths you will need to shorten in the script.

Setting up our pages

To keep things simple, add the following to pages/content/pageA.js to pages/content/pageB.js and pages/content/pageB.js respectively:

// pages/content/pageA.js export default function PageA() { return <div>PageA, woo!</div>; } // pages/content/pageB.js export default function PageB() { return <div>PageB, woo!</div>; }

We are going to keep things simple, as the important part is the redirect.

If you run next dev in the terminal, you should see the following in the browser for PageA and PageB at localhost:3000/content/pageA and localhost:3000/content/pageB respectively:

Page A on localhost

Page A on localhost

Page B on localhost

Page B on localhost

At this stage, we are now ready to create our shortened URL path.

Writing our redirects script

Next.js docs have information on performing redirects in the next.config.js file.

A redirect looks like the following:

module.exports = { async redirects() { return [ { source: "/about", destination: "/", permanent: true, }, ]; }, };

What we want to do is write a script that will manage the return value of the redirects function for us.

First, create the next.config.js file using touch next.config.js and add the following:

const urlPaths = require("./public/urls.json"); module.exports = { // ... omitted anything else that may be in this file async redirects() { return urlPaths.redirects; }, };

Now that our config file is setup, we can add the following to our scripts/urlShortener.js file:

const { readFileSync, writeFileSync, existsSync } = require("fs"); const recursive = require("recursive-readdir"); const md5 = require("md5"); const path = require("path"); async function main() { const contentPagePath = path.resolve(__dirname, "../pages/content"); const urlShortenerFilePath = path.resolve(__dirname, "../public/urls.json"); const urlShortenerFileExists = existsSync(urlShortenerFilePath); const files = await recursive(contentPagePath, ["!*.js"]); const currentUrls = urlShortenerFileExists ? JSON.parse(readFileSync(urlShortenerFilePath, "utf-8")) : { redirects: [] }; // Find all current hashes in the public urls JSON file const currentEntries = currentUrls.redirects.map((url) => url.destination); const currentHashes = currentUrls.redirects.map((url) => url.source); for (const file of files) { const filePath = file // Replace the prefix .replace(`${process.cwd()}/pages`, "") // Replace file JavaScript suffix .replace(".js", ""); // Check if we already have a hash for our file if (currentEntries.includes(filePath)) { continue; } // Create a hash for our file let outputHash = `/${md5(file).slice(0, 4)}`; // If our hash collides, rehash while (currentHashes.includes(outputHash)) { outputHash = `/${md5(outputHash).slice(0, 4)}`; } currentUrls.redirects.push({ source: outputHash, destination: filePath, permanent: true, }); } writeFileSync( urlShortenerFilePath, JSON.stringify(currentUrls, null, 2), "utf8" ); } main();

The script above does the following:

  1. Assigning some sensible variable defaults after resolving where the files sit.
  2. Using recursive-readdir to fetch all the .js files in the pages/content directory.
  3. Checks if our public folder has a file called urls.json and assigns the value to currentUrls. If not, we are assigning currentUrls to a default object with empty redirects.
  4. Iterating through all of those files file (for us, pageA.js and pageB.js) and generating a hash for each if an entry does not already exist.
  5. Each hash is assigned to our currentUrls.redirects array as an object to represents what we saw in the Next.js docs.
  6. Writing that file back out to public/urls.json.

All that is left to do is run that script. In the terminal, run node scripts/urlShortener.js and you should see the output in public/urls.json:

{ "redirects": [ { "source": "/d475", "destination": "/content/pageA", "permanent": true }, { "source": "/42e2", "destination": "/content/pageB", "permanent": true } ] }

Awesome! So the path /d475 should now redirect to /content/pageA (and so on for the rest).

To have the next.config.js input take effect, you will need to restart next dev.

Once, that is done, head to localhost:3000/{source} and you should see the page redirect to the destination (where source is a value from your public/urls.json directory).

Success!

What next?

The URL shortener script that we wrote will only apply to shortening the path part of the URL. If you want to have a shorter page like bit.ly etc, you will need to buy the domain for that.

For my personal links, I purchased the domain dnok.li (thinking it was short for Dennis O'Keeffe Link). You will need to apply that to your website, like how I did for my blog (which is being hosted on Vercel):

Applying my domain name

Applying my domain name

Once that is done, then that in combination with the redirects generator we bring the goods (such as the shortened link for this blog post https://dnok.li/b7c2).

Summary

Today's post demonstrated how to create a URL shortener for your Next.js website programmatically.

This can be incredibly useful for any URLs taking up precious space on your shared content.

Resources and further reading

  1. Basic familiarity with Create Next App.
  2. Basic familiarity with Next.js.
  3. Final code.

Photo credit: pawel_czerwinski

Personal image

Dennis O'Keeffe

@dennisokeeffe92
  • Melbourne, Australia

Hi, I am a professional Software Engineer. Formerly of Culture Amp, UsabilityHub, Present Company and NightGuru.
I am currently working on Visibuild.

1,200+ PEOPLE ALREADY JOINED ❤️️

Get fresh posts + news direct to your inbox.

No spam. We only send you relevant content.

Next.js Shortened URL Automation

Introduction

Share this post