diff --git a/apps/api/src/controllers/publicController.ts b/apps/api/src/controllers/publicController.ts index 7aa46e6..5d03f0e 100644 --- a/apps/api/src/controllers/publicController.ts +++ b/apps/api/src/controllers/publicController.ts @@ -27,6 +27,7 @@ export async function listPosts(_req: Request, res: Response) { items: posts.map((p) => toPostDTO(p, false, true)), nextCursor: hasMore ? (posts[posts.length - 1]?._id.toString() ?? null) : null, }; - res.set("Cache-Control", "public, max-age=30"); + // Everyone gets the same answer, so the CDN may serve it for a minute and refresh in the background. + res.set("Cache-Control", "public, max-age=30, s-maxage=60, stale-while-revalidate=300"); res.json(body); } diff --git a/apps/web/index.html b/apps/web/index.html index e2f67ad..f77d16f 100644 --- a/apps/web/index.html +++ b/apps/web/index.html @@ -4,19 +4,19 @@ -
Loading Commune…
An open source community platform. Share posts, follow people, join communities and read the latest news.
+Loading…
} + {query.isLoading && ( +{query.error.message}
} {query.isSuccess && posts.length === 0 &&{emptyMessage}
} {posts.map((post) => ( diff --git a/apps/web/src/lib/api.ts b/apps/web/src/lib/api.ts index 93c73f7..0e4c244 100644 --- a/apps/web/src/lib/api.ts +++ b/apps/web/src/lib/api.ts @@ -1,72 +1,127 @@ import type { AuthResponse } from "@commune/shared"; -// Production builds call the same origin ("/api"), which Vercel forwards to the API (see -// apps/web/vercel.json). That keeps the login cookie first-party. Local dev talks to :4000. -const BASE = - import.meta.env.VITE_API_URL ?? (import.meta.env.PROD ? "/api" : "http://localhost:4000/api"); +// Production builds always call the same origin ("/api"), which Vercel forwards to the API +// (see apps/web/vercel.json). That keeps the login cookie first-party. VITE_API_URL is only +// used in development, so a stray value in the hosting dashboard can't break a deployed site. +const BASE = import.meta.env.PROD + ? "/api" + : (import.meta.env.VITE_API_URL ?? "http://localhost:4000/api"); // Uploaded files are served from the API origin, e.g. http://localhost:4000/uploads/abc.png. // With a relative VITE_API_URL such as "/api" this is "", so "/uploads/..." stays relative. const ORIGIN = BASE.replace(/\/api\/?$/, ""); let accessToken: string | null = null; -let refreshing: Promise