From 63192659e44446864c0b0ef02f3524f6d642e1aa Mon Sep 17 00:00:00 2001
From: 3252a8 <3252a8@proton.me>
Date: Mon, 8 Jun 2026 10:02:46 +0300
Subject: [PATCH] fix: prevent stale mini app mobile styles
---
backend/bot/app/web/templates/subscription_webapp.html | 3 +++
backend/bot/app/web/webapp/assets.py | 10 +++++++---
deploy/docker/frontend/nginx.conf | 8 ++++++--
frontend/src/styles/base.css | 5 +++++
4 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/backend/bot/app/web/templates/subscription_webapp.html b/backend/bot/app/web/templates/subscription_webapp.html
index 00f81ff..6a61a37 100644
--- a/backend/bot/app/web/templates/subscription_webapp.html
+++ b/backend/bot/app/web/templates/subscription_webapp.html
@@ -6,6 +6,9 @@
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover"
/>
+
+
+
diff --git a/backend/bot/app/web/webapp/assets.py b/backend/bot/app/web/webapp/assets.py
index def7360..29d7098 100644
--- a/backend/bot/app/web/webapp/assets.py
+++ b/backend/bot/app/web/webapp/assets.py
@@ -18,6 +18,8 @@ _GZIP_BODY_CACHE: Dict[str, bytes] = {}
_ASSET_NAME_CACHE: Dict[tuple[str, str], tuple[float, str]] = {}
_I18N_PAYLOAD_CACHE: Dict[tuple[int, str, tuple[tuple[str, int, int], ...]], Dict[str, Any]] = {}
_ASSET_NAME_CACHE_TTL_SECONDS = 30.0
+WEBAPP_HTML_CACHE_CONTROL = "no-store, no-cache, must-revalidate, max-age=0"
+WEBAPP_LEGACY_ASSET_CACHE_CONTROL = "no-store, no-cache, must-revalidate, max-age=0"
async def health_route(request: web.Request) -> web.Response:
@@ -48,7 +50,7 @@ async def _css_asset_route(request: web.Request, *, base_name: str) -> web.Respo
allow_precompressed=bool(asset_hash),
)
response.headers["Cache-Control"] = (
- "public, max-age=31536000, immutable" if asset_hash else "no-cache"
+ "public, max-age=31536000, immutable" if asset_hash else WEBAPP_LEGACY_ASSET_CACHE_CONTROL
)
return response
@@ -901,7 +903,7 @@ async def _js_asset_route(request: web.Request, *, base_name: str) -> web.Respon
strip_dev_mock=not asset_hash,
)
response.headers["Cache-Control"] = (
- "public, max-age=31536000, immutable" if asset_hash else "no-cache"
+ "public, max-age=31536000, immutable" if asset_hash else WEBAPP_LEGACY_ASSET_CACHE_CONTROL
)
return response
@@ -1182,7 +1184,9 @@ async def index_route(request: web.Request) -> web.Response:
1,
)
response = web.Response(text=html, content_type="text/html", charset="utf-8")
- response.headers["Cache-Control"] = "no-cache"
+ response.headers["Cache-Control"] = WEBAPP_HTML_CACHE_CONTROL
+ response.headers["Pragma"] = "no-cache"
+ response.headers["Expires"] = "0"
return response
diff --git a/deploy/docker/frontend/nginx.conf b/deploy/docker/frontend/nginx.conf
index f17527d..f1a7f78 100644
--- a/deploy/docker/frontend/nginx.conf
+++ b/deploy/docker/frontend/nginx.conf
@@ -111,7 +111,9 @@ server {
location ~* ^/subscription_webapp(_admin)?\.(css|js)$ {
expires off;
- add_header Cache-Control "no-cache";
+ add_header Cache-Control "no-store, no-cache, must-revalidate, max-age=0";
+ add_header Pragma "no-cache";
+ add_header Expires "0";
add_header X-Robots-Tag "noindex, nofollow, noarchive";
try_files $uri =404;
}
@@ -124,7 +126,9 @@ server {
}
location / {
- add_header Cache-Control "no-cache";
+ add_header Cache-Control "no-store, no-cache, must-revalidate, max-age=0";
+ add_header Pragma "no-cache";
+ add_header Expires "0";
add_header X-Robots-Tag "noindex, nofollow, noarchive";
try_files $uri /index.html;
}
diff --git a/frontend/src/styles/base.css b/frontend/src/styles/base.css
index 8134cd3..1e098c3 100644
--- a/frontend/src/styles/base.css
+++ b/frontend/src/styles/base.css
@@ -97,6 +97,11 @@ body,
overflow-x: clip;
}
+html {
+ -webkit-text-size-adjust: 100%;
+ text-size-adjust: 100%;
+}
+
body {
background: var(--bg, #02070b);
color: var(--text);