Building a short url generator with nodejs and mongoDB
Tags: webdev, node, mongodb, express
Published: 2023-02-03 17:11:22

We have always come across many links that are too long for our day to day usage and it is very difficult to remember them easily or to forward/share them whenever required. So this is where we require urls to be short and effective.

We will be building an short url generator by the help of **NodeJS**, **mongoDB**and **expressJS**.

* First step is to create the file architecture to create our project, so here I am using VS code as a code editor.
* Now open the terminal and initialize an npm file by using command
```
npm init
```
* Fill in the required details as your need
* Now create a file structure for managing the routes and views folder as shown in the image below.

![File structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aa31ynjawh1gjyglxldb.png)


* Now let's first install the dependencies that we require, open the terminal and hit:
```
npm i expressjs mongoose ejs shortid dotenv nodemon
```
Here the **expressjs** is used for setting the routes and mongoose is used for creating models for our DB, whereas ejs is for the frontend part for the viewing engine of the project and **shortid** is the main function that we are going to use to generate shortids/shorturl for the feed in url and at last the **dotenv ** is an npm package for storing the credentials for accessing the DB.

* So after installing the packages/dependencies your **package.json** file should look like the image below and don't forget to change the scripts as shown below because we are going to require **nodemon** for speedy development of the app that automatically re-runs the server when any changes are made to the files.
```javascript
{
  "name": "url_shortner",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node server.js",
    "dev": "nodemon server.js"
  },
  "author": "Rohit",
  "license": "ISC",
  "dependencies": {
    "dotenv": "^10.0.0",
    "ejs": "^3.1.6",
    "express": "^4.17.1",
    "mongoose": "^6.0.7",
    "shortid": "^2.2.16"
  },
  "devDependencies": {
    "nodemon": "^2.0.12"
  }
}
```
* First we are going to setup the **dotenv** file with the DB url we are going to connect to, in this project we will be connecting our app to our local **mongoDB** database, so update the **.env** file as shown below.
```
MONGO_DB_URL=mongodb://127.0.0.1:27017/urlshortnerappdb
```

* Now we are going to make a connection with the DB in the **server.js** file.
```javascript
const express = require("express");
const mongoose = require("mongoose");
const app = express();

require("dotenv").config();

mongoose.connect(process.env.MONGO_DB_URL, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});

app.listen(process.env.PORT || 5000, () => {
  console.log("SERVER RUNNING AT PORT 5000...");
});

```
The **dotenv** is included on the first line for requiring the **dotenv** file that has the DB url for connection, followed by requiring the express for creating an instance and then followed by requiring mongoose for making the connection.
We then define a port for listening to the server on port 5000 or a PORT that we can specify in the **dotenv** file.

* Now we are going to define the schema for the url DB by requiring mongoose and adding in the collections.
```javascript
const mongoose = require("mongoose");
const shortid = require("shortid");

const shortUrlSchema = new mongoose.Schema(
  {
    full: {
      type: String,
      required: true,
    },
    short: {
      type: String,
      required: true,
      default: shortid.generate,
    },
    clicks: {
      type: Number,
      required: true,
      default: 0,
    },
  },
  { timestamps: true }
);

module.exports = mongoose.model("ShortUrl", shortUrlSchema);
```
We have used the **shortid** package for generating random shortids for our url with the help of **shortid.generate** command and a clicks collection for storing the count of number of clicks that has been made on the shorturl link by people.

