···43 // Load state to get atUri mappings
44 const state = await loadState(configDir);
45000000000046 // Build a map of slug/path to atUri from state
47 const pathToAtUri = new Map<string, string>();
48 for (const [filePath, postState] of Object.entries(state.posts)) {
49 if (postState.atUri) {
50 // Extract slug from file path (e.g., ./content/blog/my-post.md -> my-post)
51- const basename = path.basename(filePath, path.extname(filePath));
000000000000000052 pathToAtUri.set(basename, postState.atUri);
5354 // Also add variations that might match HTML file paths
55 // e.g., /blog/my-post, /posts/my-post, my-post/index
56 const dirName = path.basename(path.dirname(filePath));
57- if (dirName !== "." && dirName !== "content") {
058 pathToAtUri.set(`${dirName}/${basename}`, postState.atUri);
59 }
60 }
···43 // Load state to get atUri mappings
44 const state = await loadState(configDir);
4546+ // Generic filenames where the slug is the parent directory, not the filename
47+ // Covers: SvelteKit (+page), Astro/Hugo (index), Next.js (page), etc.
48+ const genericFilenames = new Set([
49+ "+page",
50+ "index",
51+ "_index",
52+ "page",
53+ "readme",
54+ ]);
55+56 // Build a map of slug/path to atUri from state
57 const pathToAtUri = new Map<string, string>();
58 for (const [filePath, postState] of Object.entries(state.posts)) {
59 if (postState.atUri) {
60 // Extract slug from file path (e.g., ./content/blog/my-post.md -> my-post)
61+ let basename = path.basename(filePath, path.extname(filePath));
62+63+ // If the filename is a generic convention name, use the parent directory as slug
64+ if (genericFilenames.has(basename.toLowerCase())) {
65+ // Split path and filter out route groups like (blog-article)
66+ const pathParts = filePath
67+ .split(/[/\\]/)
68+ .filter((p) => p && !(p.startsWith("(") && p.endsWith(")")));
69+ // The slug should be the second-to-last part (last is the filename)
70+ if (pathParts.length >= 2) {
71+ const slug = pathParts[pathParts.length - 2];
72+ if (slug && slug !== "." && slug !== "content" && slug !== "routes" && slug !== "src") {
73+ basename = slug;
74+ }
75+ }
76+ }
77+78 pathToAtUri.set(basename, postState.atUri);
7980 // Also add variations that might match HTML file paths
81 // e.g., /blog/my-post, /posts/my-post, my-post/index
82 const dirName = path.basename(path.dirname(filePath));
83+ // Skip route groups and common directory names
84+ if (dirName !== "." && dirName !== "content" && !(dirName.startsWith("(") && dirName.endsWith(")"))) {
85 pathToAtUri.set(`${dirName}/${basename}`, postState.atUri);
86 }
87 }