← Projekty
2026Aktivní

Spinjitzu API

Svět Ninjago má neobyčejně bohatou historii a lore, avšak dosud chyběl jakýkoli strukturovaný způsob, jak v těchto datech vyhledávat. Spinjitzu API je veřejné REST API, které tuto mezeru zaplňuje. Poskytuje strukturovaná data o postavách, sériích, elementech, zbraních, lokacích a říších s podporou filtrování, stránkováním a interaktivní dokumentace OpenAPI. K projektu jsem přistupoval jako k plnohodnotné veřejné službě: navrhl jsem jednotnou strukturu odpovědí (response envelopes), důslednou validaci, rate limiting, zabezpečení pomocí JWT, testování, kontejnerizaci v Dockeru a serverless nasazení.

  • NestJS
  • TypeScript
  • PostgreSQL
  • Neon
  • Drizzle ORM
  • Passport
  • Zod
  • class-validator
  • Jest
  • Docker
  • Swagger / OpenAPI

Náhled projektu

Spinjitzu API — project preview screenshot

Kontext

Sérii Ninjago sleduji už řadu let. Když jsem pro jeden ze svých nápadů hledal veřejné API s daty o postavách, sériích nebo elementech, zjistil jsem, že neexistuje nic použitelného – tak jsem se rozhodl ho vybudovat sám. I když je téma ryze neformální, technické zpracování muselo splňovat standardy reálného produkčního projektu: od jasně definovaných kontraktů a bezpečnostních bariér přes rate limiting až po kompletní dokumentaci a robustní nasazení.

Technický přístup

  • Modulární struktura organizovaná podle funkcí (feature-first) s průchodem Controller → Service → Drizzle → PostgreSQL. Vzor Repository jsem se rozhodl vynechat, dokud pro něj nevznikne reálné opodstatnění.
  • Neon serverless Postgres s využitím HTTP ovladače, který byl zvolen pro optimální kompatibilitu a výkon v bezserverovém (serverless) prostředí Vercelu.
  • Centralizované sjednocení struktury odpovědí pomocí globálního interceptoru a filtru výjimek (exception filter) zajišťující, že každý endpoint vrací identický formát pro úspěšné i chybové stavy.
  • Vlastní složené dekorátory (např. @AdminWrite()), které u zápisových endpointů elegantně sdružují ověření JWT tokenu, kontrolu rolí, přísnější rate limiting pro zápis a pravidla pro produkční deaktivaci či skrytí.

Výzvy

  • Správný návrh a modelování vazeb typu many-to-many mezi postavami, elementy, zbraněmi a sériemi. Data musela zůstat historicky přesná, přestože se v průběhu času mění majitelé zbraní, jejich schopnosti či jednotlivé éry příběhu.
  • Hledání příčiny konfliktu mezi verzováním API v NestJS a globálním prefixem, který znefunkčnil neverzovaný kořenový endpoint. Problém jsem vyřešil konfigurací směrování jako VERSION_NEUTRAL.
  • Zajištění spolehlivého načítání statických souborů pro Swagger UI v serverless prostředí na platformě Vercel, čehož jsem docílil servírováním CSS a JS souborů z veřejné CDN sítě namísto spoléhání se na dynamické cesty v lokálním balíčku.
  • Rozhodnutí, které funkce je v produkci nutné zcela deaktivovat a které stačí pouze skrýt. Administrační trasy a přihlašování jsou v produkčním režimu nekompromisně blokovány vlastním autorizačním strážcem (DisabledInProductionGuard) a nezmizely tak pouze z OpenAPI dokumentace.

Co jsem se naučil

  • Osobní vztah k tématu byl skvělým motorem pro dokončení projektu. Publikace ve formě veřejně přístupného API však i tak vyžadovala stejně precizní architektonická rozhodnutí jako při návrhu komerčních B2B služeb.
  • Vedení podrobného architektonického deníku a záznamu rozhodnutí (decision log v souboru AGENTS.md) již od počáteční fáze mi pomohlo jasně definovat technologické kompromisy a udržet konzistentní směr napříč celým vývojem.
  • Bezserverové (serverless) nasazení odhalí skryté předpoklady frameworku týkající se servírování statických souborů a práce s vnitřní pamětí, které se při běhu na klasickém, nepřetržitě běžícím serveru vůbec neprojeví.
  • Doporučení z automatizovaných bezpečnostních auditů je vždy nutné posuzovat v širším kontextu. Zatímco některé nálezy (např. ošetření souběhu u unikátních databázových omezení) byly klíčové, jiné (jako zákaz divokých karet u CORS) nedávaly u veřejného, převážně čtecího API žádný smysl.
  • Zavedení osobních přístupových tokenů (Personal Access Tokens) sdílejících hlavičku Authorization s JWT je naplánováno do verze v2. Implementace složité hybridní autentizace před dokončením stabilního čtecího rozhraní by byla předčasným rozhodnutím.

Hlavní funkce

  • Kompletní CRUD operace pro 6 relačně propojených entit se složitými vazbami typu many-to-many (postavy ↔ elementy, zbraně, série)
  • Autentizace pomocí JWT s ochranou přístupu na základě uživatelských rolí (role-based guards). Administrační zápisy jsou v produkčním prostředí striktně zablokovány přímo v autorizační vrstvě, nikoli pouze skryty v dokumentaci
  • Víceúrovňový rate limiting (např. 200 požadavků pro čtení, 20 pro zápis, 5 pro autentizaci za minutu) s možností specifického přepsání (throttler overrides) u jednotlivých tras
  • Jednotný formát úspěšných odpovědí se strukturou {data, meta} a konzistentní chybové obálky (error envelopes) napříč všemi endpointy
  • Verzování API pomocí URI, což umožňuje bezproblémový souběh verzí v1 a v2 bez rizika narušení funkčnosti u stávajících uživatelů
  • Jednotkové testy s mockováním databázové vrstvy Drizzle pokrývající aplikační logiku a autentizaci. Interaktivní dokumentace OpenAPI na adrese /docs

Další projekt

Minimal E-Shop

Full-stack e-commerce demo se Spring Bootem, platbami přes Stripe a dockerizovaným backendem.

Zobrazit projekt