Changelog
Latest updates to achrafash.com.
- 2.0.3 — Released on Oct 19, 2025
Island status bar
I try to add Islands to most of my pages—embedded interactive components.
To keep design consistent, I needed a toast-like solution for notifying users. So inspired by Raycast I’m introducing the status bar!
Islands now feature a caption that can be controlled by the inner components to display: info, warning, error, or success messages.
Behind-the-scenes
Island components can use the
useStatusBarhook to set the status bar content—just like a regular toast library:import { useStatusBar } from "@/components/container"; export function Child() { const { set } = useStatusBar(); set({ message: "Loading…", level: "info" }); set({ message: "Heads up", level: "warn" }); set({ message: "Something failed", level: "error" }); set({ message: "Saved", level: "success" }); set(null); // clear; goes back to default caption }I’ve also added an error boundary in the
Containercomponent so exceptions are handled softly and an error message is displayed in the status bar.Caveat
Unfortunately, Astro seems to isolate components in MDX files so this doesn’t work:
// mdx file <Container> <IslandComponent /> </Container>I tried every client directive combinations, but I keep getting:
[ERROR] useStatusBar must be used inside <Container>So I instead have to put
ContainerinsideIslandComponentand use it as a single component. - 2.0.1 — Released on Oct 17, 2025
Personal Changelog
Introducing the Personal Changelog.
Kudos to these websites that inspired me:
Design inspired by Neon’s changelog.
Behind the scenes
The changelog shares the same infrastructure as the blog, that is:
- Astro’s content layer
- markdown files for each release in a
/releasesfolder - Tailwind’s typography plugin for consistent styling
- 2.0.0 — Released on Aug 16, 2025
2.0 Redesign
After supporting a growing number of concepts—blog, functional prototypes, mini apps—this website needed a big redesign.
And after watching my side projects inevitably die while my personal website stuck around, I reckoned it had to be my most polished personal work.Under the hood
- Content collections everywhere: using Astro’s content collections for posts, metatags, and releases makes authoring consistent and type‑safe.
// src/content.config.ts const blog = defineCollection({ loader: glob({ pattern: "*.(md|mdx)", base: "./posts" }), schema: z.object({ slug: z.string(), title: z.string(), date: z.string() }) }); // src/pages/blog/index.astro const posts = await getCollection("blog", (post) => { if (import.meta.env.PROD) { return !post.data.draft && !post.data.unlisted; } return true; });-
Modular folder structure: clearer separation between content, pages, and components to support posts, interactive islands, and mini apps.
-
Tailwind CSS v4: the new css-based configuration is awesome. I now have a single
base.cssfile. No extra config. Migration was smooth but the official v4 upgrade CLI would’ve saved me a few minutes if I had saw it earlier. -
Typography: while upgrading Tailwind I came across the plugin ecosystem so I had to try it. The Typography plugin has been amazing for styling layouts.
// src/pages/blog/_layout.astro <article class:list={[ // Globals "prose prose-gray prose-invert mx-auto max-w-lg", // Headings "prose-headings:font-serif prose-headings:mb-2...", // Links "prose-a:-mx-0.5 prose-a:rounded prose-a:bg-gray-500/20...", ... ]} > <slot /> </article>Polish
- Status badge on the home page.
- Interactive islands now feel like embedded widgets with a subtly contrasting background (see Arc bookmarks search).
- Apple‑inspired borders for floating elements (email form, islands, etc.).
- New typefaces: Space Grotesk (sans), Gloock (serif), Geist (display), Geist Mono (mono), Amiri (Arabic).
Misc
- Table of contents in blog posts (inspired by rauno.me).
- Semantic Versioning feels like I’m crafting this site, and helps me accept that it can’t be perfect on the first try. A version tag was added in the footer.