diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-09-01 14:48:45 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-09-01 14:48:45 +0300 |
| commit | 8a6d697308162874a236c84aac0b0f8c7ac01f83 (patch) | |
| tree | ed7dc7e8c6f50d66bde721fae78576aede929f66 /website/src/pages/blog | |
| parent | b54a78aa510b87d1e3b56c619b72eaeb59e4a2a1 (diff) | |
refactor: separate website presentation from runtime
Diffstat (limited to 'website/src/pages/blog')
| -rw-r--r-- | website/src/pages/blog/[slug].astro | 95 | ||||
| -rw-r--r-- | website/src/pages/blog/index.astro | 42 |
2 files changed, 0 insertions, 137 deletions
diff --git a/website/src/pages/blog/[slug].astro b/website/src/pages/blog/[slug].astro deleted file mode 100644 index 3c33a38c..00000000 --- a/website/src/pages/blog/[slug].astro +++ /dev/null @@ -1,95 +0,0 @@ ---- -import { getCollection, render } from 'astro:content'; -import SiteLayout from '../../components/SiteLayout.astro'; -import AuthorCard from '../../components/AuthorCard.astro'; - -export async function getStaticPaths() { - const posts = await getCollection('blog'); - /* dev only, see blog/index.astro */ - return posts - .filter((post) => import.meta.env.DEV || !post.data.draft) - .map((post) => { - const slug = post.id.replace(/\.(md|mdx)$/i, ''); - return { params: { slug }, props: { post, slug } }; - }); -} - -const { post, slug } = Astro.props; -const { Content, headings } = await render(post); -const sectionHeadings = headings.filter((heading) => heading.depth === 2); ---- - -<SiteLayout - title={`${post.data.title} — Herdr blog`} - description={post.data.description} - canonicalPath={`/blog/${slug}/`} - ogType="article" - ogImage={post.data.ogImage} - ogImageAlt={post.data.ogImage ? post.data.title : undefined} -> - {/* a post with no h2s renders no sidebar, so the grid must stop reserving - a column for it */} - <div class:list={['article', sectionHeadings.length === 0 && 'article-solo']}> - <article class="article-body"> - <p class="article-meta"> - <a href="/blog/">← Blog</a> - <time datetime={post.data.date.toISOString()}> - {post.data.date.toLocaleDateString('en', { - year: 'numeric', - month: 'long', - day: 'numeric', - })} - </time> - </p> - <h1>{post.data.title}</h1> - {post.data.lede && post.data.description && ( - <p class="article-lede">{post.data.description}</p> - )} - <hr class="article-rule" /> - <div class="prose"> - <Content /> - </div> - <AuthorCard /> - </article> - - {sectionHeadings.length > 0 && ( - <aside class="toc" aria-label="Article sections"> - <p>Sections</p> - <nav> - {sectionHeadings.map((heading) => ( - <a href={`#${heading.slug}`} data-heading-link={heading.slug}>{heading.text}</a> - ))} - </nav> - </aside> - )} - </div> - - <script> - const headings = Array.from(document.querySelectorAll('.prose h2[id]')); - const links = new Map( - Array.from(document.querySelectorAll('[data-heading-link]')).map((link) => [ - link.getAttribute('data-heading-link'), - link, - ]), - ); - - function setActive(id) { - for (const link of links.values()) link.removeAttribute('aria-current'); - links.get(id)?.setAttribute('aria-current', 'true'); - } - - if (headings.length > 0 && links.size > 0) { - setActive(headings[0].id); - const observer = new IntersectionObserver( - (entries) => { - const visible = entries - .filter((entry) => entry.isIntersecting) - .sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top)[0]; - if (visible?.target instanceof HTMLElement) setActive(visible.target.id); - }, - { rootMargin: '-18% 0px -68% 0px', threshold: 0 }, - ); - for (const heading of headings) observer.observe(heading); - } - </script> -</SiteLayout> diff --git a/website/src/pages/blog/index.astro b/website/src/pages/blog/index.astro deleted file mode 100644 index de9349ea..00000000 --- a/website/src/pages/blog/index.astro +++ /dev/null @@ -1,42 +0,0 @@ ---- -import { getCollection } from 'astro:content'; -import SiteLayout from '../../components/SiteLayout.astro'; - -/* Drafts render locally and never in a build, so an unpublished post can be - reviewed on the dev server without being one deploy away from going live. */ -const posts = (await getCollection('blog')) - .filter((post) => import.meta.env.DEV || !post.data.draft) - .map((post) => ({ ...post, slug: post.id.replace(/\.(md|mdx)$/i, '') })) - .sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf()); - -const stamp = (date) => - date.toLocaleDateString('en', { year: 'numeric', month: 'short', day: 'numeric' }); ---- - -<SiteLayout - title="Herdr blog" - description="Notes on the agent runtime — product decisions, implementation writeups, and what we learned running agents on machines nobody is watching." - canonicalPath="/blog/" -> - <header class="ph"> - <div class="hd-eyebrow"><s></s>the blog</div> - <h1>Notes from the herd.</h1> - <p> - Product decisions, implementation writeups, and what we learn running agents on - machines nobody is watching. - </p> - </header> - - <div class="posts"> - {posts.map((post) => ( - <a href={`/blog/${post.slug}/`}> - <time datetime={post.data.date.toISOString()}>{stamp(post.data.date)}</time> - <div> - <h2>{post.data.title}</h2> - {post.data.description && <p>{post.data.description}</p>} - </div> - <span class="go-arrow" aria-hidden="true">→</span> - </a> - ))} - </div> -</SiteLayout> |
