Create your own URL shortener with Next.js and MongoDB in 10 Minutes

Motivation

A few weeks back, I was working on a Twitter bot to post my popular articles and I realized that links of some articles are not parsed well in the Tweet. However, shortening them using Rebrandly worked well.

So, I decided to mak…


This content originally appeared on DEV Community and was authored by DEV Community

Motivation

A few weeks back, I was working on a Twitter bot to post my popular articles and I realized that links of some articles are not parsed well in the Tweet. However, shortening them using Rebrandly worked well.

So, I decided to make a URL shortener for myself.

Breakdown

We need a

  • service to create a unique hash for each long URL
  • database to persist long to short URL mapping
  • service to redirect short links to their destination

As always, Next.js was my first choice for building the complete service and MongoDB for storing links.

Development

Now that we have figured out the steps, let's work on them one by one

Setup the project

Let's use the npx create-next-app url-shortener command to generate a boilerplate for our app.

./.env.local

DB_NAME=url-shortner
ATLAS_URI_PROD=mongodb+srv://<user>:<password><cluster>.mongodb.net/url-shortner?retryWrites=true&w=majority

API_KEY=<a-long-random-string>
HOST=http://localhost:3000

These environment variables should also be stored in your Vercel project.

The value of HOST should be set to your domain when you host this project. If you don't have a public domain, just you NEXT_PUBLIC_VERCEL_URL environment variable instead of HOST.

Setting up MongoDB

  1. Run npm i --save mongodb
  2. Create a mongodb.ts file at the root of the repo.
// ./mongodb.ts

import { Db, MongoClient } from "mongodb";
import { formatLog } from "./utils";

// Create cached connection variable
let cachedDB: Db | null = null;

// A function for connecting to MongoDB,
export default async function connectToDatabase(): Promise<Db> {
  // If the database connection is cached, use it instead of creating a new connection
  if (cachedDB) {
    console.info(formatLog("Using cached client!"));
    return cachedDB;
  }
  const opts = {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  };
  console.info(formatLog("No client found! Creating a new one."));
  // If no connection is cached, create a new one
  const client = new MongoClient(process.env.ATLAS_URI_PROD as string, opts);
  await client.connect();
  const db: Db = client.db(process.env.DB_NAME);
  cachedDB = db;
  return cachedDB;
}

Add create-short-link service

Go ahead and add a ./api/create-link.ts file to create a REST endpoint for this service.

Couple of things we need to be aware of

  1. A unique Hash is required to make short URLs. I used nanoid to generate a random short hash for the long URL.
  2. This endpoint should only be accessed by the POST method.
  3. We should set up an API-KEY authentication to secure the endpoint. This can be done by generating a long string and using it as an API-KEY header.
// ./api/create-link.ts

import { NextApiRequest, NextApiResponse } from "next";
import connectToDatabase from "../../mongodb";
import { customAlphabet } from "nanoid";
import { COLLECTION_NAMES } from "../../types";

const characters =
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const getHash = customAlphabet(characters, 4);

export default async function CreateLink(
  request: NextApiRequest,
  response: NextApiResponse
) {
  const apiKey = request.headers["api-key"] as string;
  if (request.method !== "POST" || apiKey !== process.env.API_KEY) {
    return response.status(405).json({
      type: "Error",
      code: 405,
      message: "Only POST method is accepted on this route",
    });
  }
  const { link } = request.body;

  if (!link) {
    response.status(400).send({
      type: "Error",
      code: 400,
      message: "Expected {link: string}",
    });
    return;
  }
  try {
    const database = await connectToDatabase();
    const urlInfoCollection = database.collection(COLLECTION_NAMES["url-info"]);
    const hash = getHash();
    const linkExists = await urlInfoCollection.findOne({
      link,
    });
    const shortUrl = `${process.env.HOST}/${hash}`;
    if (!linkExists) {
      await urlInfoCollection.insertOne({
        link,
        uid: hash,
        shortUrl: shortUrl,
        createdAt: new Date(),
      });
    }
    response.status(201);
    response.send({
      type: "success",
      code: 201,
      data: {
        shortUrl: linkExists?.shortUrl || shortUrl,
        link,
      },
    });
  } catch (e: any) {
    response.status(500);
    response.send({
      code: 500,
      type: "error",
      message: e.message,
    });
  }
}

Hosting

Hosting this project is a piece of cake because Next.js integration with Vercel is excellent.

A simplified list of steps:

  1. Push your Next.js project to a GitHub repository
  2. Go to https://vercel.app and login with your GitHub account
  3. Import the url-shortener repository by clicking on the "New Project" button on the Vercel dashboard.

You can also read about this in detail here.

Once done with the above steps, head to project settings and add the environment variables we defined in our .env.local file to the Vercel project's environment variables.

You can also connect your custom domain to this project from the settings.

🎉 Tada! Your URL shortener is ready and hosted now.

What's next?

Well, you can continue to use this project as a REST API like I do or you can create a front-end to make it a web app.

Before making it a public web app, make sure you put in additional security.

You can clone this project from this GitHub Repo.

This article is not meant to be followed in production and should only be taken for learning purposes.

Many optimizations can be made in the above approach like using a better database or indexing it properly to make it faster.

I hope you find this article helpful! Should you have any feedback or questions, please feel free to put them in the comments below.

For more such content, please follow me on Twitter

Until next time


This content originally appeared on DEV Community and was authored by DEV Community


Print Share Comment Cite Upload Translate Updates
APA

DEV Community | Sciencx (2022-03-14T09:39:40+00:00) Create your own URL shortener with Next.js and MongoDB in 10 Minutes. Retrieved from https://www.scien.cx/2022/03/14/create-your-own-url-shortener-with-next-js-and-mongodb-in-10-minutes/

MLA
" » Create your own URL shortener with Next.js and MongoDB in 10 Minutes." DEV Community | Sciencx - Monday March 14, 2022, https://www.scien.cx/2022/03/14/create-your-own-url-shortener-with-next-js-and-mongodb-in-10-minutes/
HARVARD
DEV Community | Sciencx Monday March 14, 2022 » Create your own URL shortener with Next.js and MongoDB in 10 Minutes., viewed ,<https://www.scien.cx/2022/03/14/create-your-own-url-shortener-with-next-js-and-mongodb-in-10-minutes/>
VANCOUVER
DEV Community | Sciencx - » Create your own URL shortener with Next.js and MongoDB in 10 Minutes. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/03/14/create-your-own-url-shortener-with-next-js-and-mongodb-in-10-minutes/
CHICAGO
" » Create your own URL shortener with Next.js and MongoDB in 10 Minutes." DEV Community | Sciencx - Accessed . https://www.scien.cx/2022/03/14/create-your-own-url-shortener-with-next-js-and-mongodb-in-10-minutes/
IEEE
" » Create your own URL shortener with Next.js and MongoDB in 10 Minutes." DEV Community | Sciencx [Online]. Available: https://www.scien.cx/2022/03/14/create-your-own-url-shortener-with-next-js-and-mongodb-in-10-minutes/. [Accessed: ]
rf:citation
» Create your own URL shortener with Next.js and MongoDB in 10 Minutes | DEV Community | Sciencx | https://www.scien.cx/2022/03/14/create-your-own-url-shortener-with-next-js-and-mongodb-in-10-minutes/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.