* Now add the view engine code part that is **"ejs"** in the **index.ejs** file.
```html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>URL shortner</title>
    <style>
        body {
            background-color: powderblue;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
        }
        h1 {
            color: blue;
        }
        button {
            font-size: 17px;
            color: white;
            background-color: green;
            border-radius: 15px;
            width: 70px;
            height: 50px;
        }
        form {
            width: 50%;
            display: flex;
        }
        input {
            border-radius: 10px;
            width: 100%;
            height: 40px;
            border: none;
            margin: 10px;
        }
        table {
            width: 70%;
            padding-top: 20px;
        }
        table,
        td,
        th {
            border-radius: 5px;
        }
        table,
        thead,
        tr {
            font-size: 25px;
        }
        table,
        tbody,
        tr,
        td {
            font-size: 25px;
        }
        th {
            text-align: left;
        }
    </style>
</head>
<body>
    <h1>URL shortner</h1>
    <form action="/shortUrls" method="POST">
        <input type="url" name="fullUrl" id="fullUrl">
        <button type="submit">Submit</button>
    </form>

    <table>
        <thead>
            <tr>
                <th>Full URL</th>
                <th>Short URL</th>
                <th>Clicks</th>
            </tr>
        </thead>
        <tbody>
            <% shortUrls.forEach(shortUrl=> { %>
                <tr>
                    <td><a href="<%= shortUrl.full %>"><%= shortUrl.full %></a></td>
                    <td><a href="<%= shortUrl.short %>"><%= shortUrl.short %></a></td>
                    <td><%= shortUrl.clicks %></td>
                </tr>
                <% }) %>
        </tbody>
    </table>
</body>

</html>
```
and set the form action as **"/shortUrls"** because this is the endpoint which will help us to connect to the backend.

* Now we are going to add the routes in the **server.js** file.
```javascript
const shortUrl = require("./models/shortUrl");
const ShortUrl = require("./models/shortUrl");

app.set("view engine", "ejs");
app.use(express.urlencoded({ extended: false }));

app.get("/", async (req, res) => {
  const shortUrls = await ShortUrl.find();
  res.render("index", { shortUrls: shortUrls });
});

app.post("/shortUrls", async (req, res) => {
  await ShortUrl.create({ full: req.body.fullUrl });

  res.redirect("/");
});

app.get("/:shortUrl", async (req, res) => {
  const shortUrl = await ShortUrl.findOne({ short: req.params.shortUrl });
  if (shortUrl == null) return res.sendStatus(404);

  shortUrl.clicks++;
  shortUrl.save();

  res.redirect(shortUrl.full);
});
```
We are going to set the view engine using **app.set** for viewing our ejs files and to pass json data from backend we set the app as **app.use(express.urlencoded({ extended: false }))**.

The first route that is **"/"** will be the homepage for our application that will fetch all the previous url from the DB and render it using the ejs script.

The second route **"/shortUrls"** allows us to post/add urls to the DB

The third route **"/:shortUrl"** is what makes the connection between the original link and the short url link, so that it re-directs to the link that we want the short url for and it takes the id of the url stored in the DB as the params and then we are increasing the clicks count on the url.

* So the final code looks like:
```javascript
const express = require("express");
const mongoose = require("mongoose");
const shortUrl = require("./models/shortUrl");
const app = express();
const ShortUrl = require("./models/shortUrl");

require("dotenv").config();

mongoose.connect(process.env.MONGO_DB_URL, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});

app.set("view engine", "ejs");
app.use(express.urlencoded({ extended: false }));

app.get("/", async (req, res) => {
  const shortUrls = await ShortUrl.find();
  res.render("index", { shortUrls: shortUrls });
});

app.post("/shortUrls", async (req, res) => {
  await ShortUrl.create({ full: req.body.fullUrl });

  res.redirect("/");
});

app.get("/:shortUrl", async (req, res) => {
  const shortUrl = await ShortUrl.findOne({ short: req.params.shortUrl });
  if (shortUrl == null) return res.sendStatus(404);

  shortUrl.clicks++;
  shortUrl.save();

  res.redirect(shortUrl.full);
});

app.listen(process.env.PORT || 5000, () => {
  console.log("SERVER RUNNING AT PORT 5000...");
});
```
Now hit ```npm start``` in the terminal to start the app.

Enter the url for accessing the app as - **localhost:5000** on your web-browser.

You will be able to see the following page:

![Final app image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tfl1z7tzudkflufjti2b.png)

So this is how you create a simple url shortner app using nodejs, expresjs and mongodb and can clip your urls into a small size.

Do hit the ♥ button if you liked the post and share it with your friends to let them know how to easily create an url shortner app.

FOLLOW @rohit23421 for more stuff on development and better practices for a developer😄.