import os from fastapi import FastAPI from fastapi.responses import RedirectResponse from scalar_fastapi import get_scalar_api_reference from app.routes import discovery, reviews, stats ROOT_PATH = os.environ.get("ROOT_PATH", "") DESCRIPTION = """ Hi, this is a read-only API exposing 20+ years of my personal media reviews of movies, books, and television since 2001. This API provides structured access to a personal media review database. Every review includes a date, category, title, creator, genre, rating, and optional written commentary. ## Rating scale Ratings use a **-3.0 to 3.0** scale: | Rating | Meaning | |--------|---------| | 3.0 | Masterpiece, tears flowed | | 2.0 | Great, I was glowing for a day | | 1.0 | Good enough use of my time | | 0.0 | Meh, a void of space | | -1.0 | Below average, should have spent this time knitting | | -2.0 | Bad, I want someone to pay me for this | | -3.0 | Terrible, I felt like I needed to use toilet paper after | ## Getting started - Browse available categories, genres, and creators via the **Discovery** endpoints - Fetch reviews with filtering and pagination via **GET /reviews** - Explore aggregate statistics via the **Statistics** endpoints - Get a surprise recommendation via **GET /reviews/random** ## About This API is a portfolio project demonstrating API design and documentation skills. Built with [FastAPI](https://fastapi.tiangolo.com/) and documented with [Scalar](https://scalar.com/). To see release notes, go to the [Releases](https://gugulet.hu/technical/git/g_it/api/releases) page. """ CUSTOM_CSS = """ .darklight-reference-promo { display: none !important; } .light-mode { --scalar-color-1: #343434; --scalar-color-2: #666666; --scalar-color-3: #979797; --scalar-color-accent: #C9C9C9; --scalar-background-1: #FAFAFA; --scalar-background-2: #FFFFFF; --scalar-background-3: #FFFFFF; --scalar-background-accent: #FFFFFF; --scalar-border-color: transparent; } @font-face { font-display: swap; font-family: 'DM Sans'; font-style: normal; font-weight: 100 700; src: url('https://gugulet.hu/technical/git/g_it/site/raw/branch/main/content/assets/fonts/dm-sans.ttf') format('truetype'); } @font-face { font-display: swap; font-family: 'DM Mono'; font-style: normal; font-weight: 100 700; src: url('https://gugulet.hu/technical/git/g_it/site/raw/branch/main/content/assets/fonts/dm-mono.ttf') format('truetype'); } :root { --scalar-font: 'DM Sans', sans-serif; --scalar-font-code: 'DM Mono', monospace; } .darklight-reference > * { display: none !important; } .darklight-reference { padding: 0.75rem !important; display: flex !important; } .darklight-reference::before { content: ''; display: block; width: 32px; height: 32px; background: url('https://gugulet.hu/technical/git/g_it/site/raw/branch/main/content/assets/media/g-logo-250x250.webp') no-repeat center / contain; } """ app = FastAPI( title="Reviews API", description=DESCRIPTION, version="1.1", docs_url=None, redoc_url=None, ) @app.get("/ref", include_in_schema=False) async def scalar_docs(): return get_scalar_api_reference( openapi_url=f"{ROOT_PATH}/openapi.json", title=app.title, force_dark_mode_state="light", hide_dark_mode_toggle=True, with_default_fonts=False, scalar_favicon_url="https://gugulet.hu/technical/git/g_it/site/raw/branch/main/content/assets/media/face-favicon-512x512.png", default_open_all_tags=False, custom_css=CUSTOM_CSS, ) app.include_router(reviews.router) app.include_router(discovery.router) app.include_router(stats.router) @app.get("/", include_in_schema=False) def root_redirect(): return RedirectResponse(url=f"{ROOT_PATH}/ref") @app.get("/health", tags=["System"]) def health_check(): """Verify the API is running.""" return {"status": "ok"}