From f3bde44b3dd10871ed489cf770ab52fcf9fe3ebd Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 19 Jul 2026 09:26:04 +0000 Subject: [PATCH] previewDeploy: vorhandene HTML-Datei statt Platzhalter als Startseite befoerdern Fehlt im Repo eine index.html, zeigte die Preview nur die 'wird vorbereitet'-Platzhalterseite, obwohl das eigentliche Projekt (z.B. prototyp-app.html in knso/videogen) laengst deployt war. ensureIndexHtml befoerdert jetzt die beste vorhandene HTML-Datei (bevorzugte Namen, sonst einzige/groesste) per Kopie zur index.html; der Platzhalter kommt nur noch, wenn gar keine HTML-Datei existiert. Co-Authored-By: Claude Fable 5 --- server/services/previewDeploy.js | 54 ++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/server/services/previewDeploy.js b/server/services/previewDeploy.js index bcd3375..825d9cb 100644 --- a/server/services/previewDeploy.js +++ b/server/services/previewDeploy.js @@ -148,9 +148,53 @@ function placeholderHtml(displayName) { ` } +/** + * Sucht im Deploy-Verzeichnis die beste vorhandene HTML-Datei als Startseiten- + * Ersatz: bevorzugte Namen (index.htm, home, main, start, app), sonst die + * einzige bzw. groesste HTML-Datei. Nur Dateien im Wurzelverzeichnis. + */ +async function findIndexCandidate(targetDir) { + let entries = [] + try { + entries = await fs.readdir(targetDir, { withFileTypes: true }) + } catch { + return null + } + const htmlFiles = entries + .filter((e) => e.isFile() && /\.html?$/i.test(e.name) && !e.name.startsWith('.')) + .map((e) => e.name) + .filter((name) => name.toLowerCase() !== 'index.html') + if (!htmlFiles.length) return null + + const preferred = ['index.htm', 'home.html', 'homepage.html', 'main.html', 'start.html', 'app.html'] + for (const want of preferred) { + const hit = htmlFiles.find((name) => name.toLowerCase() === want) + if (hit) return hit + } + if (htmlFiles.length === 1) return htmlFiles[0] + + // Mehrere Kandidaten ohne sprechenden Namen: die groesste Datei ist mit + // Abstand am wahrscheinlichsten die eigentliche Projektseite. + const sized = await Promise.all( + htmlFiles.map(async (name) => { + try { + const stat = await fs.stat(path.join(targetDir, name)) + return { name, size: stat.size } + } catch { + return { name, size: 0 } + } + }) + ) + sized.sort((a, b) => b.size - a.size) + return sized[0].name +} + /** * Stellt sicher, dass ein Deploy-Verzeichnis eine index.html besitzt. Fehlt sie, - * wird ein Platzhalter geschrieben, damit nginx (autoindex off) kein 403 liefert. + * wird zuerst eine vorhandene HTML-Datei zur Startseite befoerdert (Kopie), + * damit die Preview das echte Projekt zeigt statt "wird vorbereitet". Erst wenn + * gar keine HTML-Datei existiert, kommt der Platzhalter (403-Schutz, nginx + * liefert mit autoindex off sonst "403 Forbidden"). */ async function ensureIndexHtml(targetDir, displayName) { const indexPath = path.join(targetDir, 'index.html') @@ -158,7 +202,13 @@ async function ensureIndexHtml(targetDir, displayName) { await fs.access(indexPath) return { placeholder: false } } catch { - /* keine index.html vorhanden -> Platzhalter schreiben */ + /* keine index.html vorhanden -> Kandidat befoerdern oder Platzhalter */ + } + const candidate = await findIndexCandidate(targetDir) + if (candidate) { + await fs.copyFile(path.join(targetDir, candidate), indexPath) + console.log(`[previewDeploy] keine index.html – "${candidate}" als Startseite uebernommen (${targetDir})`) + return { placeholder: false, promotedFrom: candidate } } await fs.mkdir(targetDir, { recursive: true }) await fs.writeFile(indexPath, placeholderHtml(displayName), 'utf8')