WIP! A BB-style forum, on the ATmosphere!
We're still working... we'll be back soon when we have something to show off!
node
typescript
hono
htmx
atproto
1import type { MiddlewareHandler } from "hono";
2import type { WebAppEnv } from "../lib/theme-resolution.js";
3import { resolveTheme, FALLBACK_THEME } from "../lib/theme-resolution.js";
4import { ThemeCache } from "../lib/theme-cache.js";
5import { logger } from "../lib/logger.js";
6
7const DEFAULT_CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes
8
9export function createThemeMiddleware(
10 appviewUrl: string,
11 cacheTtlMs: number = DEFAULT_CACHE_TTL_MS
12): MiddlewareHandler<WebAppEnv> {
13 // Intentionally outside the request handler: one shared instance per server
14 // startup. Moving this inside the handler would create a new cache per
15 // request, silently defeating the feature.
16 const cache = new ThemeCache(cacheTtlMs);
17 return async (c, next) => {
18 const cookieHeader = c.req.header("Cookie");
19 const colorSchemeHint = c.req.header("Sec-CH-Prefers-Color-Scheme");
20 let theme;
21 try {
22 theme = await resolveTheme(appviewUrl, cookieHeader, colorSchemeHint, cache);
23 } catch (error) {
24 logger.error("createThemeMiddleware: resolveTheme threw unexpectedly — using fallback", {
25 operation: "createThemeMiddleware",
26 error: error instanceof Error ? error.message : String(error),
27 });
28 theme = FALLBACK_THEME;
29 }
30 c.set("theme", theme);
31 await next();
32 };
33}