Skip to content

Config, Health, Themes, Push & Recommendations

Unauthenticated. Public runtime config for frontend bootstrapping:

{ "apiUrl": "...", "domain": "...", "siteTitle": "...", "registrationIsOpen": true }

CORS-open (Access-Control-Allow-Origin: *, so the setup wizard can poll it cross-origin during install) liveness check. Returns 200 with { status: "ok", timestamp, services: { mongodb: "connected" } }, or 503 with status: "error" if MongoDB is disconnected.

Three built-in themes (system, kowloon-light, kowloon-dark) are seeded on module load if missing, and the seed self-heals -- any previously-seeded author: "system" theme no longer in the current built-in list is deleted automatically. Custom admin-authored themes are never touched by this.

Public. Returns all themes (built-in ones first) plus defaultThemeId.

Public. 404 if not found.

Admin only (401/403). Body:

{ "id": "...", "name": "...", "colorScheme": "...", "description": "...", "colors": { ... }, "postColors": { ... } }

id/name/colorScheme required. 409 on duplicate id.

Admin only. 403 if the target is a built-in theme -- built-ins are immutable. Whitelisted fields: name, description, colorScheme, colors, postColors.

Admin only. 403 if built-in.

Admin only. Body { themeId } -- must reference an existing theme. Sets the defaultTheme setting.

Auth required. Body:

{ "token": "...", "provider": "expo", "platform": "android" }

(provider defaults to "expo" -- the other accepted value is "native"; platform defaults to "android", also accepts "ios"/"web".)

Upserts by token -- one row per device. Re-registering the same token under a different user reassigns ownership, which is what makes device account-switching work correctly. 400 missing token.

Auth required. Body { token }. Deletes the token row, scoped to the current user.

The public "Discover" surface -- see also project_recommendations_discover internal notes if you're the server operator curating shelves via /admin/recommendations.

Unauthenticated OK. Returns active RecommendationSections in order, each resolved to its live, currently-visible items.

Curated Recommendation references are resolved against Post (via FeedItems), Circle, Group, Bookmark, Page, or FederatedServer. Items whose target was deleted, or whose visibility narrowed since curation, are silently dropped -- nothing about a recommendation is snapshotted except the tier it had at add-time; the live object is always the source of truth at read time.

Viewer-aware tiering matches /posts//circles -- local-authenticated sees public+server, everyone else sees public only.

Sections with source: "hybrid" or "heuristic" and a contentType get algorithmic backfill (getHeuristicPicks) up to targetCount, excluding already-curated refs. Empty shelves (nothing curated and nothing to backfill) are omitted from the response entirely, rather than returned empty.

Media-type shelves get their first attachment's kind (image/video/audio) resolved and exposed as mediaKind/mediaUrl on each item.

Also returns a top-level background value (the discoverBackground setting) for the Discover page's backdrop.

{
"@context": "...",
"type": "Collection",
"background": "...",
"sections": [
{ "id": "...", "name": "...", "slug": "...", "summary": "...", "contentType": "...", "source": "...", "targetCount": 10, "order": 0, "items": [ ... ] }
]
}