{"// "}admin diff --git a/app/(app)/admin/moderation/_client.tsx b/app/(app)/admin/moderation/_client.tsx index f993bb9f3..a4c1fe307 100644 --- a/app/(app)/admin/moderation/_client.tsx +++ b/app/(app)/admin/moderation/_client.tsx @@ -182,7 +182,7 @@ const ModerationQueue = () => { highlightedItem === id ? "ring-2 ring-accent rounded-lg" : ""; return ( -
diff --git a/app/(app)/admin/tags/_client.tsx b/app/(app)/admin/tags/_client.tsx index dc6ab7e1f..3739e9ac8 100644 --- a/app/(app)/admin/tags/_client.tsx +++ b/app/(app)/admin/tags/_client.tsx @@ -208,7 +208,7 @@ const TagsAdmin = () => { }; return ( -
diff --git a/app/(app)/admin/users/_client.tsx b/app/(app)/admin/users/_client.tsx index 53b36aa26..e66112c69 100644 --- a/app/(app)/admin/users/_client.tsx +++ b/app/(app)/admin/users/_client.tsx @@ -81,7 +81,7 @@ const UserManagement = () => { : usersData?.users; return ( -
Publication Not Found
diff --git a/app/(app)/tag/[slug]/page.tsx b/app/(app)/tag/[slug]/page.tsx
index 452e9d530..f6f5d631f 100644
--- a/app/(app)/tag/[slug]/page.tsx
+++ b/app/(app)/tag/[slug]/page.tsx
@@ -165,7 +165,7 @@ export default async function TagPage(props: Props) {
const nextHref = hasNextPage ? `/tag/${slug}?page=${page + 1}` : null;
return (
-
+
{"// "}
Tag
diff --git a/app/api/admin/sync-feeds/route.ts b/app/api/admin/sync-feeds/route.ts
index f12a71723..d4b4b57e2 100644
--- a/app/api/admin/sync-feeds/route.ts
+++ b/app/api/admin/sync-feeds/route.ts
@@ -11,6 +11,7 @@ import { eq } from "drizzle-orm";
import Parser from "rss-parser";
import { customAlphabet } from "nanoid";
import { fetchOgImage } from "@/lib/og-image";
+import { ensureHttps, unwrapDoubledUrl } from "@/utils/url";
// Generate Reddit-style short IDs: lowercase + numbers, 7 characters
const generateShortId = customAlphabet(
@@ -128,10 +129,14 @@ function extractImageUrl(item: Parser.Item): string | null {
| { url?: string; type?: string }
| undefined;
- if (mediaContent?.$?.url) return mediaContent.$.url;
- if (mediaThumbnail?.$?.url) return mediaThumbnail.$.url;
+ // Some feeds (e.g. HackerNoon's media:thumbnail) prefix an already-absolute
+ // CDN URL with their own origin, producing a 404ing doubled URL — unwrap it.
+ if (mediaContent?.$?.url)
+ return ensureHttps(unwrapDoubledUrl(mediaContent.$.url));
+ if (mediaThumbnail?.$?.url)
+ return ensureHttps(unwrapDoubledUrl(mediaThumbnail.$.url));
if (enclosure?.url && enclosure.type?.startsWith("image/"))
- return enclosure.url;
+ return ensureHttps(unwrapDoubledUrl(enclosure.url));
return null;
}
@@ -246,7 +251,9 @@ export async function POST(request: Request) {
// Fetch OG image from the article URL
try {
- const ogImageUrl = await fetchOgImage(item.link);
+ const ogImageUrl = ensureHttps(
+ unwrapDoubledUrl(await fetchOgImage(item.link)),
+ );
if (ogImageUrl) {
await db
.update(aggregated_article)
diff --git a/components/CommandPalette/CommandPalette.tsx b/components/CommandPalette/CommandPalette.tsx
index 755c78f88..8e8ac8790 100644
--- a/components/CommandPalette/CommandPalette.tsx
+++ b/components/CommandPalette/CommandPalette.tsx
@@ -140,7 +140,8 @@ export function CommandPalette({ onClose }: CommandPaletteProps) {
aria-label="Search Codú"
className="w-full max-w-[600px] overflow-hidden rounded-xl border border-strong bg-elevated shadow-lg"
>
-
+ {/* A subtle thin accent line marks the active field — no focus ring. */}
+
⌕
-
+ {/* Desktop closes with the Esc key; mobile gets a tap target. */}
+
Esc
+
{
return (
-
+
{/* Breadcrumb navigation */}
{breadcrumbs.length > 0 && (
}
{breadcrumbSchema && }
-
+
{"// "} Tag diff --git a/app/api/admin/sync-feeds/route.ts b/app/api/admin/sync-feeds/route.ts index f12a71723..d4b4b57e2 100644 --- a/app/api/admin/sync-feeds/route.ts +++ b/app/api/admin/sync-feeds/route.ts @@ -11,6 +11,7 @@ import { eq } from "drizzle-orm"; import Parser from "rss-parser"; import { customAlphabet } from "nanoid"; import { fetchOgImage } from "@/lib/og-image"; +import { ensureHttps, unwrapDoubledUrl } from "@/utils/url"; // Generate Reddit-style short IDs: lowercase + numbers, 7 characters const generateShortId = customAlphabet( @@ -128,10 +129,14 @@ function extractImageUrl(item: Parser.Item): string | null { | { url?: string; type?: string } | undefined; - if (mediaContent?.$?.url) return mediaContent.$.url; - if (mediaThumbnail?.$?.url) return mediaThumbnail.$.url; + // Some feeds (e.g. HackerNoon's media:thumbnail) prefix an already-absolute + // CDN URL with their own origin, producing a 404ing doubled URL — unwrap it. + if (mediaContent?.$?.url) + return ensureHttps(unwrapDoubledUrl(mediaContent.$.url)); + if (mediaThumbnail?.$?.url) + return ensureHttps(unwrapDoubledUrl(mediaThumbnail.$.url)); if (enclosure?.url && enclosure.type?.startsWith("image/")) - return enclosure.url; + return ensureHttps(unwrapDoubledUrl(enclosure.url)); return null; } @@ -246,7 +251,9 @@ export async function POST(request: Request) { // Fetch OG image from the article URL try { - const ogImageUrl = await fetchOgImage(item.link); + const ogImageUrl = ensureHttps( + unwrapDoubledUrl(await fetchOgImage(item.link)), + ); if (ogImageUrl) { await db .update(aggregated_article) diff --git a/components/CommandPalette/CommandPalette.tsx b/components/CommandPalette/CommandPalette.tsx index 755c78f88..8e8ac8790 100644 --- a/components/CommandPalette/CommandPalette.tsx +++ b/components/CommandPalette/CommandPalette.tsx @@ -140,7 +140,8 @@ export function CommandPalette({ onClose }: CommandPaletteProps) { aria-label="Search Codú" className="w-full max-w-[600px] overflow-hidden rounded-xl border border-strong bg-elevated shadow-lg" > -