2026-08-23 10:55:32 +01:00
|
|
|
/**
|
|
|
|
|
* Reading feature flags.
|
|
|
|
|
*
|
|
|
|
|
* Server-side only. No flag value reaches the browser bundle, and there is no
|
|
|
|
|
* Unleash dependency in package.json — the SDK lives in FastAPI, which already
|
|
|
|
|
* owns every other piece of data this app renders.
|
|
|
|
|
*
|
|
|
|
|
* Flags are declared in backend/flags.py. A purely front-end flag still has to
|
|
|
|
|
* be declared there; it is a flat data edit, and the return is that one list
|
|
|
|
|
* answers "what flags exist" for the whole system.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
export type Flags = Record<string, boolean>;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Reading flags pins the calling route to this ISR floor: Next uses the LOWEST
|
|
|
|
|
* revalidate among a route's fetches to set the whole route's revalidation
|
|
|
|
|
* frequency. 300s matches what /school/[slug] already sits at, so a page that
|
|
|
|
|
* reads flags is no more dynamic than a school page already is.
|
|
|
|
|
*
|
|
|
|
|
* It is also what makes a flip propagate without a webhook: five minutes on
|
|
|
|
|
* school pages, an hour on place pages, against flags that flip monthly.
|
|
|
|
|
*/
|
|
|
|
|
export const FLAGS_REVALIDATE = 300;
|
|
|
|
|
|
|
|
|
|
const API = process.env.FASTAPI_URL || process.env.NEXT_PUBLIC_API_URL
|
|
|
|
|
|| 'http://localhost:8000/api';
|
|
|
|
|
|
2026-09-08 17:12:25 +01:00
|
|
|
/**
|
|
|
|
|
* Every flag and its value. Never throws: an unreadable flag is a dark one.
|
|
|
|
|
*
|
|
|
|
|
* `revalidate` is the caller's, because reading flags pins the whole route to
|
|
|
|
|
* the lowest revalidate among its fetches. Every SEO route here declares
|
|
|
|
|
* 604800; gating one at the 300s default would drop it from a weekly cache to
|
|
|
|
|
* a 5-minute one. Pass the route's own floor and gating costs it nothing.
|
|
|
|
|
*
|
|
|
|
|
* The trade is flag-flip latency: a route that revalidates weekly takes up to
|
|
|
|
|
* a week to notice a flip. Pass a smaller number where a flip must land fast.
|
|
|
|
|
*/
|
|
|
|
|
export async function getFlags(revalidate: number = FLAGS_REVALIDATE): Promise<Flags> {
|
2026-08-23 10:55:32 +01:00
|
|
|
try {
|
|
|
|
|
const res = await fetch(`${API}/flags`, {
|
2026-09-08 17:12:25 +01:00
|
|
|
next: { revalidate },
|
2026-08-23 10:55:32 +01:00
|
|
|
});
|
|
|
|
|
if (!res.ok) return {};
|
|
|
|
|
return await res.json();
|
|
|
|
|
} catch {
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
}
|