Astro for a Portfolio Website
Context
Personal portfolios often fall into two traps: they are either over-engineered SPAs that load megabytes of JS for a static page, or they are restricted by No-Code platforms with poor performance. I needed a site that showcased high-end design and technical projects without the performance penalty of a heavy framework.
Decision
Adopt Astro as the primary framework to achieve 'Zero-JS' by default while retaining a component-based development workflow.
Alternatives Considered
Gatsby
- Robust GraphQL data layer
- Massive plugin ecosystem
- Complex build-time overhead
- Excessive 'Hydration' costs for static content
- High learning curve for simple sites
Next.js (Static Export)
- Industry standard
- Excellent developer experience
- Still ships the React runtime to the client
- Unnecessary client-side routing for single-page reads
Reasoning
Astro's 'Island Architecture' allows for a complete separation between static HTML and interactive components. This is ideal for a portfolio where 95% of the content (projects, bio, blogs) is static, and only 5% (contact forms, theme toggles) is interactive. It delivers the speed of a static site generator with the flexibility of React/Vue.
The “JavaScript Tax” Problem
Traditionally, using a framework like React meant that even a simple text-based blog post required the browser to download, parse, and execute the React library before the page became fully functional. This “JavaScript Tax” leads to:
- High TBT (Total Blocking Time): Browsers are busy executing JS instead of rendering content.
- Lighthouse Penalties: Lower scores due to excessive main-thread work.
The Astro Advantage
By choosing Astro, I restructured the portfolio around three core performance pillars:
1. Zero-JS by Default
Astro renders every component to plain HTML at build time. Unless I explicitly use a client directive (like client:load), the user receives zero JavaScript. This results in an instant First Contentful Paint (FCP).
2. Multi-Framework Support
Astro is framework-agnostic. For this portfolio, I was able to use:
- React for a complex, filtered project gallery.
- Svelte for a lightweight, high-performance contact form.
- Tailwind CSS for rapid, utility-first styling.
3. Content Collections
Astro’s native Content Collections API provides type-safety for Markdown and MDX files. This allowed me to manage my case studies and blog posts with the same rigor as my TypeScript code, catching broken links or missing metadata at build time.
Implementation Details
The migration focused on optimizing the “Critical Request Path”:
- Images: Leveraged the
astro:assetsservice to automatically generate AVIF versions of project screenshots. - Styles: Inlined critical CSS for the hero section while deferred loading the rest, ensuring the page feels visually complete in under 500ms.
- Islands: The “Theme Toggle” was isolated as a small Svelte island, ensuring it remains interactive while the rest of the page stays static.
Results & Impact
- Lighthouse Score: Achieved a perfect 100/100/100/100 across Performance, Accessibility, Best Practices, and SEO.
- Payload Size: The homepage weight dropped from 1.2MB (React-based) to 45KB (Astro-based).
- Time to Interactive (TTI): Reduced by 85%, providing an “instant” feel even on low-tier Android devices.
- Maintenance: Adding a new project is now as simple as dropping a
.mdxfile into a folder, with the schema ensuring I never forget a “cover image” or “tech stack” tag.
The Road Ahead
With the site now running at peak performance, I am exploring Astro DB to integrate live visitor analytics and project “likes” without sacrificing the static-first nature of the architecture.