Host-Routing: Bot-Produktseite und Community-Hub getrennt
Deploy / check (push) Has been cancelled
Deploy / deploy (push) Has been cancelled

Eine Anwendung, zwei Gesichter — der Server erkennt an der Domain, welche
Seite gefragt ist, und schreibt das als data-site an den <body>. Das
Frontend rendert daraufhin entweder den Community-Hub wie bisher oder die
neue Produktseite.

- Bot-Produktseite (BotApp): Landing mit Feature-Übersicht, Befehls-
  referenz, Dashboard unter /dashboard, Orange als Leitfarbe
- Weiterleitungen: Community-Routen auf der Bot-Domain und umgekehrt
  werden dauerhaft (301) auf die richtige Adresse geschickt — geteilte
  Devlog-Permalinks laufen also nicht ins Leere. Rechtstexte bleiben auf
  beiden erreichbar.
- Open-Graph-Tags je Domain, inklusive eigener Vorschau für frei
  angelegte Seiten (Entwürfe bekommen bewusst keine)
- Login: neue Einstellung für die Cookie-Domain, damit die Anmeldung auf
  beiden Seiten gilt; nach dem Discord-Login landet man wieder auf der
  Seite, von der man gestartet ist (vorher immer auf der Hauptadresse)
- Alles greift erst, wenn beide Adressen im Setup eingetragen sind —
  bis dahin verhält sich die Anwendung unverändert

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-31 15:20:53 +02:00
co-authored by Claude Fable 5
parent e8158ce90b
commit 079c75b184
13 changed files with 515 additions and 14 deletions
+20
View File
@@ -428,6 +428,9 @@ ${rssItems}
roadmap_repo: getSetting('roadmap_repo') ?? 'D4rkst3r/EcoGame',
watchdog_urls: getSetting('watchdog_urls') ?? '',
public_url: publicUrl(),
hub_url: getSetting('hub_url') ?? '',
bot_url: getSetting('bot_url') ?? '',
cookie_domain: getSetting('cookie_domain') ?? '',
gitea_url: getSetting('gitea_url') ?? config.giteaUrl,
backup_enabled: getSetting('backup_enabled') !== '0',
repo_backup_enabled: getSetting('repo_backup_enabled') === '1',
@@ -508,6 +511,7 @@ ${rssItems}
'gitea_api_token', 'twitch_client_id', 'twitch_client_secret',
'discord_guild_id', 'bot_name', 'bot_description', 'public_url', 'gitea_url',
'legal_name', 'legal_address', 'legal_email', 'legal_extra',
'hub_url', 'bot_url', 'cookie_domain',
]) delete body[key];
}
@@ -670,6 +674,22 @@ ${rssItems}
for (const key of ['legal_name', 'legal_address', 'legal_email', 'legal_extra']) {
if (body[key] !== undefined) setSetting(key, String(body[key]).trim().slice(0, 500));
}
// Getrennte Adressen für Hub und Produktseite (leer = beides gleich)
for (const key of ['hub_url', 'bot_url']) {
if (body[key] === undefined) continue;
const value = String(body[key]).trim().replace(/\/$/, '');
if (value && !/^https?:\/\/.+/.test(value)) {
return reply.code(400).send({ error: `${key}: muss mit http(s):// beginnen` });
}
setSetting(key, value);
}
if (body.cookie_domain !== undefined) {
const value = String(body.cookie_domain).trim();
if (value && !/^\.?[a-z0-9.-]+\.[a-z]{2,}$/i.test(value)) {
return reply.code(400).send({ error: 'cookie_domain: z. B. .d4rkst3r.de' });
}
setSetting('cookie_domain', value);
}
// URLs: müssen mit http(s) beginnen
for (const key of ['public_url', 'gitea_url']) {
if (body[key] === undefined) continue;