Skip to content

Custom toy URL Shortener I made a long time ago. Seeing if I can try and deploy

Notifications You must be signed in to change notification settings

Addy-Da-Baddy/FermiURL

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FermiURL

A minimalistic, production-ready URL shortener application built with modern web technologies including React, Vite, ShadCN UI, Flask, and MariaDB.

Features

  • Clean and minimalistic user interface
  • Fast URL shortening with MD5-based hash generation
  • Click tracking and analytics
  • One-to-one URL mapping (duplicate URLs return the same short code)
  • Copy to clipboard functionality
  • RESTful API design
  • Containerized deployment with Docker
  • Database persistence with MariaDB

Tech Stack

Frontend:

  • React 19 with TypeScript
  • Vite (build tool)
  • ShadCN UI component library
  • Tailwind CSS for styling
  • Lucide React for icons

Backend:

  • Python 3.11
  • Flask web framework
  • Flask-CORS for cross-origin resource sharing
  • MySQL Connector for database operations
  • Python-dotenv for environment configuration

Database:

  • MariaDB 12.0
  • Indexed schema for optimized queries

Prerequisites

Docker Deployment (Recommended)

  • Docker Desktop (Windows, macOS, or Linux)
  • 4GB RAM minimum
  • 10GB free disk space

Local Development

  • Node.js v18 or higher
  • Python 3.8 or higher
  • MariaDB 10.5 or MySQL 8.0 or higher
  • Git (for version control)

Installation and Setup

Option 1: Docker Deployment (Recommended)

Docker provides the simplest and most reliable deployment method as it handles all dependencies automatically.

Step 1: Verify Docker Installation

Ensure Docker Desktop is installed and running:

docker --version
docker-compose --version

If Docker is not installed, download it from Docker Desktop.

Step 2: Start the Application

Navigate to the project directory and run:

cd C:\smallurl
.\docker-start.ps1

Alternatively, use docker-compose directly:

docker-compose up --build

To run in detached mode (background):

docker-compose up -d --build

Step 3: Verify Services

The following services will be available:

Step 4: Stop the Application

To stop all services:

# If running in foreground, press Ctrl+C

# If running in background:
docker-compose down

# To stop and remove all data (including database):
docker-compose down -v

Option 2: Local Development Setup

For local development without Docker, follow these steps:

Step 1: Database Setup

Start your MariaDB/MySQL service and create the database:

# Connect to MariaDB
mysql -u root -p

# Create database and table
source backend/init_db.sql

Or manually execute:

CREATE DATABASE IF NOT EXISTS url_shortener;
USE url_shortener;

