Refactor: Plausible-Konfiguration aktualisiert und twitterHandle entfernt

- Defaults auf neue Domains aktualisiert (hoerdle.de statt hoerdle.elpatron.me)
- CSP in proxy.ts konfigurierbar gemacht (liest Plausible-URL aus Umgebungsvariablen)
- twitterHandle entfernt (wurde nirgendwo verwendet)
- Dokumentation aktualisiert
This commit is contained in:
Hördle Bot
2025-12-01 18:29:09 +01:00
parent ac0bb02ba0
commit 85bdbf795c
5 changed files with 33 additions and 13 deletions

View File

@@ -49,7 +49,6 @@ RUN node_modules/.bin/prisma generate
ARG NEXT_PUBLIC_APP_NAME ARG NEXT_PUBLIC_APP_NAME
ARG NEXT_PUBLIC_APP_DESCRIPTION ARG NEXT_PUBLIC_APP_DESCRIPTION
ARG NEXT_PUBLIC_DOMAIN ARG NEXT_PUBLIC_DOMAIN
ARG NEXT_PUBLIC_TWITTER_HANDLE
ARG NEXT_PUBLIC_PLAUSIBLE_DOMAIN ARG NEXT_PUBLIC_PLAUSIBLE_DOMAIN
ARG NEXT_PUBLIC_PLAUSIBLE_SCRIPT_SRC ARG NEXT_PUBLIC_PLAUSIBLE_SCRIPT_SRC
ARG NEXT_PUBLIC_THEME_COLOR ARG NEXT_PUBLIC_THEME_COLOR
@@ -63,7 +62,6 @@ ARG NEXT_PUBLIC_CREDITS_LINK_URL
ENV NEXT_PUBLIC_APP_NAME=$NEXT_PUBLIC_APP_NAME ENV NEXT_PUBLIC_APP_NAME=$NEXT_PUBLIC_APP_NAME
ENV NEXT_PUBLIC_APP_DESCRIPTION=$NEXT_PUBLIC_APP_DESCRIPTION ENV NEXT_PUBLIC_APP_DESCRIPTION=$NEXT_PUBLIC_APP_DESCRIPTION
ENV NEXT_PUBLIC_DOMAIN=$NEXT_PUBLIC_DOMAIN ENV NEXT_PUBLIC_DOMAIN=$NEXT_PUBLIC_DOMAIN
ENV NEXT_PUBLIC_TWITTER_HANDLE=$NEXT_PUBLIC_TWITTER_HANDLE
ENV NEXT_PUBLIC_PLAUSIBLE_DOMAIN=$NEXT_PUBLIC_PLAUSIBLE_DOMAIN ENV NEXT_PUBLIC_PLAUSIBLE_DOMAIN=$NEXT_PUBLIC_PLAUSIBLE_DOMAIN
ENV NEXT_PUBLIC_PLAUSIBLE_SCRIPT_SRC=$NEXT_PUBLIC_PLAUSIBLE_SCRIPT_SRC ENV NEXT_PUBLIC_PLAUSIBLE_SCRIPT_SRC=$NEXT_PUBLIC_PLAUSIBLE_SCRIPT_SRC
ENV NEXT_PUBLIC_THEME_COLOR=$NEXT_PUBLIC_THEME_COLOR ENV NEXT_PUBLIC_THEME_COLOR=$NEXT_PUBLIC_THEME_COLOR

View File

@@ -8,7 +8,6 @@ services:
NEXT_PUBLIC_APP_NAME: ${NEXT_PUBLIC_APP_NAME} NEXT_PUBLIC_APP_NAME: ${NEXT_PUBLIC_APP_NAME}
NEXT_PUBLIC_APP_DESCRIPTION: ${NEXT_PUBLIC_APP_DESCRIPTION} NEXT_PUBLIC_APP_DESCRIPTION: ${NEXT_PUBLIC_APP_DESCRIPTION}
NEXT_PUBLIC_DOMAIN: ${NEXT_PUBLIC_DOMAIN} NEXT_PUBLIC_DOMAIN: ${NEXT_PUBLIC_DOMAIN}
NEXT_PUBLIC_TWITTER_HANDLE: ${NEXT_PUBLIC_TWITTER_HANDLE}
NEXT_PUBLIC_PLAUSIBLE_DOMAIN: ${NEXT_PUBLIC_PLAUSIBLE_DOMAIN} NEXT_PUBLIC_PLAUSIBLE_DOMAIN: ${NEXT_PUBLIC_PLAUSIBLE_DOMAIN}
NEXT_PUBLIC_PLAUSIBLE_SCRIPT_SRC: ${NEXT_PUBLIC_PLAUSIBLE_SCRIPT_SRC} NEXT_PUBLIC_PLAUSIBLE_SCRIPT_SRC: ${NEXT_PUBLIC_PLAUSIBLE_SCRIPT_SRC}
NEXT_PUBLIC_THEME_COLOR: ${NEXT_PUBLIC_THEME_COLOR} NEXT_PUBLIC_THEME_COLOR: ${NEXT_PUBLIC_THEME_COLOR}

View File

