I've always wondered how Bitly (bitly.com) works. They can take long, unwieldy URLs and shorten them dramatically. It seems very interesting, and I'm curious about the mechanics behind it. Building my own link shortener to understand the process seems like a fun project, especially since it might not be that difficult at first glance.
Introduction
I've always wondered how Bitly works. They can take long, unwieldy URLs and shorten them dramatically. It seems very interesting , and I'm curious about the mechanics behind it. Building my own link shortener to understand the process seems like a fun project, especially since it might not be that difficult at first glance.
Thus, I took up the challenge and built a simple link shortener! It's currently hosted on Glitch. The project consists of two components: the main website and a mock database server hosted on separate Glitch projects. You can access the source code within these projects. Additionally, I learned how to configure my first custom subdomain for this project, . Feel free to check it out with this links.ciayang.dev!. *NOTE: Please no that this project is solely for fun and not for everyday usage. And there were some major limitations which are not suitable for real-world use case. See this section for more info!
Technical Stack & Tools
- Backend: Nodejs, Express.js
- Frontend: HTML, CSS
- Database: json-server
- UI Framework: Bootstrap, jQuery
- Hosting: Glitch
Scope and assumptions
Let's start from a general overview for this project and consider the following diagram.
The main functionality of this project is to take a long URL and return a shortened version.
- The user will input their long URL in the form, and the server will return a new short URL.
- When another user visit the page with the short url, server should identify the short url and redirect user to the correct original page.
- Users can view all created short-links by navigating to
/links
, but keep in mind this endpoint will show ALL links which includes other users.
WARNING
This project will not have any security considerations as the source code is publicly available in Glitch.com
with starter plan... DO NOT input any sensitive links or information to the servers as everyone can access to and to view the all created links!
The System Design
With the very basic requirement as stated. I came up with a overview architecture of the system.
From the diagram above, there are two core components, the website consists of frontend and backend logics, and the mock database server. For frontend, it's only have one HTML page which will then served using Express.js. The HTML page consist the input form for the user to interact and generate their short links. For backend, there are few APIs for create and retrieve the url links. To put it together, the HTML form will then interact with the API to create the short links.
Meanwhile for the database server, I choose json-server over other dedicate database as I'm not experts at configuring standalone database on my own at that time. I think it's the quickest way to setup a temporary storage solution for this project and json-server
also provides easy access REST API for retrieve or create data.
Here's the example of how the data structure looks like.
// db.json
{
"urls": [
{
"id": 1,
"urlCode": "23TplPdS",
"longUrl": "https://www.section.io/engineering-education/nodejs-url-shortener/",
"date": "Sat Feb 12 2022 15:12:12"
},
...
]
}
id
- auto generated sequence numberurlCode
- unique code for each long url object, to generate short urllongUrl
- the original url that user inputdate
- date & time when the shorturl being generated
The Limitations
Since this project is hosted on Glitch.com
with starter plan, a full-stack application will sleep after 5 minutes without interactivity by default. And hence, if you visit the website for the first time, you will need to be patient and wait for the server to boot up...
After few seconds you should see the main page!
But there is another catch... The same limits with the mock database server will happens since its hosted on another glitch project. Thus, the first submission of the url will not have any response. So... you might need to wait again for the server to fully boot up haha...
TIP
You can also visit /links to trigger server to run first before submitting form and you should see the page returns a json string consists of all the url data.
Code Deep Dive
Look, I gotta be honest here - I can't really call this a "deep dive" since the code is pretty dated and doesn't follow most of today's best practices . But hey, I'll walk you through some key parts that made this project work!
Remember how we talked about the data structure earlier? One of the main things we needed was generating a unique random code for each original link. Now, I could've tried writing this from scratch, but let's be real - there's probably a library that's already solved this way better than I could. That's why I went with the shortid
package.
Here's how we create those short links:
// /controller/convert.js -> POST /add
...
const shortid = require("shortid");
const convert = async (req, res, next) => {
...
const payload = {
urlCode: shortid.generate(), // generates a unique short code
longUrl: baseUrl,
date: new Date(),
};
...
};
And here's what happens when someone visits a shortened link:
// /controller/getOne.js -> GET /:id
const getOne = async (req, res, next) => {
if (!req.params.id) next(); // check if we actually have a code in the URL
// use json-server's API to find the matching long URL
const result = await axios
.get(`${url}/urls?urlCode=${req.params.id}`, {
headers: { serviceKey: serviceKey },
})
.then((res) => res)
.catch((err) => {
console.log("Failed to fetch link");
});
if (!result) {
res.send("404"); // oops, link not found!
} else {
res.redirect(result.data[0].longUrl); // send them to the original URL
}
};
Looking back at this code now makes me chuckle a bit - there's so much we could improve! Better error handling, proper status codes, input validation... but hey, it worked! Sometimes the best way to learn is to build something simple and then figure out how to make it better.
INFO
🚨 I just realized that the shortid
package I used is now deprecated (showing its age, right?). If you're building something similar, you might want to check out Nano ID instead - it's what the original shortid
docs are recommending these days. It's faster, safer, and actively maintained - basically everything you'd want in a modern ID generator!
Showcase
Finally, now it's time for the showcase!
Future improvements
So this project was super fun to build, but let's be real - there's tons of cool stuff we could add to make it even better! Right now it's pretty basic (and yeah, that Glitch hosting can be a bit slow) , but I've got some exciting ideas on how to level it up.
Here's what I'm thinking of adding:
- Make it faster: Ditch the JSON server for something beefier, and maybe find a hosting service that doesn't take naps
- Lock it down: Add some basic security stuff so people can have their own accounts and private links
- Cool features: Let folks see how many clicks they're getting, and maybe even set expiration dates
- Make it prettier: Upgrade UI with latest trends and make it work better on phones
But hey, for now it's a fun little project that gets the job done! And maybe, just maybe I will came out a version 2 for this project!
Project completion date: April 16, 2022
Writing date: January 20, 2025