diff --git a/frontend/src/features/settings/tabs/AnalyticsTab.tsx b/frontend/src/features/settings/tabs/AnalyticsTab.tsx index e266bba4..6b178977 100644 --- a/frontend/src/features/settings/tabs/AnalyticsTab.tsx +++ b/frontend/src/features/settings/tabs/AnalyticsTab.tsx @@ -15,6 +15,35 @@ interface AnalyticsTabProps { const PROVIDER_OPTIONS: TrackerProvider[] = ['none', 'umami', 'rybbit', 'custom']; +/** + * The shipped CSP `script-src` is a static allowlist that no configured + * tracker domain is ever added to, so a self-hosted Umami/Rybbit instance is + * blocked by the browser with nothing but a console error to show for it. + * Shown for every provider that loads a script from another origin. + */ +const CspWarning: React.FC = () => { + const { t } = useTranslation(); + + return ( +
+ {t('settings.analytics.customCspWarning', 'Content-Security-Policy reminder')} +
++ {t( + 'settings.analytics.customCspWarningText', + 'PicPeak ships with a strict CSP (`script-src \'self\'`). If your tracker loads from another domain, add that domain to your reverse-proxy or nginx CSP config — otherwise the browser silently blocks the script.', + )} +
+- {t('settings.analytics.customCspWarning', 'Content-Security-Policy reminder')} -
-- {t( - 'settings.analytics.customCspWarningText', - 'PicPeak ships with a strict CSP (`script-src \'self\'`). If your tracker loads from another domain, add that domain to your reverse-proxy or nginx CSP config — otherwise the browser silently blocks the script.', - )} -
-