12/4/2024
Share this post:
Export:

Building a photo gallery system might seem straightforward at first, but creating one that's both developer-friendly and production-ready involves solving several interesting challenges. Here's how I built an automated photo management system that handles everything from local development to production deployment.
I wanted a system that would:
The system consists of four main components:
The first step was defining our types. This might seem premature, but having a clear data model was crucial:
interface PhotoAsset {
id: string;
path: string;
checksum: string;
importedAt: Date;
metadata: {
exif?: ExifData;
aiGenerated?: {
description?: string;
tags?: string[];
// ... more AI fields
};
humanVerified?: {
description?: string;
tags?: string[];
galleries?: string[];
isPublic: boolean;
};
};
}
This structure supports both immediate needs and future features like AI tagging.
The import system watches for new photos and processes them automatically:
export class PhotoImporter {
async watchDirectory(path: string): Promise<FSWatcher> {
const watcher = chokidar.watch(path, {
ignored: /(^|[\/\\])\../,
persistent: true,
ignoreInitial: false,
});
watcher.on('add', async (filePath: string) => {
if (this.isSupported(filePath)) {
const checksum = await this.getFileChecksum(filePath);
await this.queueImport(filePath, checksum);
}
});
return watcher;
}
}
Rather than processing photos synchronously, I implemented a queue system:
This approach provides reliability and extensibility for future processing steps.
The most interesting challenge was handling the development-production transition. The solution was elegant:
function getPhotoUrl(photo: PhotoAsset): string {
if (process.env.NODE_ENV === 'development') {
return `/api/photos/${photo.id}`;
} else {
return `https://${bucketName}.s3.amazonaws.com/photos/${photo.id}.jpg`;
}
}
SST v3 made the AWS infrastructure setup clean and simple:
const photoBucket = new sst.aws.Bucket("PhotoBucket", {
access: "public",
cors: {
allowOrigins: ["*"],
allowMethods: ["GET"],
},
});
The UI needed to be both beautiful and functional:
The system is designed for expansion:
The system is easy to integrate into your own projects:
# Start the photo watcher
npm run watch-photos
# Deploy to production
npx sst deploy
# Sync photos to S3
npm run sync-photos
Building this system was a great example of how modern tools like Next.js, SST, and TypeScript can come together to create something powerful yet maintainable. The architecture supports both immediate needs and future expansion, making it a solid foundation for any photo management system.
Stay tuned for future posts about adding AI capabilities to this system!
Get notified when I publish new blog posts about game development, AI, entrepreneurship, and technology. No spam, unsubscribe anytime.