Skip to content

fix(nginx): add no-cache header for index.html to prevent stale SPA s…#9440

Open
vansh17June wants to merge 1 commit into
makeplane:previewfrom
vansh17June:fix/nginx-index-html-cache-control
Open

fix(nginx): add no-cache header for index.html to prevent stale SPA s…#9440
vansh17June wants to merge 1 commit into
makeplane:previewfrom
vansh17June:fix/nginx-index-html-cache-control

Conversation

@vansh17June

@vansh17June vansh17June commented Jul 19, 2026

Copy link
Copy Markdown

Description

Adds explicit Cache-Control: no-cache, must-revalidate headers for index.html
in the web (apps/web/nginx/nginx.conf) and admin (apps/admin/nginx/nginx.conf)
nginx configs.

index.html is not content-hashed like the files under /assets/*, so without an
explicit cache header, browsers rely on nginx's default heuristic caching. Safari
in particular applies aggressive heuristic caching to responses without an explicit
Cache-Control header, which can cause it to keep serving a stale index.html
indefinitely — even after a bug fix is deployed to production — until the user
manually clears site data.

This was flagged as a secondary finding in #9439 (the Safari/iOS
requestIdleCallback crash issue): even once that crash fix ships in a release,
Safari/iOS users could keep hitting the old broken build because of this caching
gap.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)

Screenshots and Media (if applicable)

N/A — this is a header-only nginx config change, not a UI change.

Test Scenarios

  • Built the nginx image locally and confirmed curl -I http://localhost:3000/index.html
    returns Cache-Control: no-cache, must-revalidate
  • Confirmed /assets/* static chunks are unaffected and still use their existing
    caching behavior
  • Confirmed existing security headers (X-Frame-Options, X-Content-Type-Options,
    Strict-Transport-Security, X-XSS-Protection) are still present on index.html
    responses
  • Verified the app still loads correctly via try_files fallback for both
    apps/web and apps/admin (/god-mode/index.html)

References

Related to #9439

Summary by CodeRabbit

  • Bug Fixes
    • Improved application routing so direct and unresolved URLs correctly load the appropriate app shell.
    • Added security headers to key entry pages.
    • Disabled caching for entry pages to ensure users receive the latest application version.

@CLAassistant

CLAassistant commented Jul 19, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Nginx configurations for the admin and web applications now provide exact-match shell routes with security headers and disabled caching. The admin route returns 404 when missing and serves as the fallback for unresolved requests; the web route remains the SPA fallback target.

Changes

Nginx shell routing

Layer / File(s) Summary
Admin shell route and fallback
apps/admin/nginx/nginx.conf
Adds a non-cached /god-mode/index.html route with security headers and a 404 check, then uses it as the final fallback for unresolved requests.
Web shell headers
apps/web/nginx/nginx.conf
Adds an exact /index.html route with security headers and Cache-Control: no-cache, must-revalidate, while retaining the existing SPA fallback.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: sriramveeraghanta

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding a no-cache header for index.html to prevent stale SPA shells.
Description check ✅ Passed The description follows the template and includes change details, type, screenshots, test scenarios, and references.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
apps/admin/nginx/nginx.conf (1)

29-37: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Align formatting and documentation with the web configuration.

Consider adding the explanatory comment from the web configuration here for consistency, and fixing the minor 1-space indentation offset on the location directive to match the rest of the file.

♻️ Proposed refactor
-     location = /god-mode/index.html {
-      root   /usr/share/nginx/html;
-      add_header X-Frame-Options "DENY" always;
-      add_header X-Content-Type-Options "nosniff" always;
-      add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
-      add_header X-XSS-Protection "1; mode=block" always;
-      add_header Cache-Control "no-cache, must-revalidate" always;
-      try_files $uri =404;
-    }
+    # index.html is not content-hashed like /assets/*, so it must never be
+    # cached long-term. Safari/iOS's aggressive heuristic caching can otherwise
+    # keep serving a stale shell indefinitely, even after a fix is deployed.
+    location = /god-mode/index.html {
+      root   /usr/share/nginx/html;
+      add_header X-Frame-Options "DENY" always;
+      add_header X-Content-Type-Options "nosniff" always;
+      add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
+      add_header X-XSS-Protection "1; mode=block" always;
+      add_header Cache-Control "no-cache, must-revalidate" always;
+      try_files $uri =404;
+    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/admin/nginx/nginx.conf` around lines 29 - 37, Align the
/god-mode/index.html location block with the surrounding nginx configuration by
correcting the location directive’s indentation and adding the corresponding
explanatory comment used in the web configuration. Keep the existing headers and
try_files behavior unchanged.
apps/web/nginx/nginx.conf (1)

42-48: 📐 Maintainability & Code Quality | 🔵 Trivial

Consider updating the AIO proxy configuration.

The changes here correctly prevent heuristic caching for the Nginx deployments. However, based on the context snippets, the All-In-One (AIO) deployment (apps/proxy/Caddyfile.aio.ce) serves the web and admin applications directly via Caddy's file_server rather than proxying to these Nginx containers.

Because Caddy does not append Cache-Control headers by default, Safari's heuristic caching might still cause stale application shells in the AIO setup. Consider applying a similar caching policy via the header directive in the Caddyfile in a future PR to cover AIO users.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/nginx/nginx.conf` around lines 42 - 48, Update the AIO Caddy
configuration in Caddyfile.aio.ce to add an explicit no-cache policy for the web
and admin applications served by file_server. Use Caddy’s header directive to
set the equivalent Cache-Control response headers, preserving the existing
file-serving behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@apps/admin/nginx/nginx.conf`:
- Around line 29-37: Align the /god-mode/index.html location block with the
surrounding nginx configuration by correcting the location directive’s
indentation and adding the corresponding explanatory comment used in the web
configuration. Keep the existing headers and try_files behavior unchanged.

In `@apps/web/nginx/nginx.conf`:
- Around line 42-48: Update the AIO Caddy configuration in Caddyfile.aio.ce to
add an explicit no-cache policy for the web and admin applications served by
file_server. Use Caddy’s header directive to set the equivalent Cache-Control
response headers, preserving the existing file-serving behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3b1a5c48-1a1b-4f8e-aa07-06fa44bd367e

📥 Commits

Reviewing files that changed from the base of the PR and between 7cef741 and 2a3810d.

📒 Files selected for processing (2)
  • apps/admin/nginx/nginx.conf
  • apps/web/nginx/nginx.conf

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants