Files
garden-astro/src/pages/[...slug].astro
T
wesandClaude Fable 5 8f48656e91 Build stamp, live listening strip, OG cards, closer shiki ground
- footer: 'built <ts> · <hash> · <n> notes', hash linking to Gitea
  (GARDEN_COMMIT passed in by build.sh; '+' marks dirty-tree builds)
- homepage header: live strip fed by api.c0smere.net/spotify/summary
  (weekly aggregate + monthly top artist/genre), fail-closed like the
  odometer and header quote
- /og/<slug>.png satori+resvg cards for every note + the homepage;
  og:/twitter: meta in Base
- shiki github-dark-default (#0d1117 sits closer to the page ground)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 22:08:53 -04:00

91 lines
2.6 KiB
Plaintext

---
import { getCollection, render } from 'astro:content';
import Base from '../layouts/Base.astro';
import { slugForId, urlForId } from '../lib/quartz-compat.mjs';
export async function getStaticPaths() {
const entries = await getCollection('garden', (e) => !e.data.draft);
const ids = new Set(entries.map((e) => e.id));
const paths = entries
.filter((e) => e.id !== 'index')
.map((e) => ({
params: { slug: slugForId(e.id) },
props: { entry: e, listing: null },
}));
// synthetic listing pages for folders that have no index.md
const folders = new Set<string>();
for (const id of ids) {
let d = id.includes('/') ? id.slice(0, id.lastIndexOf('/')) : '';
while (d) {
folders.add(d);
d = d.includes('/') ? d.slice(0, d.lastIndexOf('/')) : '';
}
}
for (const folder of folders) {
if (ids.has(`${folder}/index`)) continue;
const children = entries
.filter((e) => {
const dir = e.id.includes('/') ? e.id.slice(0, e.id.lastIndexOf('/')) : '';
return dir === folder && !e.id.endsWith('/index');
})
.map((e) => ({
title: e.data.title ?? e.id.split('/').pop(),
url: urlForId(e.id),
}));
const subfolders = [...folders]
.filter((f) => {
const dir = f.includes('/') ? f.slice(0, f.lastIndexOf('/')) : '';
return dir === folder;
})
.map((f) => ({
title: f.split('/').pop(),
url: '/' + slugForId(f) + '/',
}));
paths.push({
params: { slug: slugForId(folder) + '/index' },
props: {
entry: null,
listing: { name: folder.split('/').pop(), items: [...subfolders, ...children] },
},
});
}
return paths;
}
const { entry, listing } = Astro.props;
const title = entry
? (entry.data.title ?? entry.id.split('/').pop())
: listing.name;
const rendered = entry ? await render(entry) : null;
const Content = rendered?.Content ?? null;
// notes whose body already opens with an identical h1 (common vault
// pattern) would show a doubled title — skip the synthetic one
const contentLeadsWithTitle =
rendered?.headings?.[0]?.depth === 1 &&
rendered.headings[0].text.trim() === String(title).trim();
---
<Base
title={title}
description={entry?.data.description}
headings={rendered?.headings ?? []}
ogSlug={entry ? slugForId(entry.id) : undefined}
>
{!contentLeadsWithTitle && <h1>{title}</h1>}
{Content && <Content />}
{
listing && (
<ul>
{listing.items.map((item) => (
<li>
<a href={item.url}>{item.title}</a>
</li>
))}
</ul>
)
}
</Base>