GitHub โ†—

LinkShort

๐Ÿงช View animated test results โ€” 15/15 โ†’

A production-ready URL shortener โ€” FastAPI backend, JWT auth, click tracking, React 19 SPA, SQLite.

LinkShort (repository: FastAPI-url) is a complete URL-shortening service with a Python/FastAPI API, JWT-based authentication, per-user link management, click statistics, and a served single-page application frontend.

Stack: FastAPI (Python) ยท SQLAlchemy ยท SQLite ยท JWT (python-jose) ยท React 19 SPA (static files served by FastAPI) ยท pytest

Highlights

  • Full auth flow โ€” register โ†’ login โ†’ JWT bearer tokens; /auth/me returns the current user
  • 6-character short codes โ€” cryptographically random (secrets), with collision retry
  • Click tracking โ€” every redirect increments the click counter
  • Link expiration โ€” optional expires_in_seconds per link; expired links answer 410 Gone while stats stay viewable
  • Per-user URLs โ€” /urls/my lists your links; deletes are owner-scoped
  • 302 redirects โ€” /urls/r/{code} redirects to the target with a click recorded
  • Public stats โ€” /urls/{code}/stats returns target + click count
  • SPA serving โ€” FastAPI mounts the built React app and falls back to index.html for client-side routing
  • CORS open โ€” allow_origins=["*"] for development

Tech stack

Layer Technology
API FastAPI (app = FastAPI(title="URL Shortener", version="1.0.0"))
ORM SQLAlchemy (Base.metadata.create_all on startup)
Database SQLite
Auth JWT bearer tokens (python-jose)
Password hashing app/auth.py (hashed, never stored plaintext)
Frontend React 19 SPA in backend/static/
Tests pytest (tests/test_api.py)

API surface

Method Path Auth Description
POST /auth/register โ€” Create account, receive JWT
POST /auth/login โ€” Authenticate, receive JWT
GET /auth/me Bearer Current user profile
POST /urls/shorten Bearer Shorten a URL
GET /urls/my Bearer List your URLs (newest first)
GET /urls/{code}/stats โ€” Public click stats
DELETE /urls/{code} Bearer Delete your URL (owner-scoped)
GET /urls/r/{code} โ€” 302 redirect + click count
GET /health โ€” Liveness probe

Repository layout

FastAPI-url/
โ”œโ”€โ”€ app/
โ”‚   โ”œโ”€โ”€ main.py            # FastAPI app, CORS, SPA serving
โ”‚   โ”œโ”€โ”€ auth.py            # JWT creation/verification, password hashing
โ”‚   โ”œโ”€โ”€ database.py        # SQLAlchemy engine + session
โ”‚   โ”œโ”€โ”€ models.py          # User, URL models
โ”‚   โ”œโ”€โ”€ schemas.py         # Pydantic schemas (UserCreate, Token, URLOut, URLStats)
โ”‚   โ”œโ”€โ”€ config.py          # Settings
โ”‚   โ””โ”€โ”€ routers/
โ”‚       โ”œโ”€โ”€ auth_router.py # /auth/* endpoints
โ”‚       โ””โ”€โ”€ urls.py        # /urls/* endpoints
โ”œโ”€โ”€ backend/static/        # Built React SPA (served by FastAPI)
โ”œโ”€โ”€ tests/
โ”‚   โ””โ”€โ”€ test_api.py        # API integration tests
โ””โ”€โ”€ ...

Short-code generation

def gen_short() -> str:
    chars = string.ascii_letters + string.digits
    return ''.join(secrets.choice(chars) for _ in range(6))

6 characters from a 62-char alphabet โ‰ˆ 5.7ร—10ยนโฐ combinations; collisions are checked and retried against the database.

Related pages