Latest

DAYS / newest first

Sunday, March 8, 2026

VOD

Bedroom

1,373 min

On YouTube

GitHub commits

ohnsh/scratch1

Saturday, March 7, 2026

Writing

Starlight CSS tweaks: A hero for a blog index page

Yesterday, I created (a rough version of) an Astro component that renders a stream of recent posts for a blog index page. I’m already using it on days.ohn.sh. For now, I’m using Astro’s Starlight documentation framework, which means the default styling isn’t optimized for a blog.

In Starlight, styles can be customized site-wide with the global customCss config option. In this case, I only wanted to modify the hero on the main index page. Luckily, you can import CSS into an MDX page, just like you would in an Astro component. Doing so allows for page-specific CSS tweaks.

Read full post →

VOD

On YouTube

GitHub commits

Friday, March 6, 2026

Writing

Creating an index page.

On a blog, the main (root) page should contain a list of recent posts. Starlight doesn’t have that functionality built-in, so here’s a first pass at a custom <RecentPosts> component. It’s already being used at days.ohn.sh.

// RecentPosts.astro
---
import Preview from './Preview.astro'
import { getCollection } from 'astro:content'

const posts = await getCollection('docs')
posts.sort((a, b) => Number(b.data.date) - Number(a.data.date))
const numPosts = 5
---

<section>
  {
    posts.slice(0, numPosts).map((entry) => (
        <Preview {entry} />
        <hr />
    ))
  }
</section>
<style>
  hr {
    margin-block: 3rem;
    border: none;
    border-top: 1px solid var(--sl-color-gray-5);
  }
</style>

Notice that Astro’s JSX-like templates can contain unwrapped fragments like <Preview /><hr />. Additionally, since they only render once (at build time in this case), there’s no need for a React-like key prop on map-generated elements.

Read full post →

VOD

On YouTube

GitHub commits