CREATE TABLE IF NOT EXISTS urls (
    id INT AUTO_INCREMENT PRIMARY KEY,
    original_url VARCHAR(2048) NOT NULL,
    short_code VARCHAR(10) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    clicks INT DEFAULT 0,
    INDEX idx_short_code (short_code),
    INDEX idx_original_url (original_url(255))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Step 2: Backend Configuration

Navigate to the backend directory:

cd backend

Create a Python virtual environment:

# Windows
python -m venv venv
venv\Scripts\activate

# macOS/Linux
python3 -m venv venv
source venv/bin/activate

Install dependencies:

pip install -r requirements.txt

Configure environment variables by editing the .env file:

DB_HOST=localhost
DB_USER=root
DB_PASSWORD=your_database_password
DB_NAME=url_shortener

Start the Flask backend:

python app.py

The backend API will be available at http://localhost:5000

Step 3: Frontend Configuration

Open a new terminal and navigate to the frontend directory:

cd frontend

Install Node.js dependencies:

npm install

Start the Vite development server:

npm run dev

The frontend application will be available at http://localhost:5173

Usage Guide

Shortening a URL

  1. Navigate to http://localhost:5173
  2. Enter a long URL in the input field (e.g., https://example.com/very/long/path)
  3. Click the "Shorten URL" button
  4. Copy the generated short URL using the copy button
  5. Share the shortened URL

Accessing a Shortened URL

Visit the shortened URL (e.g., http://localhost:5000/abc123) and you will be automatically redirected to the original URL. Each access increments the click counter.

Viewing Statistics

Access statistics for any shortened URL:

GET http://localhost:5000/stats/abc123

Response:

{
  "original_url": "https://example.com/very/long/path",
  "short_code": "abc123",
  "created_at": "2025-11-18T10:30:00",
  "clicks": 42
}

API Documentation

Endpoints

POST /shorten

Creates a new shortened URL or returns existing short code for duplicate URLs.

Request:

{
  "url": "https://example.com/very/long/url"
}

Response (201 Created or 200 OK):

{
  "short_code": "abc123"
}

Error Response (400 Bad Request):

{
  "error": "URL is required"
}

GET /{short_code}

Redirects to the original URL and increments the click counter.

Response: HTTP 302 redirect to original URL

Error Response (404 Not Found): "URL not found"

GET /stats/{short_code}

Retrieves statistics for a shortened URL.

Response (200 OK):

{
  "original_url": "https://example.com/very/long/url",
  "short_code": "abc123",
  "created_at": "2025-11-18T10:30:00",
  "clicks": 42
}

Error Response (404 Not Found):

{
  "error": "URL not found"
}

GET /health

Health check endpoint for monitoring.

Response (200 OK):

{
  "status": "healthy",
  "database": "connected"
}

Error Response (500 Internal Server Error):

{
  "status": "unhealthy",
  "database": "disconnected"
}

Architecture Overview

System Flow

  1. URL Shortening Process:

    • User submits a URL via the frontend
    • Frontend sends POST request to /shorten endpoint
    • Backend validates and normalizes the URL
    • Backend checks database for existing entry
    • If URL exists, returns existing short code
    • If new, generates MD5 hash (first 6 characters) as short code
    • Handles hash collisions with retry mechanism
    • Stores mapping in database
    • Returns short code to frontend
  2. URL Redirection Process:

    • User accesses shortened URL
    • Backend queries database for short code
    • If found, increments click counter and redirects (HTTP 302)
    • If not found, returns 404 error
  3. Database Schema:

    • id: Auto-incrementing primary key
    • original_url: Full URL (up to 2048 characters)
    • short_code: 6-character unique identifier (indexed)
    • created_at: Timestamp of creation
    • clicks: Number of times accessed
    • Indexes on short_code and original_url for query optimization

Troubleshooting

Docker Issues

Docker Desktop Not Running

Error:

error during connect: Get "http://%2F%2F.%2Fpipe%2FdockerDesktopLinuxEngine/v1.51/...": 
open //./pipe/dockerDesktopLinuxEngine: The system cannot find the file specified.

Solution:

  1. Open Docker Desktop from the Start Menu
  2. Wait for the Docker icon in the system tray to stop animating
  3. Verify Docker is running: docker info
  4. Run the application again

Port Already in Use

Error:

Bind for 0.0.0.0:5000 failed: port is already allocated

Solution:

Find and stop the process using the port:

# Find process using port
netstat -ano | findstr :5000

# Stop the process (replace PID with actual process ID)
taskkill /PID <PID> /F

Or change the port in docker-compose.yml:

services:
  backend:
    ports:
      - "5001:5000"  # Change host port to 5001

Container Build Failures

Error:

failed to solve with frontend dockerfile.v0

Solution:

Clear Docker cache and rebuild:

# Remove all containers and images
docker-compose down -v --rmi all

# Rebuild from scratch
docker-compose up --build --force-recreate

Database Connection Issues

Error in backend logs:

Error connecting to MariaDB: Can't connect to MySQL server

Solution:

  1. Wait for database initialization (takes 10-15 seconds on first run)
  2. Check database health:
    docker-compose ps
  3. View database logs:
    docker-compose logs database
  4. Restart database container:
    docker-compose restart database

Local Development Issues

Python Virtual Environment Issues

Error:

'python' is not recognized as an internal or external command

Solution:

Ensure Python is installed and in PATH:

# Check Python installation
python --version

# Or try
python3 --version

# Add to PATH if needed (Windows)
# Control Panel > System > Advanced > Environment Variables

MariaDB Connection Refused

Error:

mysql.connector.errors.DatabaseError: 2003: Can't connect to MySQL server

Solution:

  1. Verify MariaDB is running:

    # Windows
    Get-Service -Name MariaDB
    
    # Start if stopped
    Start-Service -Name MariaDB
  2. Check credentials in .env file

  3. Verify database exists:

    SHOW DATABASES;

Frontend CORS Errors

Error in browser console:

Access to fetch at 'http://localhost:5000/shorten' from origin 'http://localhost:5173' 
has been blocked by CORS policy

Solution:

  1. Ensure Flask-CORS is installed:

    pip install flask-cors
  2. Verify CORS is enabled in backend/app.py:

    from flask_cors import CORS
    app = Flask(__name__)
    CORS(app)
  3. Restart the backend server

Node Modules Installation Failures

Error:

npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree

Solution:

Clear npm cache and reinstall:

# Clear npm cache
npm cache clean --force

# Delete node_modules and package-lock.json
rm -rf node_modules package-lock.json

# Reinstall
npm install

# Or use legacy peer deps
npm install --legacy-peer-deps

Common Application Issues

Short URLs Not Working After Server Restart

Issue: Previously generated short URLs return 404 after restarting Docker.

Cause: Database volume was removed with docker-compose down -v

Solution:

  • Use docker-compose down (without -v flag) to preserve data
  • To persist data permanently, the MariaDB volume is already configured in docker-compose.yml

Frontend Shows "Failed to Connect to Server"

Solution:

  1. Verify backend is running:

    curl http://localhost:5000/health
  2. Check backend logs:

    docker-compose logs backend
  3. Ensure correct API URL in frontend/src/App.tsx (should be http://localhost:5000)

Production Deployment

Environment Configuration

For production deployment, update the following:

  1. Frontend API URL (frontend/src/App.tsx):

    const response = await fetch('https://api.yourdomain.com/shorten', {
      // ...
    })
  2. Backend Environment (.env):

    DB_HOST=production-database-host
    DB_USER=production_user
    DB_PASSWORD=strong_password_here
    DB_NAME=url_shortener
    FLASK_ENV=production
  3. Security Considerations:

    • Use HTTPS for all connections
    • Enable rate limiting on API endpoints
    • Use strong database passwords
    • Configure firewall rules
    • Regular database backups
    • Enable logging and monitoring

Building for Production

# Build frontend
cd frontend
npm run build

# The dist/ folder contains production-ready files

Development

Project Structure

smallurl/
├── backend/
│   ├── app.py              # Flask application
│   ├── requirements.txt    # Python dependencies
│   ├── Dockerfile          # Backend container config
│   ├── .env               # Environment variables
│   └── init_db.sql        # Database schema
├── frontend/
│   ├── src/
│   │   ├── App.tsx        # Main React component
│   │   ├── components/    # UI components
│   │   └── lib/           # Utilities
│   ├── Dockerfile         # Frontend container config
│   ├── package.json       # Node dependencies
│   └── vite.config.ts     # Vite configuration
├── docker-compose.yml     # Multi-container orchestration
├── docker-start.ps1       # Quick start script
└── README.md             # Documentation

Running Tests

# Backend tests (to be implemented)
cd backend
pytest

# Frontend tests (to be implemented)
cd frontend
npm test

Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License. See the LICENSE file for details.

Support

For issues, questions, or contributions, please open an issue on the GitHub repository.

Acknowledgments

  • ShadCN UI for the component library
  • Flask framework for the backend
  • Vite for the blazing-fast development experience
  • MariaDB for reliable data persistence

About

Custom toy URL Shortener I made a long time ago. Seeing if I can try and deploy

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published