
npm init -y
npm i express
npm i mysql
npm i shortid
npm i ejs
const express = require("express");
const shortid = require("shortid");
const mysql = require("mysql");
const app = express();
app.set("view engine", "ejs");
app.use(express.static(__dirname + "/public"));
app.use(express.urlencoded({ extended: false }));
const db = mysql.createConnection({
host: "localhost",
user: "root",
password: "",
database: "url_shortener"
});
db.connect(err => {
if(err) {
console.log("Error connecting to DB");
return;
}
console.log("Connceted to DB");
});
function getLinks(req,res){
db.query("SELECT * FROM url ORDER BY ID DESC",(error,results) => {
if(error){
res.render('home',{result:[]})
}
else{
console.log(results)
res.render('home',{results:results})
}
})
}
app.get("/", (req, res) => {
getLinks(req,res)
});
app.post("/shorturl", (req, res) => {
const fullUrl = req.body.fullUrl;
if (!fullUrl) {
return res.sendStatus(404);
}
db.query('SELECT * FROM `url` WHERE `fullUrl` = ?', [fullUrl], (error, results) => {
if (error) {
console.log(error);
return res.sendStatus(404);
}
if (results.length === 0) {
const short = shortid.generate();
const url = { fullUrl: req.body.fullUrl, shortUrl: short, counts: 1 };
db.query('INSERT INTO `url` SET ?', url, (err, res) => {
if (err) {
console.log("Error creating table");
return;
}
});
getLinks(req,res)
} else {
const _short = results[0].shortUrl;
const _counts = results[0].counts;
db.query('UPDATE `url` SET `counts` = ? WHERE `shortUrl` = ?', [_counts + 1, _short], (err, res) => {
if (err) {
console.log("Error updating table");
return;
}
});
getLinks(req,res)
}
});
});
app.get("/:shortUrl", (req, res) => {
db.query('SELECT * FROM `url` WHERE `shortUrl` = ?', [req.params.shortUrl], (error, results) => {
if (error) {
return res.sendStatus(404);
}
if (results.length === 0) {
res.render("error");
} else {
res.redirect(results[0].fullUrl);
}
});
});
app.listen(3000);Now create a folder named public and inside it make a css folder and inside it make a home.css file. After that, copy/paste the below code into it.
.container {
width: 50%;
margin: auto;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
padding: 10px;
}
h2 {
margin: 0;
}
p {
max-width: 350px;
}
input[type="url"] {
height: 28px;
width: 250px;
padding-left: 8px;
border-radius: 4px;
border: 1px solid #000;
}
input[type="submit"] {
padding: 10px 20px;
color: #fff;
background-color: #349ded;
border: none;
border-radius: 4px;
margin-left: 5px;
}
input[type="submit"]:hover {
cursor: pointer;
opacity: 0.85;
}
.span-link {
padding: 10px 20px;
border-radius: 4px;
background-color: #349ded;
color: #fff;
}
.result-container {
background-color: #dddcdc;
padding: 10px;
min-width: 200px;
display: flex;
justify-content: space-around;
}
a {
text-decoration: none;
}
.copy-span:hover {
cursor: pointer;
opacity: 0.75;
}And now make views folder inside the root directory and inside it make two files namely home.ejs and error.ejs
<!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 Shortener</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="/styles/home.css" />
</head>
<body>
<div class="container">
<h2>Bitly URL Shortener Clone</h2>
<p>Convert long URL to shorter one with a single click. Its easy, simple and absolutely free!</p>
<form action="/shortUrl" method="post">
<div class="form-group">
<input class="form-control" type="url" placeholder="Enter the URL" name="fullUrl" required />
</div>
<div class="form-group">
<input class="form-control" type="submit" value="Convert" />
</div>
</form>
<%if(results){%>
<table class="table table-bordered">
<thead>
<tr>
<th>FullUrl</th>
<th>ShortUrl</th>
<th>Count</th>
</tr>
<tbody>
<%results.forEach(result=> {%>
<tr>
<td>
<%=result.fullUrl%>
</td>
<td>
<span><a id="short-url" href="<%= `/${result.shortUrl}` %>" target="_blank"><%= result.shortUrl %></a></span>
</td>
<td>
<%=result.counts%>
</td>
</tr>
<%})%>
</tbody>
</thead>
</table>
<%}%>
</div>
</body>
</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>Error Page</title>
<link rel="stylesheet" type="text/css" href="/styles/home.css" />
</head>
<body>
<div class="container">
<h2>URL Shortener</h2>
<p>The URL you entered does not exist!</p>
<br />
<a href="/"><span class="span-link">Visit Home Page</span></a>
</div>
</body>
</html>Google Chrome has dominated web browsing for over a decade with 71.77% global market share.…
Perplexity just made its AI-powered browser, Comet, completely free for everyone on October 2, 2025.…
You've probably heard about ChatGPT Atlas, OpenAI's new AI-powered browser that launched on October 21,…
Perplexity Comet became free for everyone on October 2, 2025, bringing research-focused AI browsing to…
ChatGPT Atlas launched on October 21, 2025, but it's only available on macOS. If you're…
Two AI browsers just entered the ring in October 2025, and they're both fighting for…