Creating a URL Shortener with TypeScript + Express.js + MongoDB
In this article, we will create a URL Shortener API which can create and retrieve data from MongoDB Cloud.
What is TypeScript
First, we create a directory for our project then initialize git and npm in root directory and create our first ts file in
mkdir short-urlsnpm init -y && git initmkdir src/index.ts
Now we need to install packages. We will use
- Express.js for API
- cors for CORS options
- helmet for basic security
- yup for schema validation
- nanoid for short urls
- monk for MongoDB
- dotenv for env files
Since we are using TypeScript we need the type definitions for these packages. We can install all of these with
npm i express cors helmet yup nanoid monk dotenvnpm i -D @types/node @types/express @types/cors @types/yup @types/nanoid
We don’t need types for helmet, monk and dotenv because they provide their own definitions. Finally we need TypeScript to compile our ts files. We install ts-node and nodemon alongside with ts to make our development faster.
npm i -D typescript ts-node nodemon
As I mentioned above we can customize the ts compiler using tsconfig.json. We can create tsconfig by hand but there is a better way to do it. We can use the npx command
npx tsc --init
This command will create tsconfig.json in our project root. We gonna change some options in this tsconfig.json file like
Configuring .gitignore and package.json
We can add
.env to our .gitignore file to ignore them. Before configuring package.json lets create an empty
.env file in projects root directory with command
We will save our MongoDB URI here later. Now lets configure package.json. We add these following scripts to scripts section
"start": "node dist/index.js","dev": "nodemon src/index.ts","build": "tsc -p . && cp .env dist/.env"
Creating an express app
We open up our index.ts and start writing some code. First we import Express and middlewares.
We create express application and add our middlewares with
app.use() function. Then we need to define a schema for our data which can be done using
yup. We create an yup object with desired shape. In this case I want a destination field and a slug field. I want both to be string and destination will be a required url.
Now we can create our endpoints and start listening for incoming requests. We need an endpoint to create short urls and another one to retrieve them. You can change the data schema and add fields like
token which can track the click count and token for editing slug etc.
First endpoint will be a
create endpoint which will create a document in MongoDB with given slug and destination and if there is no slug provided in post data we should be creating a random slug for given destination.
This function will response with posted slug and destination if they are valid otherwise it will return an error message. Before running our express app we need to add an error function and start listening for incoming requests.
Now if we go to our terminal and run
npm run dev nodemon will start watching for file changes in
src directory. Open your favorite API client and send a post request for
http://localhost:5000/create with json body.
Connecting to a MongoDB
So far we can send and validate our data, now we need to save these slugs and corresponding urls to our database so we can redirect when user uses a slug. We’ll be using MongoDB Cloud for our database but you can use MongoDB locally if you want. You can follow the Part 1 of Bret Cameron’s MongoDB: A Beginner’s Guide article to learn how to create a MongoDB cluster on cloud. From now on I assume you have your MongoDB URI.
We already created
.env file so we just paste it with the name
Before connection to MongoDB go to your cluster connections and create database named
URL and collection named
Your URI should look similar to this where
Next step is creating a connection for the database. We can do that in a separate file. Create a file named
db.ts in our
db.ts we need to connect to our MongoDB
.env file by loading content to the
process.env variable with
dotenv.config(). Then we create a
monk instance with default function which corresponds to
const db = require("monk")(MONGO_URI)
After connecting to database we get the
urls collection with
get() function. Finally we create an Index at slug field with
unique: true option that assures every slug is unique.
Integrating MongoDB to Express.js
So far we created an express app and and prepared the connection to our database now we have to integrate those two.
First we alter our
create endpoint so it can save documents to database.
Here we save our data to database with
Now if we send a post request to
/create with proper request body it will save our slug and destination data to MongoDB and return its id.
If we try to send the same request the response status will be 400 and it will say that
slug is in use because we created an unique index at
Finally we add our last endpoint to retrieve information about given slug.
To test this function we can send a get request to
localhost:5000 with desired slug.
We are able to create random and unique slugs if no slug is provided in request body.
You can create more operations and alter the data schema to create more complex shortener. Just another idea is static serving with express to create a frontend to your api and using
res.redirect(redirect_url) to perform redirection which is the actual purpose of this article.
You can find the full source code here.