Current path: {$location.path}
``` --- ## API layer ### Core function: `api()` Located in `frontend/src/lib/api.ts`. Features: - **Request deduplication** — identical concurrent GETs share one promise - **Loading indicator** — drives `activeRequests` store → `LoadingBar` - **Build-version check** — auto-reloads page when server build is newer - **Mock interceptor** — when `__MOCK__` is `true`, routes requests to `frontend/mocking/*.json` - **Sentry integration** — span instrumentation (when enabled) ### Usage patterns ```typescript import { api, getCachedEntries, getCachedEntry, getDBEntries, postDBEntry } from "./lib/api" // Cached (1h TTL, for read-heavy data) const pages = await getCachedEntries<"content">("content", { lang: "de", active: true }) const page = await getCachedEntry<"content">("content", { path: "/about" }) // Uncached const items = await getDBEntries<"content">("content", { type: "blog" }, "sort", 10) // Write const result = await postDBEntry("content", { name: "New Page", active: true }) // Raw API call const { data, count } = await api{$_("hero.subtitle", { values: { name: "World" } })}
``` --- ## Common pitfalls - **Never `spaNavigate()` in SSR** — always guard with `typeof window !== "undefined"`. - **Store subscriptions in modules** — if subscribing to stores outside components, remember to unsubscribe to prevent memory leaks. - **API PUT returns only changed fields** — don't expect a full object back from PUT requests. - **`_id` not `id` for filters** — API filters use MongoDB's `_id`, but response objects may have both `id` and `_id`. - **`$location` strips trailing slashes** — `/about/` becomes `/about` (except root `/`). - **Content cache is 1 hour** — `getCachedEntries` caches in memory for 1h. For admin previews, use `getDBEntries` (uncached).