LinkShort
LinkShort (repository: `FastAPI-url`) is a complete URL-shortening service with a Python/FastAPI API, JWT-based authentication, per-user link
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/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