@@ -139,6 +139,59 @@ if (fs.existsSync(staticPath)) {
139139 } ) ;
140140} else {
141141 console . warn ( `Static frontend directory not found at ${ staticPath } ` ) ;
142+
143+ // Emergency fallback: if the static frontend isn't present in the image
144+ // (for example a mis-built image or multi-stage copy failure), serve a
145+ // small informational HTML page at / so users hitting the site root get a
146+ // helpful message instead of a generic Azure "Application Error".
147+ app . get ( '/' , ( _req : Request , res : Response ) => {
148+ res . type ( 'text/html' ) ;
149+ const html = `<!doctype html>
150+ <html>
151+ <head>
152+ <meta charset="utf-8">
153+ <title>App Scripting — Frontend unavailable</title>
154+ <meta name="viewport" content="width=device-width,initial-scale=1">
155+ <style>body{font-family:Segoe UI,Roboto,Arial,sans-serif;margin:2rem;color:#222}a{color:#0366d6}</style>
156+ </head>
157+ <body>
158+ <h1>Frontend temporarily unavailable</h1>
159+ <p>The frontend static bundle was not found inside this container image.</p>
160+ <p>You can still use the API directly:</p>
161+ <ul>
162+ <li><a href="/api/health">/api/health</a></li>
163+ </ul>
164+ <p>If you maintain this deployment, rebuild the editor image so the
165+ <code>editor-dist</code> directory is present, or deploy the editor/nginx image.</p>
166+ <hr/>
167+ <p><small>Generated at ${ new Date ( ) . toISOString ( ) } </small></p>
168+ </body>
169+ </html>` ;
170+ return res . status ( 200 ) . send ( html ) ;
171+ } ) ;
172+
173+ // Provide a minimal env-config.js so clients can still fetch runtime settings
174+ app . get ( '/env-config.js' , ( _req : Request , res : Response ) => {
175+ res . type ( 'application/javascript' ) ;
176+ return res . status ( 200 ) . send ( '// env-config not present in image (fallback)\n' ) ;
177+ } ) ;
178+
179+ // Provide the same runtime-config.js fallback as we do when static files exist
180+ app . get ( '/runtime-config.js' , ( _req : Request , res : Response ) => {
181+ res . type ( 'application/javascript' ) ;
182+ const runtime = {
183+ VITE_BACKEND_BASE_URL : process . env . VITE_BACKEND_BASE_URL || '' ,
184+ VITE_LOGIN_BASE_URL : process . env . VITE_LOGIN_BASE_URL || '' ,
185+ VITE_NODE_ENV : process . env . VITE_NODE_ENV || 'production' ,
186+ VITE_OAUTH_WEB_CLIENT_ID : process . env . VITE_OAUTH_WEB_CLIENT_ID || '' ,
187+ VITE_OAUTH_WEB_CLIENT_SECRET : process . env . VITE_OAUTH_WEB_CLIENT_SECRET ? 'SET' : '' ,
188+ _generated : new Date ( ) . toISOString ( ) ,
189+ } as Record < string , any > ;
190+ const content = `// Runtime configuration (generated)\nwindow.runtimeConfig = ${ JSON . stringify (
191+ runtime ,
192+ ) } ;\n`;
193+ return res . status ( 200 ) . send ( content ) ;
194+ } ) ;
142195}
143196
144197// Lightweight diagnostics endpoint so we can query the container about the frontend bundle
0 commit comments