diff --git a/app/(app)/[username]/[slug]/_userLinkDetail.tsx b/app/(app)/[username]/[slug]/_userLinkDetail.tsx index 3aa9ad3f0..75bdf0012 100644 --- a/app/(app)/[username]/[slug]/_userLinkDetail.tsx +++ b/app/(app)/[username]/[slug]/_userLinkDetail.tsx @@ -119,7 +119,7 @@ const UserLinkDetail = ({ username, contentSlug, initialContent }: Props) => { if (status === "pending") { return ( -
+
@@ -134,7 +134,7 @@ const UserLinkDetail = ({ username, contentSlug, initialContent }: Props) => { if (status === "error" || !linkContent) { return ( -
+
{ const isOwner = session?.user?.id === linkContent.author?.id; return ( -
+
{ const { data: reportCounts } = api.report.getCounts.useQuery(); return ( -
+

{"// "}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 ( -

+
{ }; 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 ( -

+
+
diff --git a/app/(app)/draft/[id]/page.tsx b/app/(app)/draft/[id]/page.tsx index 86ff32fda..d9e70ea81 100644 --- a/app/(app)/draft/[id]/page.tsx +++ b/app/(app)/draft/[id]/page.tsx @@ -48,7 +48,7 @@ const PreviewPage = async (props: Props) => { const content = Markdoc.transform(ast, config); return ( -
+
) : (
diff --git a/app/(app)/s/[sourceSlug]/[slug]/_feedArticleContent.tsx b/app/(app)/s/[sourceSlug]/[slug]/_feedArticleContent.tsx index b1e9ce7e5..617cf1aa1 100644 --- a/app/(app)/s/[sourceSlug]/[slug]/_feedArticleContent.tsx +++ b/app/(app)/s/[sourceSlug]/[slug]/_feedArticleContent.tsx @@ -42,7 +42,7 @@ const FeedArticleContent = ({ sourceSlug, article }: Props) => { const safeExternalUrl = safeExternalHref(article.externalUrl); return ( -
+
{ // first render (including SSR) is the real profile rather than a skeleton. if (status === "error" || !pub) { 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 && (