How I made a MERN custom link shortener
Tags: webdev, beginners, mongodb, react
Published: 2023-07-13 10:32:27

> "Honey I shrunk the link!" 

**************************************************************

##### A bare bones project by a beginner. 

When I was working on a project, I wanted to be able to predict the links to certain files provided by the user, to make things easier to reference them in my code.

Custom back halves in links means customizing the endings e.g. Bit.ly/xxxx (The popular URL shortening service [Bit.ly](https://bit.ly/) allows users to do this, but there is a limit in terms of how many links can be customized ($)). Other link trimming platforms were ok, but I didn’t want to be limited in the number of links I could tweak. I also wanted to brush up on my understanding of Express, React and try working with a new database (MongoDB) so decided to try making a link shortener.

I read through many tutorials online, but for many of them I just couldn’t get it to work on my machine. This project encompasses what I learned from guides written by others, plus my own tweaks.

**************************************************************

**Key features:**

- Structure: I separated into 2 different directories, one for the front-end and one for the back-end. Also pushed to 2 different repositories in GitHub.
- Setting up the schema for the database to store: 1) the original url 2) a unique urlId (more on this below) 3) shortened url (urlId + base url)
- To create the shortened link, I used an npm package ([uniqid](https://www.npmjs.com/package/uniqid)) to generate a series of random characters which get appended to the base URL. Initially I was working locally, so it looked something like localhost:3000/[xxx]. I saved this as a urlId in my database.
- Running the origin URL through another npm package called [valid-url](https://www.npmjs.com/package/valid-url) to make sure it‘s legit before storing in database. If not, send error which is displayed in front-end. I also wrote placeholder text in the input field so user kows to enter a full link e.g. https://www.google.com. Another option is to use RegEx to check the URL.
- Allowing the user to customize the back half of the shortened link, in other words updating the record in the database (first checking to see if the urlId exists in MongoDB). Throw an error if that urlId already exists.
- Redirection: directing to the original URL when you enter the shortened url. At first I tried using useNavigate (react router) but this didn’t work with external links, so I ended up simply using window.location.href = original url.
- Copy to clipboard function for shortened link: I implemented with the help of this tutorial. For the clipboard icon, I simply used Font Awesome.


**************************************************************
**Deploying the app:**

- I imported the back-end of my project to [**Railway**](https://railway.app/) (a good choice for full-stack projects) and hooked up MongoDB database in the Railway platform, adding the MONGO_URI manually as an environment variable. I imported the React front-end project to Railway without any extra steps.
** I also needed to update my code so that the API calls from React front-end were to the Railway address where my back-end lives, so no longer localhost.
- It wasn’t really a link shortener since the Railway auto-generated domain was longer than the original one, so I opted to purchase a domain. Next I followed [these steps](https://stackoverflow.com/questions/74461333/adding-custom-godaddy-domain-to-railway-web-app) to update the DNS records and link up the front-end of my project **only** to the custom domain (to find the remote IP address of my project I used https://www.whatismyip.com/dns-lookup/). I kept the back-end on Railway address as is (I could have bought a subdomain for the API which would be ideal, but decided not to for now to save costs).**

- Check out the project here: [s5n.co](s5n.co)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cso0j84vche5hce4fwjf.png)

Thanks for reading!