@@ -12,15 +12,14 @@ The application is configured via environment variables. You can set these in a
|----------|-------------|---------| |----------|-------------|---------|
| `NEXT_PUBLIC_APP_NAME` | The name of the application. | `Hördle` | | `NEXT_PUBLIC_APP_NAME` | The name of the application. | `Hördle` |
| `NEXT_PUBLIC_APP_DESCRIPTION` | The description used in metadata. | `Daily music guessing game...` | | `NEXT_PUBLIC_APP_DESCRIPTION` | The description used in metadata. | `Daily music guessing game...` |
| `NEXT_PUBLIC_DOMAIN` | The domain name (used for sharing). | `hoerdle.elpatron.me` | | `NEXT_PUBLIC_DOMAIN` | The domain name (used for sharing). | `hoerdle.de` |
| `NEXT_PUBLIC_TWITTER_HANDLE` | Twitter handle for metadata. | `@elpatron` |
### Analytics (Plausible) ### Analytics (Plausible)
| Variable | Description | Default | | Variable | Description | Default |
|----------|-------------|---------| |----------|-------------|---------|
| `NEXT_PUBLIC_PLAUSIBLE_DOMAIN` | The domain to track in Plausible. | `hoerdle.elpatron.me` | | `NEXT_PUBLIC_PLAUSIBLE_DOMAIN` | The domain to track in Plausible. | `hoerdle.de` |
| `NEXT_PUBLIC_PLAUSIBLE_SCRIPT_SRC` | The URL of the Plausible script. | `https://plausible.elpatron.me/js/script.js` | | `NEXT_PUBLIC_PLAUSIBLE_SCRIPT_SRC` | The URL of the Plausible script. | `https://plausible.example.com/js/script.js` |
### Credits ### Credits

View File

@@ -1,10 +1,9 @@
export const config = { export const config = {
appName: process.env.NEXT_PUBLIC_APP_NAME || 'Hördle', appName: process.env.NEXT_PUBLIC_APP_NAME || 'Hördle',
appDescription: process.env.NEXT_PUBLIC_APP_DESCRIPTION || 'Daily music guessing game - Guess the song from short audio clips', appDescription: process.env.NEXT_PUBLIC_APP_DESCRIPTION || 'Daily music guessing game - Guess the song from short audio clips',
domain: process.env.NEXT_PUBLIC_DOMAIN || 'hoerdle.elpatron.me', domain: process.env.NEXT_PUBLIC_DOMAIN || 'hoerdle.de',
twitterHandle: process.env.NEXT_PUBLIC_TWITTER_HANDLE || '@elpatron', plausibleDomain: process.env.NEXT_PUBLIC_PLAUSIBLE_DOMAIN || 'hoerdle.de',
plausibleDomain: process.env.NEXT_PUBLIC_PLAUSIBLE_DOMAIN || 'hoerdle.elpatron.me', plausibleScriptSrc: process.env.NEXT_PUBLIC_PLAUSIBLE_SCRIPT_SRC || 'https://plausible.example.com/js/script.js',
plausibleScriptSrc: process.env.NEXT_PUBLIC_PLAUSIBLE_SCRIPT_SRC || 'https://plausible.elpatron.me/js/script.js',
colors: { colors: {
themeColor: process.env.NEXT_PUBLIC_THEME_COLOR || '#000000', themeColor: process.env.NEXT_PUBLIC_THEME_COLOR || '#000000',
backgroundColor: process.env.NEXT_PUBLIC_BACKGROUND_COLOR || '#ffffff', backgroundColor: process.env.NEXT_PUBLIC_BACKGROUND_COLOR || '#ffffff',

View File

@@ -21,16 +21,41 @@ export default function proxy(request: NextRequest) {
headers.set('Referrer-Policy', 'strict-origin-when-cross-origin'); headers.set('Referrer-Policy', 'strict-origin-when-cross-origin');
headers.set('Permissions-Policy', 'camera=(), microphone=(), geolocation=()'); headers.set('Permissions-Policy', 'camera=(), microphone=(), geolocation=()');
// Extract Plausible domain from script URL for CSP
const plausibleScriptSrc = process.env.NEXT_PUBLIC_PLAUSIBLE_SCRIPT_SRC || 'https://plausible.example.com/js/script.js';
let plausibleOrigin = 'https://plausible.example.com';
try {
const url = new URL(plausibleScriptSrc);
plausibleOrigin = url.origin;
} catch {
// If URL parsing fails, try to extract domain manually
const match = plausibleScriptSrc.match(/https?:\/\/([^/]+)/);
if (match) {
plausibleOrigin = `https://${match[1]}`;
}
}
// Get other service URLs from environment (only add to CSP if configured)
const gotifyUrl = process.env.GOTIFY_URL;
const openrouterUrl = process.env.NEXT_PUBLIC_OPENROUTER_URL || 'https://openrouter.ai';
// Build CSP dynamically based on environment variables
const connectSrcParts = ["'self'", openrouterUrl, plausibleOrigin];
if (gotifyUrl && !gotifyUrl.includes('example.com')) {
connectSrcParts.push(gotifyUrl);
}
const csp = [ const csp = [
"default-src 'self'", "default-src 'self'",
"script-src 'self' 'unsafe-inline' 'unsafe-eval' https://plausible.elpatron.me", `script-src 'self' 'unsafe-inline' 'unsafe-eval' ${plausibleOrigin}`,
"style-src 'self' 'unsafe-inline'", "style-src 'self' 'unsafe-inline'",
"img-src 'self' data: blob:", "img-src 'self' data: blob:",
"font-src 'self' data:", "font-src 'self' data:",
"connect-src 'self' https://openrouter.ai https://gotify.example.com https://plausible.elpatron.me", `connect-src ${connectSrcParts.join(' ')}`,
"media-src 'self' blob:", "media-src 'self' blob:",
"frame-ancestors 'self'", "frame-ancestors 'self'",
].join('; '); ].join('; ');
headers.set('Content-Security-Policy', csp); headers.set('Content-Security-Policy', csp);
return response; return response;