How I Built a Modern Blog with Astro, Tailwind v4 and AI Agent
How I Built a Modern Blog with Astro, Tailwind v4 and AI Agent
I’ve always wanted a space to share my thoughts on technology, design, and code, but I didn’t want to spend weeks configuring a CMS or fighting with a heavy framework. I wanted something fast, beautiful, and easy to maintain.
This blog is the result.
The Stack
For this project, I chose a stack that prioritizes performance and developer experience:
- Astro: The foundation. Astro’s “Zero JS by default” philosophy ensures blazing fast load times, while its Islands architecture lets me hydrate interactive components only when necessary.
- Tailwind CSS v4: The styling engine. I’m using the latest version of Tailwind, which leverages native CSS variables for dynamic theming without the need for a complex configuration file. No
@apply, just utility classes. - React: Used sparingly for interactive elements like the theme toggle.
- Giscus: A lightweight, GitHub-powered comment system that requires no backend maintenance.
- Vercel: For seamless deployment and edge caching.
The AI Workflow
The most unique part of this project wasn’t the tech stack, but how I built it. I didn’t write every line of CSS manually. Instead, I partnered with an AI Agent (Antigravity/Cursor) to “Vibe Code” the design.
My workflow looked like this:
- Describe the Vibe: I told the agent I wanted a “minimalist, Vercel-style aesthetic” with specific attention to typography and whitespace.
- Iterate: I’d ask for a component, review the visual result, and ask for tweaks. “Make the comments section wider,” or “Fix the dark mode contrast.”
- Command, Don’t Code: I focused on the high-level architecture—defining the content collections, setting up the layout—while the agent handled the implementation details of the UI components.
This allowed me to move significantly faster than if I were typing out every flex, grid, and padding utility myself.
Challenges
It wasn’t all smooth sailing. One significant hurdle was implementing the dark mode toggle properly.
Dark Mode Hydration
I initially ran into a hydration mismatch where the server rendered the light theme, but the user’s system preference was dark, causing a flash of incorrect color on load.
To fix this, I had to ensure the theme script ran immediately in the <head> to block rendering until the correct class was applied to the <html> element. For the toggle button itself, I used a client:only="react" directive or a carefully timed useEffect to ensure it only rendered after hydration was complete, preventing the dreaded “Hydration failed” error.
// Example of the fix logic
const theme = (() => {
if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) {
return localStorage.getItem('theme');
}
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'dark';
}
return 'light';
})();
if (theme === 'dark') {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
Conclusion
Building this blog has been a quick and rewarding journey. The combination of Astro’s performance and the AI agent’s coding speed allowed me to go from idea to deployment in record time.
I plan to use this space to document more of my experiments with AI-assisted software engineering. Stay tuned!