astro-photostream
v0.3.7
Published
An Astro integration for creating photo galleries with AI metadata generation and geolocation features
Downloads
23
Maintainers
Readme
Astro Photo Stream
An Astro integration for creating sophisticated photo galleries and streams with AI-powered metadata generation, geolocation features, and responsive design. Transform your photos into beautiful, SEO-optimized galleries with minimal configuration.
Features
AI-Powered Metadata - Automatic titles, descriptions, and tags using Claude/OpenAI
Smart Geolocation - Location name resolution with privacy-focused blur/offset options
Static Maps - Single and multi-marker maps with intelligent location consolidation
Responsive Design - 2/3/4 column layouts that work perfectly on all devices
SEO Optimized - Dynamic OpenGraph images and structured data
Performance First - Static generation with lazy loading and image optimization
Tag System - Automatic tag-based filtering and navigation
Pagination - Built-in pagination with keyboard navigation
EXIF Processing - Comprehensive camera metadata extraction
Theme Independent - Works with any Astro theme or site
Quick Start
Installation
# Using npm
npx astro add astro-photostream
# Using pnpm
pnpm astro add astro-photostream
# Using yarn
yarn astro add astro-photostreamBasic Setup
- Add the integration to your
astro.config.mjs:
import { defineConfig } from 'astro/config';
import photoStream from 'astro-photostream';
export default defineConfig({
integrations: [
photoStream({
// Zero-config setup works out of the box!
}),
],
});- Create your photo content collection (
src/content/config.ts):
import { defineCollection } from 'astro:content';
import { photoSchema } from 'astro-photostream/schema';
const photos = defineCollection({
type: 'content',
schema: photoSchema,
});
export const collections = { photos };- Add photos using the two-directory system:
src/
├── assets/photos/ # Actual image files
│ ├── sunset-beach.jpg
│ └── mountain-hike.jpg
└── content/photos/ # Metadata (.md) files
├── sunset-beach.md
└── mountain-hike.md- Create photo entries (
src/content/photos/sunset-beach.md):
---
title: 'Golden Hour at the Beach'
description: 'Stunning sunset over the Pacific Ocean'
coverImage:
src: '../../assets/photos/sunset-beach.jpg'
alt: 'Golden sunset over ocean waves'
tags: ['sunset', 'beach', 'golden-hour']
publishDate: 2024-08-15
location:
name: 'Malibu Beach, California'
latitude: 34.0259
longitude: -118.7798
---
A perfect evening capturing the golden hour at Malibu Beach.- Your photo gallery is ready! Visit
/photoson your site.
Advanced Configuration
Complete Configuration Example
// astro.config.mjs
import { defineConfig } from 'astro/config';
import photoStream from 'astro-photostream';
export default defineConfig({
integrations: [
photoStream({
// Photo processing
photos: {
directory: 'src/content/photos',
formats: ['jpg', 'jpeg', 'png', 'webp'],
maxWidth: 1920,
maxHeight: 1080,
quality: 85,
},
// AI metadata generation
ai: {
enabled: true,
provider: 'claude', // 'claude' | 'openai' | 'custom'
apiKey: process.env.CLAUDE_API_KEY,
model: 'claude-3-sonnet-20240229',
prompt: 'Analyze this photo and suggest a title and description...',
},
// Geolocation with privacy
geolocation: {
enabled: true,
privacy: {
enabled: true,
radius: 1000, // meters
method: 'blur', // 'blur' | 'offset' | 'disable'
},
},
// Gallery display
gallery: {
itemsPerPage: 20,
gridCols: {
mobile: 2,
tablet: 3,
desktop: 4,
},
enableMap: true,
enableTags: true,
enableSearch: false,
},
// SEO optimization
seo: {
generateOpenGraph: true,
siteName: 'My Photo Gallery',
twitterHandle: '@yourhandle',
},
}),
],
});Environment Variables
# .env
CLAUDE_API_KEY=sk-ant-api03-...
OPENAI_API_KEY=sk-...
OPENCAGE_API_KEY=your-opencage-keyConfiguration File
Create astro-photostream.config.js for advanced configuration:
export default {
ai: {
enabled: true,
provider: 'claude',
model: 'claude-3-sonnet-20240229',
prompt: `Analyze this photo professionally. Provide:
- A compelling, descriptive title (under 60 chars)
- A detailed description (2-3 sentences)
- 3-5 relevant tags`,
},
geolocation: {
enabled: true,
privacy: {
enabled: true,
radius: 2000,
method: 'blur',
},
},
};CLI Commands
The package includes powerful CLI tools for metadata generation:
Generate Metadata for All Photos
# Using npx
npx astro-photostream
# Using the full command
npx photo-metadata-generator
# With options
npx astro-photostream --ai --location --update-exifCLI Options
# Generate AI metadata only
npx astro-photostream --ai
# Update location information only
npx astro-photostream --location
# Update EXIF data only
npx astro-photostream --update-exif
# Generate configuration file
npx astro-photostream --generate-config
# Batch process with progress
npx astro-photostream --batch --progress
# Help
npx astro-photostream --helpComponents
Import and use components directly in your Astro pages:
PhotoGrid
---
import { PhotoGrid } from 'astro-photostream/components';
import { getCollection } from 'astro:content';
const photos = await getCollection('photos');
---
<PhotoGrid
photos={photos}
columns={{ mobile: 2, tablet: 3, desktop: 4 }}
class="my-custom-grid"
/>PhotoCard
---
import { PhotoCard } from 'astro-photostream/components';
---
<PhotoCard
photo={photo}
loading="lazy"
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>MultiMarkerMap
---
import { MultiMarkerMap } from 'astro-photostream/components';
---
<MultiMarkerMap
photos={photosWithLocation}
consolidationRadius={5000}
/>Routing
The integration automatically creates these routes:
/photos- Main photo gallery (paginated)/photos/2,/photos/3, etc. - Pagination/photos/[slug]- Individual photo pages/photos/tags/[tag]- Tag-based filtering/photos/tags/[tag]/2- Tag pagination/api/og/photo/[slug].png- Dynamic OG images
Utilities
Photo Data Processing
import {
getAllPhotos,
getPhotosByTag,
getFeaturedLocations,
getPhotoStatistics,
} from 'astro-photostream/utils';
// Get all published photos
const photos = await getAllPhotos();
// Filter by tag
const landscapePhotos = await getPhotosByTag('landscape');
// Get location data for maps
const locations = await getFeaturedLocations();
// Get statistics
const stats = await getPhotoStatistics();Metadata Generation
import { generatePhotoMetadata } from 'astro-photostream/utils';
const metadata = await generatePhotoMetadata('/path/to/photo.jpg', {
ai: { enabled: true, provider: 'claude' },
geolocation: { enabled: true },
});Mobile Support
- Responsive Design: Automatically adapts to all screen sizes
- Touch Navigation: Swipe gestures for photo browsing
- Performance: Optimized loading and lazy loading for mobile
- Accessibility: Full keyboard and screen reader support
Styling
The components use minimal CSS classes that you can easily override:
/* Custom styling */
.photo-grid {
gap: 2rem;
}
.photo-card {
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.photo-card:hover {
transform: translateY(-4px);
transition: transform 0.2s ease;
}Photo Schema
The content collection schema includes:
{
title: string; // Photo title
description?: string; // Optional description
coverImage: { // Image configuration
src: string; // Path to image file
alt: string; // Alt text for accessibility
};
camera?: string; // Camera make/model
lens?: string; // Lens information
settings?: { // Camera settings
aperture?: string; // f/2.8
shutter?: string; // 1/250s
iso?: string; // ISO 100
focalLength?: string; // 85mm
};
location?: { // GPS location
name?: string; // Location name
latitude?: number; // GPS coordinates
longitude?: number;
};
tags: string[]; // Photo tags
publishDate: Date; // Publication date
draft: boolean; // Draft status
}Privacy & Security
- Location Privacy: Configurable blur radius and offset for GPS coordinates
- API Key Security: Environment variable configuration
- EXIF Stripping: Optional removal of sensitive metadata
- Content Security: Safe handling of user-generated content
Performance
- Static Generation: All pages are statically generated at build time
- Image Optimization: Automatic image optimization and responsive images
- Lazy Loading: Images load only when needed
- Code Splitting: Minimal JavaScript bundle sizes
- CDN Ready: Perfect for deployment to any CDN or static host
Development
Local Development
# Clone the repository
git clone https://github.com/walterra/astro-photostream.git
cd astro-photostream
# Install dependencies
pnpm install
# Build CLI tools
pnpm build:cli
# Run tests
pnpm test
# Link for local testing
pnpm link --globalTesting in Another Project
# In your Astro project
pnpm link --global astro-photostreamContributing
We welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
MIT License - see the LICENSE file for details.
Font Licenses
The OG image generation feature downloads and uses Roboto Mono font files during installation, which are licensed under the SIL Open Font License v1.1. The font files are automatically downloaded from the official Google Fonts repository and are used solely for generating OpenGraph images.
Acknowledgments
- Built with Astro and astro-integration-kit
- EXIF processing powered by exifr
- Image optimization using Sharp
- AI integration with Anthropic Claude and OpenAI
- OG image generation with Satori and Resvg
- Fonts courtesy of Google Fonts
Resources
Star this repo if you find it useful!
