Building deadlocked.life: A Blog Built with Astro and Claude
The technical journey of building this blog with Astro, AWS, and modern web technologies
I’ve tried blogging a few times over the years, but staying consistent never really stuck. Hosting costs and general life chaos didn’t help either. Still, I decided to give it another shot after building a sample blog during a lab at AWS re:Invent 2025. This post gives a behind-the-scenes look at the technical choices and implementation of deadlocked.life.
An AI-Driven Build Experience.
This entire site started as an experiment during the “Vibin’ With Claude” session at AWS re:Invent 2025. I built the initial version in just a few hours using Claude Code by Anthropic, then refined and extended it afterward with more help from Claude.
The whole thing came together surprisingly fast, and the process was a lot of fun. AWS was nice enough to provide some awesome plugins that made the process even easier, but even without those plugins, the process would still be fairly painless—provided you engineer your prompts correctly.
Understanding the AWS Claude Code Plugins
Before diving into the build process, it’s worth explaining the AWS-provided plugins that structured my workflow. These plugins implement the EPCC methodology (Explore, Plan, Code, Commit):
Product Development Commands:
/prd [idea]- Interactive PRD (Product Requirements Document) creation. Claude asks clarifying questions about your idea and generates a comprehensive requirements document with goals, features, tech stack recommendations, and success criteria./trd [context]- Technical Requirements Document generation for deeper technical specifications.
EPCC Workflow Commands:
/epcc-explore [area]- Systematically explores your codebase or investigates a specific area before making changes. Useful for understanding existing code./epcc-plan [feature]- Creates a detailed implementation plan for a feature, breaking it down into steps with file changes and technical approach./epcc-code [task]- Implements code based on a plan, with options like--tddfor test-driven development or--quickfor rapid prototyping./epcc-commit [message]- Creates well-formatted git commits with proper messages and co-authorship attribution.
Session Management:
/epcc-resume- Resumes work from previous sessions, showing project status and next steps.
These commands provide structure and ensure you think through requirements before diving into code. They’re especially valuable for greenfield projects where you’re starting from scratch.
Starting with /prd
Starting with nothing but a domain name and the AWS Claude Code plugins (see References below), I kicked things off with a single command:
/prd deadlocked.life - a technical blog for sharing tutorials, ADHD insights, and project showcases
This triggered an interactive session where Claude asked clarifying questions:
- What type of content would I be publishing?
- Who was my target audience?
- What features were must-haves vs. nice-to-haves?
- What was my preferred tech stack?
- Should it support multiple content categories?
- What's the deployment target?
Within minutes, Claude generated a comprehensive PRD.md file that included:
Executive Summary: “A modern technical blog platform for sharing technical experiences, tutorials, sample projects, ADHD insights, and life reflections. Built as a static site with markdown-based content, deployed to AWS S3/CloudFront, featuring distinct visual sections for different content types with a professional yet personal aesthetic using purple/green/blue gradients.”
Core Features Prioritized:
- P0 (Must Have): Markdown content system, code syntax highlighting, tag/category system, search, visual content sections, light/dark themes, AWS infrastructure
- P1 (Should Have): Project pages, RSS feed, reading time, related posts
- P2 (Nice to Have): Analytics, SEO optimization, newsletter, comments
Technology Stack Recommendations:
- Astro (static site generator) - chosen because I had recent experience and it’s perfect for content-heavy sites
- Markdown/MDX for content
- Tailwind CSS or vanilla CSS with gradient support
- Pagefind or Fuse.js for client-side search
- AWS S3 + CloudFront + Route53 for hosting
- GitHub Actions for CI/CD
Key insight: Starting with /prd forced me to think through requirements upfront, even though I was excited to just start coding. This structured approach saved time later by preventing scope creep and clarifying the MVP. The PRD became my north star for the project.
From PRD to Implementation
With the PRD in hand, I could have used /epcc-plan to create an implementation plan, but I decided to jump straight to /epcc-code for the initial scaffolding:
/epcc-code --quick Create Astro blog with markdown content support and basic theme system
Claude generated the project structure and asked if I wanted to:
- Use the Astro blog template as a starting point? (Yes)
- Set up TypeScript? (Yes)
- Include content collections? (Yes)
- Configure for AWS deployment? (Yes)
Within minutes, Claude had:
- Scaffolded the Astro project with the blog template
- Set up the content structure with markdown-based posts and content collections
- Implemented the tag and category system for organizing content
- Created the initial theme with purple/pink gradient aesthetic from my PRD
- Built responsive layouts with proper mobile support
- Configured build for S3 deployment
The entire initial implementation took about 3-4 hours during the workshop. Not bad for a complete blog platform!
Iterative Refinement
After the workshop, I continued working with Claude to refine the design. This is where the conversational nature of Claude Code really shined.
Theme System Evolution
My first customization request after the MVP:
"Create a theme that matches the AWS console"
Claude generated a theme using AWS Cloudscape Design System colors (blue #0972d3 and orange #ec7211), with both light and dark mode support. This got me thinking—why limit myself to one theme?
"Create a vibrant theme focused around cyan and magenta colors. Create 3 other random themes. Maybe one with Claude colors, and a nautical theme."
Claude responded by creating four new themes:
- Cyberpunk: Cyan (#00d9ff) and magenta (#ff00ff) for a futuristic vibe
- Claude: Warm amber/orange (#cc785c) inspired by Anthropic’s branding
- Nautical: Ocean blues (#1e5a8e) and sandy beiges for a maritime feel
- Sunset: Oranges (#ff6b35) and purples (#7c3e8c) for warm evenings
Each theme included:
- Complete color palette (primary, secondary, tertiary backgrounds)
- Text colors for different hierarchy levels
- Both dark and light mode variants
- Proper contrast ratios for accessibility
Custom Logo Design
Instead of using a generic logo, I asked Claude to design something meaningful:
"Create a new design for my logo for the site using theme colors. Logo should represent the name and purpose of the site so ADHD, brain, deadlock."
Claude generated an SVG logo with:
- Neural pathway nodes in a circular deadlock pattern (6 nodes total)
- 5 outer nodes representing thoughts/processes that can deadlock
- 1 center node representing the “deadlock” state
- Dynamic theme colors that adapt to the current theme
- Hover animations: pulse effect, glow, and animated connection pathways
- Completely scalable vector graphics
The logo perfectly captured the concept: multiple neural pathways that can get stuck waiting on each other—just like how ADHD can feel sometimes.
Theme Chooser Component
Originally, switching themes required editing src/consts.ts and rebuilding. I asked:
"Let's add a theme chooser so I can switch easily without needing to update the constants file."
Claude built a dropdown component in the header with:
- List of all available themes with names and descriptions
- Personality traits for each theme (“Professional and corporate” for AWS, “Electric and futuristic” for Cyberpunk)
- LocalStorage persistence so your choice is remembered
- Active theme indicated with a checkmark (✓)
- Live switching without page reload
The bug that taught me about Vite: Initially, the theme CSS files returned 404 errors. Claude diagnosed the issue immediately: the theme registry was using hard-coded paths like /src/styles/themes/vibrant.css, which don’t exist in the built output.
The fix: Use Vite’s ?url import suffix to get proper asset URLs:
import vibrantUrl from './vibrant.css?url';
export const themes: Record<string, ThemeMetadata> = {
vibrant: {
id: 'vibrant',
name: 'Vibrant',
cssFile: vibrantUrl, // Generates: /_astro/vibrant.hash.css
},
};
This generates proper built asset URLs with cache-busting hashes like /_astro/vibrant.B7xK9f2.css.
Magazine-Style Blog Cards
The default blog card layout felt too generic—small cards in a grid didn’t do justice to the content. I found a design I liked and shared a screenshot:
"Let's tweak it... Instead of the current card format with 2 cards in the same row, let's do one per card and make it wider and taller. Add the image on one side and description on the other, and alternate which side the image is on every row."
"And let's make the image twice as wide as the description side"
Claude completely redesigned the PostCard component:
- Changed from grid layout to horizontal cards (one per row)
- 2:1 image-to-content ratio using CSS Grid (grid-template-columns: 2fr 1fr)
- Alternating left/right image positions via props (imagePosition passed from parent)
- Full-width cards that span the container
- Natural height based on content (no fixed heights)
- Category badge generated from the first tag
- “Read article →” call-to-action with hover animation
- Responsive stacking on mobile (image always on top)
What Worked Well
Prompt Engineering: Being specific and iterative got the best results. When something wasn’t quite right, I could share a screenshot or describe the issue clearly, and Claude would adjust immediately.
Starting with /prd: Even though I wanted to dive straight into coding, the PRD process clarified my vision and created a roadmap that kept me focused.
The AWS Plugins: The EPCC workflow plugins provided structure. The /prd command especially was valuable for thinking through requirements upfront.
Conversational Development: I could say things like “remove the border completely and align all the cards” and Claude understood exactly what I meant in the context of our previous work.
Iterative Design Process: Starting with something basic and refining it based on visual feedback felt more natural than trying to spec everything perfectly upfront.
Challenges and Learnings
Context Management: After clearing context a few times during development, I lost some of my early conversation history. Lesson learned: export conversations regularly with /export filename to preserve the development narrative.
Image Handling: Initial image implementations used object-fit: cover, which cropped logos badly. It took a couple of iterations to realize object-fit: scale-down was the right choice for mixed content (photos + logos).
Theme CSS 404 Errors: Hard-coded paths to /src/ directory didn’t work in the production build. Learning about Vite’s asset handling and ?url imports was valuable for understanding how static site generators bundle assets.
Balancing AI Suggestions with Vision: Sometimes Claude would suggest a perfectly valid technical approach that wasn’t quite what I had in mind visually. Learning to be more specific about the design goals (“magazine-style layout” vs. “cards in a grid”) helped align the output with my vision.
The Stack
Frontend Framework:
- Astro 4.x - Static site generator optimized for content
- TypeScript - Type safety for components and content collections
- Vanilla CSS with CSS custom properties for theming
- No JavaScript framework needed (Astro is mostly static HTML)
Styling Approach:
- CSS custom properties (—brand-primary, —bg-secondary, etc.)
- Theme system with light/dark mode variants
- Responsive design using CSS Grid and Flexbox
- No Tailwind—went with vanilla CSS for learning and control
Content Management:
- Markdown/MDX for blog posts with frontmatter metadata
- Astro Content Collections for type-safe content
- Astro Image component for optimized image loading
- Shiki for syntax highlighting (built into Astro)
Deployment:
- AWS S3 for static file hosting
- AWS CloudFront for CDN and HTTPS
- AWS Route53 for DNS (deadlocked.life domain)
- GitHub for version control
- CI/CD using GitHub Actions (planned)
Development Tools:
- Claude Code with AWS EPCC plugins
- Git for version control
- VS Code as IDE
- Node.js 20+ for build tooling
What’s Next
This blog is live and functional, but there’s always room to grow:
- Add search functionality with Pagefind
- RSS feed generation for each category
- Project showcase section with live demos
- Related posts suggestions based on tags
- Reading time estimates per post
- SEO optimization (meta tags, Open Graph, sitemap)
- Analytics integration (Plausible or similar)
- Comment system (Giscus with GitHub Discussions)
- Newsletter signup for post notifications
References
- https://workshops.aws/card/bedrock?tag=Claude - The AWS re:Invent 2025 session where this started
- https://github.com/aws-solutions-library-samples/guidance-for-claude-code-with-amazon-bedrock - EPCC workflow plugins
- link-to-PRD.md - The full Product Requirements Document
- https://docs.astro.build - Static site generator docs
- https://docs.claude.ai/claude-code - Official Claude Code guide
Final Thoughts
Building this blog with Claude Code felt less like traditional coding and more like collaborative design with an AI partner who understands context. I described what I wanted, Claude asked clarifying questions, and together we iterated until it felt right.
The experience reinforced something I’ve been thinking about lately: AI tools work best when you treat them as collaborative partners, not magic code generators. The /prd command forced me to think through requirements. The iterative refinement process taught me to be specific about what I wanted. And exporting conversations gave me documentation of the entire journey.
A few key takeaways for anyone building with Claude Code:
- Start with /prd - Even if you think you know what you want, the structured questioning helps clarify your vision
- Be specific in your prompts - “Make it look better” is vague; “Magazine-style horizontal layout with 2:1 image ratio” gets better results
- Share screenshots - Visual references communicate design intent better than words alone
- Iterate, don’t specify everything upfront - Build something basic, see it live, then refine
- Export conversations - Your chat history is valuable documentation and learning material
- Understand the code - Don’t just copy/paste; ask Claude to explain complex sections
If you’re thinking about building something with Claude Code, my advice: embrace the conversational development process. Start with /prd, be specific in your prompts, share visual examples, and don’t be afraid to iterate. The results might surprise you.