Why Astro for a Photography Portfolio?

When I decided to create a website to showcase my photography journey, I had several requirements:

  • Fast loading images (crucial for a photography site)
  • Static generation for optimal performance
  • Component flexibility to mix different frameworks as needed
  • Content management that doesn’t require a complex CMS
  • Modern developer experience with TypeScript support

After researching options, Astro checked all these boxes and more.

The Architecture Decision

Multi-Page vs. Single-Page App

Instead of building a complex SPA, I chose a multi-page architecture:

  • Homepage: Main portfolio with project showcases
  • Gallery: Photo collection with interactive carousel
  • Challenge: 30-day progress tracker
  • Blog: Content sharing and reflections

This approach gives each section its own focused purpose while maintaining fast navigation between pages.

Content Collections: A Game Changer

One of Astro’s standout features is Content Collections. Instead of managing content in JSON files or a headless CMS, I can write markdown files with type-safe frontmatter:

// src/content/config.ts
const blog = defineCollection({
	type: "content",
	schema: z.object({
		title: z.string(),
		description: z.string(),
		publishDate: z.date(),
		heroImage: z.string().optional(),
		tags: z.array(z.string()).default([]),
		draft: z.boolean().default(false),
	}),
});

This gives me TypeScript intellisense for all my content and catches errors at build time.

Technical Implementation Highlights

For the gallery, I needed something that could handle high-resolution images gracefully. Swiper.js provided:

  • Touch-friendly navigation for mobile users
  • Lazy loading for performance
  • Zoom functionality for detailed viewing
  • Thumbnail navigation for quick browsing
const mainSwiperConfig = {
	modules: [Navigation, Pagination, Thumbs, Zoom],
	spaceBetween: 10,
	navigation: true,
	zoom: true,
	// ... more config
};

Component Strategy

I used a hybrid approach with components:

  • Astro components for layout and static content
  • React components for interactive features (gallery, challenge tracker)
  • Custom CSS variables for consistent theming

This allows for selective hydration—only the interactive parts load JavaScript.

Image Optimization

Astro’s image optimization is fantastic for a photography site:

---
import { Image } from "astro:assets";
---

<Image src={photo.image} alt={photo.title} width={800} height={600} loading="lazy" />

This automatically generates optimized WebP versions and responsive sizes.

Development Workflow

Content Creation

Adding new photos or blog posts is as simple as creating a markdown file:

---
title: "Golden Hour Cityscape"
captureDate: 2025-01-10T18:30:00Z
camera: "Canon EOS R6"
settings:
  aperture: "f/8"
  shutter: "1/250"
  iso: "200"
tags: ["cityscape", "golden-hour"]
---

This shot was taken during my 5th day of the challenge...

Type Safety

The Content Collections provide full TypeScript support, so I get autocomplete and error checking for all content:

const allPosts = await getCollection("blog");
const publishedPosts = allPosts
	.filter((post) => !post.data.draft)
	.sort((a, b) => new Date(b.data.publishDate).getTime() - new Date(a.data.publishDate).getTime());

Performance Results

The static generation approach delivers excellent results:

  • Build time: ~3 seconds for the entire site
  • Lighthouse scores: 95+ across all metrics
  • Bundle size: Under 200KB for JavaScript
  • Image loading: Lazy loading with WebP optimization

Lessons Learned

1. Start Simple, Add Complexity Gradually

I began with basic pages and added features like the photo gallery incrementally. This prevented overwhelming complexity early on.

2. Content Collections Are Powerful

The type-safe content management eliminated entire categories of bugs and made content creation enjoyable.

3. Static Sites Don’t Mean Static Experiences

With selective hydration, I can have rich interactions (image galleries, progress trackers) while maintaining performance.

4. Developer Experience Matters

Astro’s dev server with hot reloading and TypeScript support made the development process smooth and enjoyable.

What’s Next

Some features I’m considering for future iterations:

  • Search functionality for blog posts and photos
  • Comment system for blog engagement
  • RSS feed for blog subscribers
  • Progressive enhancement for offline viewing

The Photography Connection

Building this portfolio has reinforced something important: both photography and web development are about creating experiences. Whether I’m composing a photo or architecting a website, I’m thinking about how someone will interact with and experience my work.

The technical skills transfer in unexpected ways—understanding composition in photography helps with visual design decisions, and the systematic approach to learning development translates well to learning photography fundamentals.

Interested in the technical details? The source code for this site showcases modern Astro patterns and could be a useful reference for your own projects.