this repo has no description
0
fork

Configure Feed

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

fix: use rkey-based canonicalUrl for Remanso documents

Build the canonicalUrl after record creation so the rkey is available,
producing the correct format: https://remanso.space/pub/{did}/{rkey}/{slug}.
Extracts slugifyTitle as a shared utility and adds canonicalUrlBuilder
to PublisherConfig for per-publisher URL customization.

+40 -7
+23 -3
packages/cli/src/lib/atproto.ts
··· 263 263 path: postPath, 264 264 textContent: textContent.slice(0, 10000), 265 265 publishedAt: publishDate.toISOString(), 266 - canonicalUrl: `${config.siteUrl}${postPath}`, 267 266 }; 267 + 268 + if (!config.canonicalUrlBuilder) { 269 + record.canonicalUrl = `${config.siteUrl}${postPath}`; 270 + } 268 271 269 272 if (post.frontmatter.description) { 270 273 record.description = post.frontmatter.description; ··· 284 287 record, 285 288 }); 286 289 287 - return response.data.uri; 290 + const atUri = response.data.uri; 291 + 292 + if (config.canonicalUrlBuilder) { 293 + const parsed = parseAtUri(atUri); 294 + if (parsed) { 295 + record.canonicalUrl = config.canonicalUrlBuilder(atUri, post); 296 + await agent.com.atproto.repo.putRecord({ 297 + repo: agent.did!, 298 + collection: parsed.collection, 299 + rkey: parsed.rkey, 300 + record, 301 + }); 302 + } 303 + } 304 + 305 + return atUri; 288 306 } 289 307 290 308 export async function updateDocument( ··· 330 348 path: postPath, 331 349 textContent: textContent.slice(0, 10000), 332 350 publishedAt: publishDate.toISOString(), 333 - canonicalUrl: `${config.siteUrl}${postPath}`, 351 + canonicalUrl: config.canonicalUrlBuilder 352 + ? config.canonicalUrlBuilder(atUri, post) 353 + : `${config.siteUrl}${postPath}`, 334 354 }; 335 355 336 356 if (post.frontmatter.description) {
+8 -4
packages/cli/src/lib/markdown.ts
··· 182 182 return slug; 183 183 } 184 184 185 + export function slugifyTitle(title: string): string { 186 + return (title || "") 187 + .toLowerCase() 188 + .replace(/\s+/g, "-") 189 + .replace(/[^\w-]/g, ""); 190 + } 191 + 185 192 export function resolvePathTemplate(template: string, post: BlogPost): string { 186 193 const publishDate = new Date(post.frontmatter.publishDate); 187 194 const year = String(publishDate.getFullYear()); ··· 191 198 const day = String(publishDate.getDate()).padStart(2, "0"); 192 199 const dayUTC = String(publishDate.getUTCDate()).padStart(2, "0"); 193 200 194 - const slugifiedTitle = (post.frontmatter.title || "") 195 - .toLowerCase() 196 - .replace(/\s+/g, "-") 197 - .replace(/[^\w-]/g, ""); 201 + const slugifiedTitle = slugifyTitle(post.frontmatter.title); 198 202 199 203 // Replace known tokens 200 204 let result = template
+1
packages/cli/src/lib/types.ts
··· 41 41 stripDatePrefix?: boolean; // Remove YYYY-MM-DD- prefix from filenames (Jekyll-style, default: false) 42 42 pathTemplate?: string; // URL path template with tokens like {year}/{month}/{day}/{slug} (overrides pathPrefix + slug) 43 43 textContentField?: string; // Frontmatter field to use for textContent instead of markdown body 44 + canonicalUrlBuilder?: (atUri: string, post: BlogPost) => string; 44 45 bluesky?: BlueskyConfig; // Optional Bluesky posting configuration 45 46 ui?: UIConfig; // Optional UI components configuration 46 47 }
+8
packages/remanso/src/commands/publish.ts
··· 16 16 resolveImagePath, 17 17 deleteRecord, 18 18 listDocuments, 19 + parseAtUri, 19 20 } from "../../../cli/src/lib/atproto"; 20 21 import { 21 22 scanContentDirectory, 22 23 getContentHash, 23 24 updateFrontmatterWithAtUri, 24 25 resolvePostPath, 26 + slugifyTitle, 25 27 } from "../../../cli/src/lib/markdown"; 26 28 import type { 27 29 BlogPost, ··· 338 340 imagesDir, 339 341 pdsUrl: config.pdsUrl, 340 342 pathPrefix: "", 343 + canonicalUrlBuilder: (atUri: string, post: BlogPost) => { 344 + const parsed = parseAtUri(atUri); 345 + if (!parsed) throw new Error(`Invalid atUri: ${atUri}`); 346 + const slug = slugifyTitle(post.frontmatter.title); 347 + return `${siteUrl}/${parsed.rkey}/${slug}`; 348 + }, 341 349 }; 342 350 343 351 // Publish posts