Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .claude/rules/server-apps.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,10 @@ area: webapp
type: fix
---

Fix pages occasionally loading unstyled during deploys. The dashboard now recovers automatically.
Brief description of what changed and why.
EOF
```

- **area**: `webapp` | `supervisor`
- **type**: `feature` | `fix` | `improvement` | `breaking`
- If the PR also touches `packages/`, just the changeset is sufficient (no `.server-changes/` needed).

The body ships **verbatim in user-facing release notes**. Keep it to 1–2 short sentences, non-technical, written for a dashboard user: describe what changed for them, never the implementation (no header names, endpoints, middleware, storage mechanisms, internal tools). See `.server-changes/README.md` for full guidance.
6 changes: 0 additions & 6 deletions .server-changes/stale-deploy-asset-recovery.md

This file was deleted.

272 changes: 0 additions & 272 deletions apps/webapp/app/components/StaleAssetRecovery.tsx

This file was deleted.

6 changes: 0 additions & 6 deletions apps/webapp/app/entry.server.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,6 @@ export default function handleRequest(
) {
const url = new URL(request.url);

// Stale documents reference /build asset hashes that 404 after a deploy —
// always revalidate HTML. Route-set headers win.
if (!responseHeaders.has("Cache-Control")) {
responseHeaders.set("Cache-Control", "no-cache");
}

if (url.pathname.startsWith("/login")) {
responseHeaders.set("X-Frame-Options", "SAMEORIGIN");
responseHeaders.set("Content-Security-Policy", "frame-ancestors 'self'");
Expand Down
8 changes: 0 additions & 8 deletions apps/webapp/app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import type { ToastMessage } from "~/models/message.server";
import { commitSession, getSession } from "~/models/message.server";
import tailwindStylesheetUrl from "~/tailwind.css";
import { RouteErrorDisplay } from "./components/ErrorDisplay";
import { StaleAssetRecovery } from "./components/StaleAssetRecovery";
import { AppContainer, MainCenteredContainer } from "./components/layout/AppLayout";
import { ShortcutsProvider } from "./components/primitives/ShortcutsProvider";
import { Toast } from "./components/primitives/Toast";
Expand All @@ -19,11 +18,6 @@ import { getUser } from "./services/session.server";
import { getTimezonePreference } from "./services/preferences/uiPreferences.server";
import { appEnvTitleTag } from "./utils";

// Derived here (not inside StaleAssetRecovery) so the shared component takes
// the flag as a prop. NODE_ENV is statically replaced in browser bundles, and
// the ErrorBoundary can't rely on loader data.
const isProduction = process.env.NODE_ENV === "production";

export const links: LinksFunction = () => {
return [{ rel: "stylesheet", href: tailwindStylesheetUrl }];
};
Expand Down Expand Up @@ -105,7 +99,6 @@ export function ErrorBoundary() {
<head>
<meta charSet="utf-8" />

<StaleAssetRecovery isProduction={isProduction} />
<Meta />
<Links />
</head>
Expand All @@ -132,7 +125,6 @@ export default function App() {
<>
<html lang="en" className="h-full" data-theme="dark">
<head>
<StaleAssetRecovery isProduction={isProduction} />
<Meta />
<Links />
</head>
Expand Down
17 changes: 0 additions & 17 deletions apps/webapp/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,23 +134,6 @@ if (ENABLE_CLUSTER && cluster.isPrimary) {
const port = process.env.REMIX_APP_PORT || process.env.PORT || 3000;

if (process.env.HTTP_SERVER_DISABLED !== "true") {
// Stamp every response with the build this replica is running. The
// client-side stale-asset recovery reads it from Remix loader fetches to
// turn an ordinary navigation into a full document load when the server
// has moved to a new build.
app.use((_req, res, next) => {
res.set("X-Build-Id", build.assets.version);
next();
});

// Reports the build this replica is running. The client-side stale-asset
// recovery polls it after a /build 404 and reloads only once the server
// reports a different build than the one the page was rendered with.
app.get("/build-version", (_req, res) => {
res.set("Cache-Control", "no-store");
res.json({ version: build.assets.version });
});

const socketIo: { io: IoServer } | undefined = build.entry.module.socketIo;
const wss: WebSocketServer | undefined = build.entry.module.wss;
const apiRateLimiter: RateLimitMiddleware = build.entry.module.apiRateLimiter;
Expand Down