diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png
index c1fc127..7fee627 100644
Binary files a/public/apple-touch-icon.png and b/public/apple-touch-icon.png differ
diff --git a/public/favicon-192.png b/public/favicon-192.png
index 9134208..55f5341 100644
Binary files a/public/favicon-192.png and b/public/favicon-192.png differ
diff --git a/public/favicon-512.png b/public/favicon-512.png
index 7ee0918..e76ab90 100644
Binary files a/public/favicon-512.png and b/public/favicon-512.png differ
diff --git a/public/favicon-96x96.png b/public/favicon-96x96.png
index 5c14440..de93764 100644
Binary files a/public/favicon-96x96.png and b/public/favicon-96x96.png differ
diff --git a/public/favicon.ico b/public/favicon.ico
index f851e11..95cf5dc 100644
Binary files a/public/favicon.ico and b/public/favicon.ico differ
diff --git a/public/favicon.svg b/public/favicon.svg
index 3c96ad5..e2be59e 100644
--- a/public/favicon.svg
+++ b/public/favicon.svg
@@ -1 +1,3 @@
-
\ No newline at end of file
+
diff --git a/scripts/copy-docs-images.cjs b/scripts/copy-docs-images.cjs
index 860a36a..e1ad6ea 100644
--- a/scripts/copy-docs-images.cjs
+++ b/scripts/copy-docs-images.cjs
@@ -5,6 +5,31 @@ const docsImagesSrc = path.resolve(__dirname, "..", "content", "docs", "images")
const publicDir = path.resolve(__dirname, "..", "public");
const publicResourcesDir = path.resolve(publicDir, "resources");
+// Favicons + PWA manifest are committed at public/ root as the source of truth,
+// but the docs Cloudflare Worker only serves assets under /docs/* — top-level
+// public/ files land at the site root, which the worker never sees. Mirror them
+// into public/docs/ (git-ignored, build-generated) so they're emitted at
+// /docs/favicon.* and served by the docs worker itself. The hrefs in
+// src/routes/__root.tsx reference these via buildDocsPath ("/docs/..").
+const FAVICON_FILES = [
+ "favicon.svg",
+ "favicon.ico",
+ "favicon-96x96.png",
+ "favicon-192.png",
+ "favicon-512.png",
+ "apple-touch-icon.png",
+ "site.webmanifest",
+];
+const publicDocsDir = path.resolve(publicDir, "docs");
+fs.mkdirSync(publicDocsDir, { recursive: true });
+for (const name of FAVICON_FILES) {
+ const srcPath = path.join(publicDir, name);
+ if (fs.existsSync(srcPath)) {
+ fs.copyFileSync(srcPath, path.join(publicDocsDir, name));
+ }
+}
+console.log("[copy-docs-images] Copied favicons + manifest -> public/docs/");
+
function syncDir(src, dest) {
fs.mkdirSync(dest, { recursive: true });
diff --git a/src/routes/__root.tsx b/src/routes/__root.tsx
index d70dfed..f57f6cf 100644
--- a/src/routes/__root.tsx
+++ b/src/routes/__root.tsx
@@ -180,8 +180,11 @@ export const Route = createRootRoute({
],
links: [
{ rel: "stylesheet", href: appCss },
- // Favicons + PWA manifest, copied from the main superwall.com site. Served
- // from public/ under the /docs base, so hrefs are resolved via buildDocsPath.
+ // Favicons + PWA manifest. The docs Cloudflare Worker only serves assets
+ // under /docs/*, so these are referenced under the /docs base (buildDocsPath).
+ // The committed source lives at public/ root and is mirrored into public/docs/
+ // at build time by scripts/copy-docs-images.cjs, so /docs/favicon.* resolves
+ // from this worker (its own $W mark, not superwall.com's root favicon).
{ rel: "icon", type: "image/svg+xml", href: buildDocsPath("favicon.svg") },
{ rel: "icon", type: "image/png", sizes: "96x96", href: buildDocsPath("favicon-96x96.png") },
{ rel: "shortcut icon", href: buildDocsPath("favicon.ico") },