LinkShort
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/mereturns 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_secondsper link; expired links answer410 Gonewhile stats stay viewable - Per-user URLs —
/urls/mylists your links; deletes are owner-scoped - 302 redirects —
/urls/r/{code}redirects to the target with a click recorded - Public stats —
/urls/{code}/statsreturns target + click count - SPA serving — FastAPI mounts the built React app and falls back to
index.htmlfor 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
- Getting Started — local setup and first run
- API Reference — every endpoint with requests/responses
- Deployment — Docker, environments, production notes