Ronti Patange commited on
Commit
83f5986
·
1 Parent(s): 12fa13a

Support configurable socket server URL, add PWA install/auto-refresh support

Browse files

- io() now reads VITE_SERVER_URL (empty on the Space itself, set to the
Space's public URL when this frontend is deployed elsewhere, e.g. Vercel)
- Add manifest.json + minimal service worker for installability; no offline
caching (would go stale for a realtime game), only used to detect new
deploys and reload the page when a new service worker activates

Files changed (6) hide show
  1. .env.example +6 -0
  2. App.tsx +1 -1
  3. index.html +3 -0
  4. main.tsx +16 -0
  5. manifest.json +11 -0
  6. sw.js +6 -0
.env.example CHANGED
@@ -7,3 +7,9 @@ GEMINI_API_KEY="MY_GEMINI_API_KEY"
7
  # AI Studio automatically injects this at runtime with the Cloud Run service URL.
8
  # Used for self-referential links, OAuth callbacks, and API endpoints.
9
  APP_URL="MY_APP_URL"
 
 
 
 
 
 
 
7
  # AI Studio automatically injects this at runtime with the Cloud Run service URL.
8
  # Used for self-referential links, OAuth callbacks, and API endpoints.
9
  APP_URL="MY_APP_URL"
10
+
11
+ # VITE_SERVER_URL: socket.io server to connect to. Leave unset on the HF Space
12
+ # (frontend + server are co-located, same-origin works). Set this on Vercel to
13
+ # the HF Space's public URL, e.g. "https://ronitp1-stock-rivals.hf.space", since
14
+ # Vercel only serves the static frontend and has no socket.io server.
15
+ VITE_SERVER_URL=""
App.tsx CHANGED
@@ -848,7 +848,7 @@ export default function App() {
848
 
849
  // --- Socket Connection ---
850
  useEffect(() => {
851
- const newSocket = io({
852
  reconnection: true,
853
  reconnectionAttempts: 10,
854
  reconnectionDelay: 1000,
 
848
 
849
  // --- Socket Connection ---
850
  useEffect(() => {
851
+ const newSocket = io(import.meta.env.VITE_SERVER_URL || undefined, {
852
  reconnection: true,
853
  reconnectionAttempts: 10,
854
  reconnectionDelay: 1000,
index.html CHANGED
@@ -3,6 +3,9 @@
3
  <head>
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
 
 
 
6
  <title>Stock Rivals</title>
7
  </head>
8
  <body>
 
3
  <head>
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <link rel="manifest" href="./manifest.json" />
7
+ <link rel="icon" href="./favicon.svg" />
8
+ <meta name="theme-color" content="#0f172a" />
9
  <title>Stock Rivals</title>
10
  </head>
11
  <body>
main.tsx CHANGED
@@ -8,3 +8,19 @@ createRoot(document.getElementById('root')!).render(
8
  <App />
9
  </StrictMode>,
10
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  <App />
9
  </StrictMode>,
10
  );
11
+
12
+ // PWA install support + auto-refresh when a new deploy's SW takes over.
13
+ if ('serviceWorker' in navigator) {
14
+ window.addEventListener('load', () => {
15
+ navigator.serviceWorker.register('/sw.js').then((reg) => {
16
+ reg.addEventListener('updatefound', () => {
17
+ const worker = reg.installing;
18
+ worker?.addEventListener('statechange', () => {
19
+ if (worker.state === 'activated' && navigator.serviceWorker.controller) {
20
+ window.location.reload();
21
+ }
22
+ });
23
+ });
24
+ });
25
+ });
26
+ }
manifest.json ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "Stock Rivals",
3
+ "short_name": "StockRivals",
4
+ "start_url": "./",
5
+ "display": "standalone",
6
+ "background_color": "#0f172a",
7
+ "theme_color": "#0f172a",
8
+ "icons": [
9
+ { "src": "./favicon.svg", "sizes": "any", "type": "image/svg+xml" }
10
+ ]
11
+ }
sw.js ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ // ponytail: no offline caching — this is a realtime game, stale cached state
2
+ // would be worse than no cache. This SW exists only to make the app
3
+ // installable and to detect new deploys for the auto-refresh prompt.
4
+ self.addEventListener('install', () => self.skipWaiting());
5
+ self.addEventListener('activate', (e) => e.waitUntil(self.clients.claim()));
6
+ self.addEventListener('fetch', () => {}); // required for installability