A delightful S3-powered headless CMS for creative professionals
Bucketlist is a beautiful, desktop-native content management system that turns your AWS S3 bucket into a powerful headless CMS. Perfect for music producers, photographers, writers, and developers who want complete ownership of their content with zero vendor lock-in.
- 💰 Own Your Content: All data lives in YOUR S3 bucket. No proprietary databases, no vendor lock-in.
- 🎨 Beautiful UI: Modern, theme-aware interface with light and dark modes
- 🚀 Instant API: Auto-generate REST APIs with configurable endpoints
- 📦 Zero Infrastructure: No servers to maintain, just S3
- 🎵 Media Rich: Full support for images, audio, embeds, and rich text
- 🔒 Secure: Built with web security enabled, CSP, and sandboxing
- 🎯 Schema First: Define your content structure, get TypeScript types automatically
- 🎸 Music Portfolios - Showcase tracks, albums, and releases
- 📸 Photography - Manage galleries with optimized images
- ✍️ Writers - Blogs, articles, and creative content
- 🎨 Creative Portfolios - Projects, case studies, and work samples
- 🎙️ Podcasters - Episodes, show notes, and audio files
- 🛍️ Product Catalogs - E-commerce content without the database
- ✅ Visual Schema Builder - Create content structures with a drag-and-drop interface
- ✅ Collection Management - Organize entries by type with custom ordering
- ✅ Rich Media Support - Images, audio files, and social embeds
- ✅ Markdown Editor - Rich text with live preview and formatting toolbar
- ✅ Media Library - Centralized asset management with usage tracking
- ✅ Drag & Drop Reordering - Intuitive content organization
- ✅ Multi-Bucket Support - Manage multiple S3 buckets with complete data isolation
- ✅ Automatic Migration - Seamless data import when switching between buckets
- 📝 String - Text fields with pattern validation
- 🔢 Number - Numeric fields with min/max constraints
- ✅ Boolean - True/false toggles
- 📋 Array - Repeatable field groups
- 🗂️ Object - Nested data structures
- 📅 Date - Date/time pickers
- 🖼️ Image - Auto-optimized images with responsive sizes (thumbnail, small, medium, large, xlarge) + WebP variants
- 🎵 Audio - MP3, WAV, OGG, M4A file uploads
- 📺 Embed - YouTube, Vimeo, Spotify, SoundCloud, and more
- 📄 Rich Text - Markdown with live preview
- 🌐 REST API - Automatically generated JSON endpoints
- 🔗 Slug-based URLs - Human-readable API paths
- 📂 Configurable Directories - Customize your S3 folder structure
- 📊 TypeScript Types - Auto-generated type definitions from schemas
- 🎯 Schema Collections - Query entries by schema type
- 📖 API Documentation - Interactive docs with code examples
- ⚡ CloudFront CDN - Optional CDN support for faster delivery and lower costs
- 🔄 Smart URL Transformation - Automatic S3 to CloudFront URL conversion in published APIs
- 📐 Responsive Sizes - 5 sizes generated automatically
- 🎨 WebP Support - Modern format with fallbacks
- 🖼️ srcSet Ready - Perfect for Next.js Image and responsive design
- ⚡ Fast Loading - Optimized for web performance
- 🎨 Theming - Light and dark modes with custom color schemes
- ⚙️ Configurable - Customize image sizes, directories, and more
- 🔍 API Preview - Browse your published API with live data
- 📝 TypeScript First - Full type safety across the stack
- 🧪 Testing - Vitest + Testing Library setup
- 🪝 Git Hooks - Auto-formatting with husky + lint-staged
- Node.js v18 or v20 (recommended)
- npm v8 or higher
- AWS S3 bucket with public access configured
- AWS credentials (IAM user or SSO profile)
# Clone the repository
git clone https://github.com/SecretLaboratory/cursor-s3-cms.git
cd cursor-s3-cms
# Install dependencies
npm install
# Run in development mode
npm run dev# Build the application
npm run build
# Create distributable packages
npm run dist # All platforms
npm run dist:mac # macOS only
npm run dist:win # Windows only
npm run dist:linux # Linux only- Launch Bucketlist
- Click "Configure S3" on the landing page
- Enter your AWS credentials:
- Region: Your S3 bucket region (e.g.,
us-east-1) - Bucket: Your bucket name
- Auth Method: Access Keys or AWS Profile
- Region: Your S3 bucket region (e.g.,
- Click "Save Configuration"
Pro Tip: Use AWS IAM Identity Center (SSO) for better security!
- Navigate to "Schema Builder"
- Click "Create New Schema"
- Give it a name (e.g.,
BlogPost,Album,Project) - Add fields:
- Title (String, required)
- Content (Rich Text)
- Cover Image (Image)
- Audio Track (Audio) - for music!
- Published Date (Date)
- Click "Save Schema"
- Go to "Content Manager"
- Click "Create Collection"
- Select your schema
- Add collection metadata:
- Name: "Featured Albums"
- Description: "My best work"
- Slug:
featured-albums - Primary Image (optional)
- Click "Create"
- Select your collection
- Click "Add Entry"
- Fill in your content:
- Upload images (auto-optimized to 5 sizes + WebP!)
- Upload audio files (MP3, WAV, OGG, M4A)
- Write rich text with markdown
- Add social embeds (YouTube, Spotify, etc.)
- Click "Save Entry"
- Drag & drop to reorder
- Go to "Content Manager"
- Click "Publish Changes"
- Your content is now live at:
- Collections:
https://YOUR-BUCKET.s3.amazonaws.com/api/collections/index.json - Entries:
https://YOUR-BUCKET.s3.amazonaws.com/api/entries/{slug}.json
- Collections:
// In your Next.js/React app
const response = await fetch('https://YOUR-BUCKET.s3.amazonaws.com/api/collections/index.json')
const collections = await response.json()Bonus: Use the TypeScript types from "API Documentation" tab!
Manage multiple projects or clients with separate S3 buckets:
-
Add New Bucket:
- Go to Settings → S3 Configuration
- Click "Add New Bucket" or "Switch Bucket"
- Enter new bucket details (name, region, credentials)
- Click "Save Configuration"
-
Automatic Migration:
- When switching to a new bucket, migration starts automatically
- Modal shows "Importing Data" with progress
- All existing S3 data is imported to local database
- No manual setup required!
-
Data Isolation:
- Each bucket maintains separate schemas and content
- Switch between buckets instantly
- Perfect for freelancers managing multiple clients
For production sites, use CloudFront for faster delivery and lower costs:
-
Create CloudFront Distribution:
- Go to AWS CloudFront Console
- Create distribution, select your S3 bucket as origin
- Wait 10-15 minutes for deployment
-
Configure in Bucketlist:
- Go to Settings → S3 Configuration
- Paste your CloudFront URL (e.g.,
https://d1234567890.cloudfront.net) - It auto-saves!
-
Republish Content:
- Go to Content Manager
- Click "Publish Changes"
- All API URLs now use CloudFront! 🚀
Benefits:
- ⚡ 10x faster delivery (edge locations worldwide)
- 💰 Lower bandwidth costs
- 🔒 HTTPS by default
- 🌐 Custom domain support
See the Help section in Bucketlist for detailed CloudFront setup instructions.
- 🪣 Multiple S3 Buckets - Manage different projects or clients in separate buckets
- 🔒 Complete Data Isolation - Each bucket maintains its own schemas, collections, and entries
- 🔄 Automatic Migration - When switching to a new bucket, data is automatically imported from S3
- ⚡ Seamless Switching - No app restart required - switch between buckets instantly
- 📊 Bucket-Specific Analytics - Track publishing dates and entry counts per bucket
- 🛡️ Data Integrity - Built-in safeguards prevent data mixing between buckets
Use Cases:
- Freelancers: Separate buckets for different clients
- Agencies: Different projects with isolated content
- Multi-Site: Separate content for different websites
- Testing: Production vs staging environments
- View all uploaded images and audio files
- Track asset usage across entries
- Filter by type (images, audio, embeds)
- Search by filename
- Preview and download assets
- Copy URLs for direct use
- Delete unused assets (with usage warnings)
- Optional CloudFront integration for production deployments
- Faster content delivery via global CDN edge locations
- Lower costs - Reduced S3 bandwidth fees
- Better performance - Automatic caching at the edge
- Custom domains - Use your own domain (e.g., cdn.yourdomain.com)
- HTTPS included - Free SSL certificates
- Smart URL transformation:
- CMS stores S3 URLs internally (reliable, always works)
- Published API automatically converts all URLs to CloudFront
- Works across all API endpoints (collections, entries, schema lookups)
- Transforms
primaryImageand all asset URLs in published content - Zero manual configuration required
- Easy setup - Step-by-step guide in Help section
- Zero breaking changes - Completely optional, falls back to S3
- Built-in light and dark modes
- Customizable color schemes
- Preview your theme live
- Consistent theming across all UI elements
- Customize S3 folder structure:
/api→ your custom API path/collections→ collections folder/entries→ entries folder/assets→ media assets folder/schemas→ schemas folder
- Perfect for multi-site setups
- Auto-generated types from your schemas
- Full intellisense in your code editor
- Type-safe content access
- Copy/paste ready interfaces
- 🔄 Real-time Updates - Entry counts and last published dates update automatically
- 📊 Live Status Indicators - See publishing status and entry counts in real-time
- 🎯 Intuitive State Management - No more manual refreshes needed
- ⚡ Instant Feedback - UI updates immediately after content changes
- 🔍 Smart Data Isolation - Each bucket maintains its own state and analytics
- Live API Browser - Explore your published endpoints in-app
- Interactive Documentation - Code examples for JavaScript, cURL, and more
- Workflow:
- Create/edit content in Content Manager
- Click "Publish Changes" to generate API
- View published data in API Preview tab
- Note: API Preview shows published data, not draft changes
GET /api/collections/index.json
Returns list of all collections with metadata.
GET /api/collections/{slug}.json
Returns collection details with all entries.
GET /api/entries/{slug}.json
Returns individual entry with all data and metadata.
GET /api/collections/{SchemaName}.json
Returns all collections using a specific schema.
Perfect for music producers and podcasters:
interface AudioField {
url: string // Direct S3 URL
key: string // S3 object key
filename: string // Original filename
size: number // File size in bytes
mimeType: string // audio/mpeg, audio/wav, etc.
duration?: number // Duration in seconds
uploadedAt: string // ISO timestamp
}Supported Formats: MP3, WAV, OGG, M4A (max 50MB)
Automatic responsive image generation:
interface ImageField {
url: string // Original image URL
filename: string
width: number
height: number
sizes: {
thumbnail: { url; width; height; webpUrl }
small: { url; width; height; webpUrl }
medium: { url; width; height; webpUrl }
large: { url; width; height; webpUrl }
xlarge: { url; width; height; webpUrl }
}
srcSet: string // Responsive srcset attribute
webpSrcSet: string // WebP srcset for modern browsers
}Perfect for Next.js Image:
<Image
src={image.sizes.medium.url}
srcSet={image.srcSet}
sizes="(max-width: 768px) 100vw, 50vw"
width={image.sizes.medium.width}
height={image.sizes.medium.height}
alt="My image"
/>Support for popular platforms:
▶️ YouTube- 🎬 Vimeo
- 🎵 Spotify
- 🔊 SoundCloud
- 🐦 Twitter/X
Just paste the URL - Bucketlist handles the rest!
- Web Security Enabled - Full Electron security hardening
- Content Security Policy - Strict CSP in production (allows S3 + CloudFront)
- Sandbox Mode - Renderer process sandboxing
- No Inline Scripts - Clean separation of concerns
- IAM Best Practices - Use SSO or dedicated IAM users
- CloudFront Ready - Optional CDN with HTTPS by default
Recommended AWS IAM Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject", "s3:ListBucket"],
"Resource": ["arn:aws:s3:::YOUR-BUCKET-NAME", "arn:aws:s3:::YOUR-BUCKET-NAME/*"]
}
]
}# Run tests
npm run test
# Run tests with UI
npm run test:ui
# Run tests in watch mode
npm run test:watch
# Generate coverage report
npm run test:coveragenpm run dev # Start development server
npm run build # Build for production
npm run lint # Run ESLint
npm run lint:fix # Auto-fix linting issues
npm run format # Format code with Prettier
npm run test:run # Run tests once
npm run pack # Build without packagingcursor-s3-cms/
├── src/
│ ├── main/ # Electron main process
│ │ ├── services/ # S3, content, media services
│ │ ├── main.ts # App entry point
│ │ └── preload.ts # IPC bridge
│ ├── renderer/ # React frontend
│ │ ├── components/ # UI components
│ │ ├── hooks/ # Custom React hooks
│ │ ├── contexts/ # React contexts
│ │ └── utils/ # Utilities
│ ├── types/ # TypeScript definitions
│ └── test/ # Test utilities
├── build/ # Build resources (icons)
└── release/ # Distribution packages
Frontend:
- ⚛️ React 18
- 📘 TypeScript
- 🎨 Tailwind CSS
- 🎯 Vite
- 🍞 React Hot Toast
- 🖱️ DnD Kit (drag & drop)
- ✏️ Lucide Icons
Backend:
- ⚡ Electron 28
- ☁️ AWS SDK v3
- 🖼️ Sharp (image processing)
- 💾 Electron Store
Development:
- 🧪 Vitest + Testing Library
- 🎨 ESLint + Prettier
- 🪝 Husky + lint-staged
- 🔨 Electron Builder
Schemas are JSON files with strong typing:
{
"id": "album-2024",
"name": "Album",
"description": "Music album schema",
"version": "1.0.0",
"fields": [
{
"id": "title",
"name": "title",
"type": "string",
"required": true,
"description": "Album title"
},
{
"id": "cover",
"name": "cover_art",
"type": "image",
"required": true,
"description": "Album artwork"
},
{
"id": "tracks",
"name": "tracks",
"type": "array",
"required": false,
"description": "Album tracks",
"itemType": "object"
},
{
"id": "audio",
"name": "preview_track",
"type": "audio",
"required": false,
"description": "Preview audio"
}
],
"createdAt": "2025-10-15T00:00:00.000Z",
"updatedAt": "2025-10-15T00:00:00.000Z"
}Bucketlist includes beautiful built-in themes:
- 🌊 Ocean Blue (Default)
- 🌙 Midnight (Dark)
- 🌸 Rose (Warm)
- 🌲 Forest (Earthy)
- 🌅 Sunset (Vibrant)
- 🍇 Grape (Purple)
Plus: Create your own custom themes!
Customize generated image sizes in Settings:
{
"thumbnail": { "width": 150 },
"small": { "width": 320 },
"medium": { "width": 640 },
"large": { "width": 1024 },
"xlarge": { "width": 1920 }
}Images maintain aspect ratio and include WebP variants automatically.
Configure your S3 folder layout:
your-bucket/
├── api/ # Published API endpoints
│ ├── collections/ # Collection index files
│ └── entries/ # Individual entry files
├── collections/ # Collection metadata
├── entries/ # Entry JSON files
├── assets/ # Media files
│ ├── originals/ # Original images
│ ├── audio/ # Audio files
│ ├── thumbnail/ # 150px images
│ ├── small/ # 320px images
│ ├── medium/ # 640px images
│ ├── large/ # 1024px images
│ ├── xlarge/ # 1920px images
│ └── *-webp/ # WebP variants
└── schemas/ # Schema definitions
All folder names are customizable in Settings!
Schema: Album
- Title (String)
- Cover Art (Image) → Auto-generates 5 sizes + WebP
- Release Date (Date)
- Tracks (Array)
- Preview (Audio) → MP3/WAV upload
- Spotify Link (Embed)
- Bio (Rich Text) → Markdown
API Output:
{
"id": "neon-dreams-2025",
"slug": "neon-dreams",
"metadata": {
"title": "Neon Dreams",
"description": "My latest album"
},
"data": {
"cover_art": {
"url": "https://bucket.s3.amazonaws.com/assets/originals/cover.jpg",
"sizes": {
"thumbnail": { "url": "...", "width": 150, "height": 150 },
"medium": { "url": "...", "width": 640, "height": 640 }
},
"srcSet": "...",
"webpSrcSet": "..."
},
"preview_track": {
"url": "https://bucket.s3.amazonaws.com/assets/audio/track1.mp3",
"filename": "track1.mp3",
"size": 5242880,
"mimeType": "audio/mpeg",
"duration": 245
}
}
}Your Website:
// Fetch and display with full type safety!
import type { Album } from './types/generated'
const album: Album = await fetch('...').then(r => r.json())
<Image
src={album.data.cover_art.sizes.medium.url}
srcSet={album.data.cover_art.srcSet}
alt={album.metadata.title}
/>
<audio controls src={album.data.preview_track.url} />Problem: Can't connect to S3
- ✅ Check AWS credentials are valid
- ✅ Verify bucket exists in the correct region
- ✅ Ensure bucket has public read access
- ✅ Check IAM permissions (S3 read/write)
Problem: Images don't load in browser
- ✅ Add bucket policy for public read (see Help section)
- ✅ Verify CORS is configured
- ✅ Check Content-Type headers
Problem: npm install fails
- ✅ Use Node.js v18 or v20 (not v21)
- ✅ Run
npm install --legacy-peer-deps - ✅ Clear cache:
rm -rf node_modules package-lock.json && npm install
Problem: Sharp module errors
- ✅ Run
npm run postinstallto rebuild native modules - ✅ Check platform compatibility (macOS/Windows/Linux)
Problem: Image/audio upload fails
- ✅ Check file size limits (Images: 10MB, Audio: 50MB)
- ✅ Verify supported formats
- ✅ Check S3 bucket permissions
- ✅ Look for errors in DevTools console
We love contributions! Here's how:
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Make your changes
- Test thoroughly:
npm run test - Commit with pre-commit hooks:
git commit -m "feat: add amazing feature" - Push to your fork:
git push origin feature/amazing-feature - Open a Pull Request
- Pre-commit hooks automatically format your code
- ESLint + Prettier enforce consistent style
- TypeScript strict mode enabled
- Follow conventional commits
MIT License - you're free to use Bucketlist for personal or commercial projects!
Built with love for creative professionals who deserve better tools.
Technologies:
- AWS S3 for rock-solid storage
- Electron for desktop experience
- React for beautiful UI
- Sharp for lightning-fast image processing
Need help? We've got you covered:
- 📖 Check the Help tab in the app for detailed guides
- 🐛 Search Issues on GitHub
- 💬 Open an Issue with:
- What you're trying to do
- What's happening instead
- Screenshots if relevant
- Your OS and Node.js version
- ✅ Multi-Bucket Support - Manage multiple S3 buckets with complete isolation
- ✅ Automatic Migration - Seamless data import when switching buckets
- ✅ CloudFront URL Transformation - Smart URL conversion in published APIs
- ✅ Enhanced UX - Real-time updates and improved state management
- ✅ Data Integrity - Built-in safeguards against data mixing
- Video field support
- Bulk import/export
- Content versioning
- Collaborative editing
- Webhooks for publish events
- Search and filtering
- Backup and restore functionality
Made with 🪣 by creative professionals, for creative professionals
Stop wrestling with complicated CMSs. Start creating.