npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

astro-photostream

v0.3.7

Published

An Astro integration for creating photo galleries with AI metadata generation and geolocation features

Downloads

23

Readme

Astro Photo Stream

npm version License: MIT TypeScript

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-photostream

Basic Setup

  1. 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!
    }),
  ],
});
  1. 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 };
  1. 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
  1. 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.
  1. Your photo gallery is ready! Visit /photos on 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-key

Configuration 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-exif

CLI 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 --help

Components

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 --global

Testing in Another Project

# In your Astro project
pnpm link --global astro-photostream

Contributing

We welcome contributions! Please see our Contributing Guide for details.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. 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


Resources

Star this repo if you find it useful!