Build a photo album organizer from zero to production using Spec-Driven Development
This tutorial walks through building a complete application from scratch using the full SDD workflow. You’ll create a photo album organizer with drag-and-drop functionality, local storage, and SQLite metadata tracking.
Time to complete: 30-45 minutesWhat you’ll build: A functional photo organizer with albums, drag-and-drop, and virtual scrollingPrerequisites: Spec Kit installed, AI assistant configured
You want to build an application that helps organize personal photo collections into albums without uploading photos to the cloud. Albums should be grouped by date and reorganizable via drag-and-drop. The app needs to handle thousands of photos efficiently.Key constraints:
Create a new project and configure your AI assistant:
# Create project with Claude Code integrationspecify init photo-organizer --ai claude# Navigate to projectcd photo-organizer# Launch AI assistantclaude
Verify setup:Check that Spec Kit commands are available:
/speckit.constitution
/speckit.specify
/speckit.plan
/speckit.tasks
/speckit.implement
Your project now has a .specify/ directory with templates, scripts, and the agent-specific command files (e.g., .claude/commands/).
Define the governing principles that will guide all development decisions:
/speckit.constitution Create principles focused on code quality, testing standards, user experience consistency, and performance requirements. The application should prioritize simplicity and use minimal dependencies. All features must be fully tested. Performance should be optimized for handling thousands of photos without lag.
What gets created:.specify/memory/constitution.md with principles like:
Example Constitution
# Project Constitution: Photo Organizer## Version- Version: 1.0.0- Ratified: 2026-03-01- Last Amended: 2026-03-01## Principles### Article I: Simplicity FirstPrioritize simple, maintainable solutions over complex architectures.**Rules:**- Use ≤3 libraries beyond the framework- Avoid abstractions until proven necessary- Prefer vanilla JS over heavy frameworks**Rationale**: Simple code is easier to maintain and has fewer bugs.### Article II: Performance by DesignThe application MUST handle thousands of photos efficiently.**Rules:**- Virtual scrolling for large collections (>100 items)- Lazy loading for thumbnails- Database queries optimized with indexes- No operation should block the UI thread >16ms**Rationale**: User experience depends on responsive performance.### Article III: Test-Driven QualityAll features must have comprehensive test coverage.**Rules:**- Unit tests for business logic- Integration tests for database operations- E2E tests for critical user journeys- Tests written before implementation (TDD)**Rationale**: Testing catches regressions and ensures reliability.### Article IV: Local-First ArchitectureUser data MUST remain on their local machine.**Rules:**- No cloud storage or uploads- Photos referenced by filesystem path- Metadata stored in local SQLite database- Offline-capable by default**Rationale**: Privacy and user data ownership are non-negotiable.
The constitution is immutable during development. If you need to change principles, document the rationale and create a new version.
Describe what you want to build (not how to build it):
/speckit.specify Build an application that helps me organize my photos into separate photo albums. Albums are grouped by date and can be reorganized by dragging and dropping on the main page. Albums are never nested inside other albums - they are always top-level. Within each album, photos are previewed in a tile-like grid interface with thumbnails. Each photo should show a thumbnail preview, capture date, and file size. Users can create new albums, delete albums, and move photos between albums using drag and drop. Users can add photos to albums by selecting files from their local filesystem. The application should feel responsive even with hundreds of albums and thousands of photos.
Populates spec.md with user stories, requirements, success criteria
5
Creates quality checklist
Generates: checklists/requirements.md to validate completeness
Generated spec.md sections:
User Stories (Prioritized)
### User Story 1 - View Album Collection (Priority: P1)Users can see all their photo albums displayed in a grid, sorted by date, with thumbnail previews.**Why this priority**: Core value - without viewing albums, no other features matter.**Independent Test**: Can be tested by creating test albums and verifying display. Delivers immediate value by showing existing photo organization.**Acceptance Scenarios**:1. **Given** user has 10 albums, **When** they open the app, **Then** all 10 albums are displayed in a grid sorted by creation date (newest first)2. **Given** an album has 100 photos, **When** album is displayed, **Then** the first 4 photos are shown as a preview thumbnail collage3. **Given** user has 500 albums, **When** they scroll the album list, **Then** albums load smoothly without lag using virtual scrolling### User Story 2 - Create and Manage Albums (Priority: P1)Users can create new albums, rename albums, and delete albums.**Why this priority**: Essential for organizing photos - users need to create structure before adding content.**Independent Test**: Can be tested by creating, renaming, and deleting albums. Delivers value by enabling organization.**Acceptance Scenarios**:1. **Given** user clicks "New Album", **When** they enter a name, **Then** a new empty album is created with the current date2. **Given** user right-clicks an album, **When** they select "Rename", **Then** they can edit the album name inline3. **Given** user selects an album and presses Delete, **When** they confirm, **Then** the album and all photo references are removed### User Story 3 - Add Photos to Albums (Priority: P1)Users can add photos from their local filesystem to albums.**Why this priority**: Core functionality - users need to populate albums with photos.**Independent Test**: Can be tested by selecting photos and verifying they appear in albums. Delivers value by enabling photo collection.**Acceptance Scenarios**:1. **Given** user opens an album, **When** they click "Add Photos" and select files, **Then** selected photos are added to the album2. **Given** user drags files from their filesystem onto an album, **When** they drop the files, **Then** photos are added to that album3. **Given** user adds 1000 photos to an album, **When** photos are added, **Then** the process completes within 5 seconds### User Story 4 - Drag and Drop Organization (Priority: P2)Users can drag photos between albums and reorder albums.**Why this priority**: Enhances UX but basic organization works without it.**Independent Test**: Can be tested by dragging photos and albums. Delivers value by improving organization efficiency.**Acceptance Scenarios**:1. **Given** user drags a photo from one album, **When** they drop it on another album, **Then** the photo moves to the target album2. **Given** user drags an album, **When** they drop it in a new position, **Then** the album order is updated and persisted3. **Given** user drags multiple selected photos, **When** they drop them on an album, **Then** all selected photos move together
Functional Requirements
### Functional Requirements- **FR-001**: System MUST store album metadata (id, name, created_date, sort_order) in local SQLite database- **FR-002**: System MUST store photo metadata (id, album_id, filepath, thumbnail_path, capture_date, file_size) in local SQLite database- **FR-003**: System MUST reference photo files by absolute filesystem path without copying/moving original files- **FR-004**: System MUST generate thumbnail images (200x200px) and cache them in application directory- **FR-005**: System MUST support JPEG, PNG, HEIC, and WebP image formats- **FR-006**: System MUST use virtual scrolling for album lists with >100 albums- **FR-007**: System MUST use virtual scrolling for photo grids with >100 photos- **FR-008**: System MUST extract EXIF metadata (capture date) from photos when available- **FR-009**: System MUST handle missing or moved photo files gracefully with placeholder thumbnails- **FR-010**: System MUST persist drag-and-drop reordering immediately to database
Success Criteria (Measurable)
## Success Criteria### Measurable Outcomes- **SC-001**: Application loads and displays 500 albums within 2 seconds- **SC-002**: Scrolling through 1000 photos maintains 60fps (no frame drops)- **SC-003**: Adding 100 photos to an album completes within 5 seconds- **SC-004**: Drag-and-drop operations complete with <100ms perceived latency- **SC-005**: Thumbnail generation for 1000 photos completes in background within 30 seconds- **SC-006**: Album creation completes within 500ms- **SC-007**: Database queries for album/photo lists complete within 50ms- **SC-008**: Application uses <100MB memory with 10,000 photos loaded
Notice the specification is technology-agnostic. No mention of Vite, React, or specific libraries yet. That comes in the plan.
If the spec has [NEEDS CLARIFICATION] markers, resolve them:
/speckit.clarify
Example clarification question:
Question: Thumbnail Storage Location
## Question 1: Thumbnail Storage**Context**: The spec mentions generating thumbnails but doesn't specify where they're stored.**What we need to know**: Where should thumbnail images be stored?**Suggested Answers**:| Option | Answer | Implications ||--------|--------|-------------|| A | Store in application data directory (`~/.photo-organizer/thumbnails/`) | Clean separation, requires disk space, persists across app restarts || B | Store in system temp directory | Automatic cleanup, regenerates on restart, saves disk space || C | Store in SQLite as blobs | Single database file, increases DB size, slower queries || Custom | Provide your own answer | Explain your preferred approach |**Your choice**: A - Store in application data directory for persistence
Answer format:
Q1: A
The AI updates the spec with your answer and re-validates the checklist.
Now specify how to build it (tech stack and architecture):
/speckit.plan The application uses Vite with a minimal number of libraries. Use vanilla HTML, CSS, and JavaScript as much as possible to keep it simple. Images are not uploaded anywhere - they stay on the local filesystem. Metadata about albums and photo organization is stored in a local SQLite database. Use the File System Access API for photo selection. Implement virtual scrolling for performance with large photo collections. Use the Web Workers API for thumbnail generation to avoid blocking the UI.
## Constitution Check### Article I: Simplicity First✓ PASS - Using vanilla JS, no React/Vue/Angular✓ PASS - Only 2 libraries: Vite (dev tool) + sql.js (database)✓ PASS - No unnecessary abstractions### Article II: Performance by Design✓ PASS - Virtual scrolling for large lists✓ PASS - Web Worker for thumbnail generation (non-blocking)✓ PASS - Database indexes on common queries✓ PASS - IndexedDB for thumbnail caching### Article III: Test-Driven Quality✓ PASS - Unit tests for database operations✓ PASS - Integration tests for file handling✓ PASS - E2E tests for drag-and-drop workflows### Article IV: Local-First Architecture✓ PASS - No cloud APIs or uploads✓ PASS - Photos stay in original locations✓ PASS - Metadata in local SQLite✓ PASS - Offline-capable (no network required)**RESULT**: All principles satisfied. Proceed to Phase 0.
If any constitution principles are violated, the AI will:
Flag the violation in the Constitution Check
Require justification in the Complexity Tracking table
Please audit the implementation plan to ensure it addresses all requirements from the spec. Check that:1. All functional requirements have corresponding implementation steps2. Performance requirements (virtual scrolling, thumbnail caching) are addressed3. The architecture aligns with our constitution principles4. No obvious gaps or missing pieces
The AI reviews the plan and suggests refinements if needed.
If using GitHub, create a PR with detailed description:
Create a pull request from branch 001-photo-album-organizer to main. Include a detailed description covering:- Feature overview- Key technical decisions- Testing approach- Performance optimizations- Screenshots or demo GIF if possible
The AI uses GitHub CLI (gh pr create) to create the PR automatically.