aboutsummaryrefslogtreecommitdiff
path: root/website/src/pages/blog
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-08-03 21:33:33 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-08-03 21:39:25 +0300
commit22bb476d646ccadec71f584b90c2a135fec92929 (patch)
treec6d4b6dffe0b8891c52e7e0cc10c8e6051734c30 /website/src/pages/blog
parenteacea2daf0b72973173b728936b27478374f2cd2 (diff)
feat(website): rebuild marketing pages on new brand chassis
Diffstat (limited to 'website/src/pages/blog')
-rw-r--r--website/src/pages/blog/[slug].astro69
-rw-r--r--website/src/pages/blog/index.astro56
2 files changed, 66 insertions, 59 deletions
diff --git a/website/src/pages/blog/[slug].astro b/website/src/pages/blog/[slug].astro
index 48cba857..3c33a38c 100644
--- a/website/src/pages/blog/[slug].astro
+++ b/website/src/pages/blog/[slug].astro
@@ -1,18 +1,16 @@
---
import { getCollection, render } from 'astro:content';
-import MarketingLayout from '../../components/MarketingLayout.astro';
+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) => !post.data.draft)
+ .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 },
- };
+ return { params: { slug }, props: { post, slug } };
});
}
@@ -21,7 +19,7 @@ const { Content, headings } = await render(post);
const sectionHeadings = headings.filter((heading) => heading.depth === 2);
---
-<MarketingLayout
+<SiteLayout
title={`${post.data.title} — Herdr blog`}
description={post.data.description}
canonicalPath={`/blog/${slug}/`}
@@ -29,9 +27,33 @@ const sectionHeadings = headings.filter((heading) => heading.depth === 2);
ogImage={post.data.ogImage}
ogImageAlt={post.data.ogImage ? post.data.title : undefined}
>
- <main class="content-shell">
- <div class="article-layout section">
- <aside class="article-toc" aria-label="Article sections">
+ {/* 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) => (
@@ -39,30 +61,11 @@ const sectionHeadings = headings.filter((heading) => heading.depth === 2);
))}
</nav>
</aside>
-
- <article class="article-shell">
- <header class="article-header">
- <p class="post-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>
- <p>{post.data.description}</p>
- </header>
- <div class="article-prose">
- <Content />
- </div>
- <AuthorCard />
- </article>
- </div>
- </main>
+ )}
+ </div>
<script>
- const headings = Array.from(document.querySelectorAll('.article-prose h2[id]'));
+ 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'),
@@ -89,4 +92,4 @@ const sectionHeadings = headings.filter((heading) => heading.depth === 2);
for (const heading of headings) observer.observe(heading);
}
</script>
-</MarketingLayout>
+</SiteLayout>
diff --git a/website/src/pages/blog/index.astro b/website/src/pages/blog/index.astro
index 8ca2ca10..de9349ea 100644
--- a/website/src/pages/blog/index.astro
+++ b/website/src/pages/blog/index.astro
@@ -1,38 +1,42 @@
---
import { getCollection } from 'astro:content';
-import MarketingLayout from '../../components/MarketingLayout.astro';
+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) => !post.data.draft)
+ .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' });
---
-<MarketingLayout
+<SiteLayout
title="Herdr blog"
- description="Notes on terminal-native agent workflows and the engineering behind Herdr."
+ description="Notes on the agent runtime — product decisions, implementation writeups, and what we learned running agents on machines nobody is watching."
canonicalPath="/blog/"
>
- <main class="content-shell">
- <section class="page-hero page-hero-compact">
- <p class="eyebrow"><span class="status-dot dot-working"></span>Blog</p>
- <h1>Notes from Herdr.</h1>
- <p class="hero-lede">
- Product notes and implementation writeups for the terminal-native agent multiplexer.
- </p>
- </section>
+ <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>
- <section class="section section-narrow" aria-label="Blog posts">
- <div class="post-list">
- {posts.map((post) => (
- <article class="post-card">
- <a class="post-card-link" href={`/blog/${post.slug}/`}>
- <h2>{post.data.title}</h2>
- <span aria-hidden="true">→</span>
- </a>
- </article>
- ))}
- </div>
- </section>
- </main>
-</MarketingLayout>
+ <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>