post

Building a URL Shortener with Node.js, MongoDB, and Vercel in 30 Minutes

Today, I’ll show you how to build a practical URL shortener with click analytics using modern web technologies. This project is perfect for developers looking to create something useful while learning about Node.js, MongoDB, and serverless deployment.

Why Build a URL Shortener?

Before diving in, you might wonder: why build yet another URL shortener? Here’s why this project is valuable:

  1. You own your data and links
  2. You can track click analytics
  3. You’ll learn modern web development practices
  4. It’s a perfect serverless deployment example
  5. You can extend it with custom features

The Tech Stack

We’re using a modern, lightweight stack:

  • Node.js & Express: For our backend API
  • MongoDB Atlas: For data persistence
  • Vercel: For serverless deployment
  • Tailwind CSS: For a clean, responsive UI

Key Features

Our URL shortener includes:

  • URL shortening with nanoid for unique IDs
  • Click tracking
  • Real-time statistics
  • Mobile-friendly interface
  • Clean, RESTful API

The Implementation

Here’s the interesting part – how we built it. Let’s break down the key components:

1. The Data Model

We kept the MongoDB schema simple but effective:

const urlSchema = new mongoose.Schema({
  originalUrl: String,
  shortUrl: String,
  clicks: { type: Number, default: 0 },
  createdAt: { type: Date, default: Date.now }
});

2. URL Generation

Instead of using complex algorithms, we opted for nanoid, which provides:

  • Short, unique IDs
  • No collisions (practically)
  • URL-safe characters

3. The API

We implemented three main endpoints:

// Create short URL
app.post('/api/shorten', async (req, res) => {
  const shortUrl = nanoid(8);
  const urlDoc = await Url.create({
    originalUrl: url,
    shortUrl
  });
  res.json(urlDoc);
});

// Get URL stats
app.get('/api/stats/:shortUrl', async (req, res) => {
  const urlDoc = await Url.findOne({ shortUrl: req.params.shortUrl });
  res.json(urlDoc);
});

// Handle redirects
app.get('/:shortUrl', async (req, res) => {
  const urlDoc = await Url.findOne({ shortUrl: req.params.shortUrl });
  urlDoc.clicks++;
  await urlDoc.save();
  res.redirect(urlDoc.originalUrl);
});

4. Serverless Deployment

Vercel made deployment incredibly simple. The key was properly configuring our Express app for serverless:

// Handle both API and static files
app.use(express.static('public'));
export default app;

Challenges and Solutions

During development, we encountered and solved several interesting challenges:

  1. MongoDB Connection: Initially, we had issues with MongoDB connections in the serverless environment. The solution was proper connection handling and error management.
  2. Route Handling: Vercel’s routing needed special attention to handle both API endpoints and the frontend correctly.
  3. Statistics Updates: Ensuring atomic updates for click counting required careful consideration of MongoDB operations.

Future Improvements

The current implementation is solid but could be enhanced with:

  1. Custom short URLs
  2. User authentication
  3. QR code generation
  4. Advanced analytics
  5. API rate limiting

Try It Yourself

The project is open source and available on GitHub: URL Shortener Project

You can see it in action here: Live Demo

Conclusion

Building a URL shortener was both fun and educational. It demonstrates how modern web technologies can come together to create something useful in a short time. The serverless deployment aspect makes it particularly interesting, as it shows how to build scalable applications without managing servers.

What features would you add to this URL shortener? Let me know in the comments below!


P.S. All the code is available on GitHub, and I encourage you to fork it, enhance it, and make it your own. If you build something cool with it, I’d love to hear about it!

Co-written with Claude 3.5 Sonnet

This post and the accompanying URL shortener project were developed in collaboration with Claude 3.5 Sonnet, an AI assistant from Anthropic. Claude helped architect the solution, write the code, and structure this blog post. While I implemented and tested the solution, made key technical decisions, and deployed the final product, I believe in being transparent about AI collaboration in both development and content creation.

The complete source code is available on GitHub.