a tool for shared writing and social publishing
0

Configure Feed

Select the types of activity you want to include in your feed.

improve standard site post resolution

Jared Pereira (May 28, 2026, 3:15 PM EDT) 3212781d 0d52157d

+43 -16
+43 -16
src/utils/resolveStandardSitePostUrl.ts
··· 1 1 import type { SupabaseClient } from "@supabase/supabase-js"; 2 2 import type { Database, Json } from "supabase/database.types"; 3 3 import { parseStandardSitePostInput } from "components/Blocks/StandardSitePostBlock/parseStandardSitePostInput"; 4 - import { normalizeDocumentRecord } from "src/utils/normalizeRecords"; 4 + import { 5 + normalizeDocumentRecord, 6 + normalizePublicationRecord, 7 + } from "src/utils/normalizeRecords"; 5 8 6 9 /** 7 10 * Resolve a URL or AT URI to a standard-site-post AT URI by checking our DB. ··· 29 32 return null; 30 33 } 31 34 const origin = `${url.protocol}//${url.host}`; 32 - const pathOnly = url.pathname.replace(/\/$/, "") || "/"; 35 + const requestedPath = url.pathname.replace(/\/$/, "") || "/"; 36 + const requestedUrl = origin + (requestedPath === "/" ? "" : requestedPath); 33 37 34 - // Find a publication whose URL matches this origin. Supports both 38 + // Publications can live at a sub-path (e.g. https://example.com/blog), so we 39 + // can't match the origin exactly. Prefix-match on the host to gather every 40 + // publication that could own this URL, then filter to the one whose url is 41 + // the longest prefix of the requested URL. Supports both 35 42 // pub.leaflet.publication (base_path) and site.standard.publication (url). 36 - // Descending uri order prefers site.standard.publication over pub.leaflet.publication. 37 - const { data: publication } = await supabase 43 + // Descending uri order prefers site.standard.publication over 44 + // pub.leaflet.publication when base paths are equally specific. 45 + const { data: publications } = await supabase 38 46 .from("publications") 39 - .select("uri") 47 + .select("uri, record") 40 48 .or( 41 - `record->>base_path.eq.${url.host},record->>url.eq.${origin},record->>url.eq.${origin}/`, 49 + [ 50 + `record->>base_path.like.${url.host}*`, 51 + `record->>url.like.${origin}*`, 52 + ].join(","), 42 53 ) 43 - .order("uri", { ascending: false }) 44 - .limit(1) 45 - .maybeSingle(); 46 - console.log(publication); 47 - if (!publication) return null; 54 + .order("uri", { ascending: false }); 55 + 56 + if (!publications?.length) return null; 57 + 58 + // Pick the publication whose url is the longest prefix of the requested URL, 59 + // and compute the document path relative to that publication's base path. 60 + let best: { uri: string; path: string; urlLength: number } | null = null; 61 + for (const pub of publications) { 62 + const normalized = normalizePublicationRecord(pub.record); 63 + if (!normalized?.url) continue; 64 + const pubUrl = normalized.url.replace(/\/$/, ""); 65 + if (requestedUrl !== pubUrl && !requestedUrl.startsWith(`${pubUrl}/`)) 66 + continue; 67 + const basePath = new URL(pubUrl).pathname.replace(/\/$/, ""); 68 + const relative = requestedPath.slice(basePath.length) || "/"; 69 + const path = relative.startsWith("/") ? relative : `/${relative}`; 70 + if (!best || pubUrl.length > best.urlLength) 71 + best = { uri: pub.uri, path, urlLength: pubUrl.length }; 72 + } 73 + 74 + if (!best) return null; 48 75 49 - // Find documents in that publication where data.path matches pathOnly 76 + // Find documents in that publication where data.path matches the requested 77 + // path (relative to the publication's base path). 50 78 const { data: docsInPub } = await supabase 51 79 .from("documents_in_publications") 52 80 .select("documents(uri, data)") 53 - .eq("publication", publication.uri); 81 + .eq("publication", best.uri); 54 82 55 83 if (!docsInPub) return null; 56 84 ··· 65 93 : `/${normalized.path}` 66 94 : null; 67 95 const docPath = rawPath ? rawPath.replace(/\/$/, "") || "/" : null; 68 - console.log(docPath, pathOnly); 69 - if (docPath === pathOnly) return doc.uri; 96 + if (docPath === best.path) return doc.uri; 70 97 } 71 98 return null; 72 99 }