A mobile-first web application for storing, organizing, and managing hundreds of AI image prompts efficiently. No account required—everything stays in your browser.
✨ Mobile-First Design
- Optimized for mobile devices with touch-friendly interface
- Responsive layout that works seamlessly on desktop
- Off-canvas sidebar navigation for mobile
🔍 Smart Search & Filtering
- Real-time search across prompt titles and content
- Multi-tag filtering for precise prompt discovery
- Favorites-only view for quick access
- Sort by newest, oldest, title, or favorites
📱 Prompt Management
- Create, edit, and delete prompts with inline editing
- Add custom tags to organize prompts
- Quick copy-to-clipboard functionality
- Mark prompts as favorites with one click
- Image storage with automatic compression
- Upload and display reference images with each prompt
🤖 AI Features
- Auto-generate titles and tags from prompt content
- Generate 1-2 sentence AI summaries for quick scanning
- Bulk generation for all prompts at once
💾 Secure Local Storage
- All metadata stored in browser's localStorage
- Large images stored in IndexedDB (50MB+ capacity)
- No server required, no data tracking
- Automatic persistence across sessions
📤 Import/Export
- Export all prompts as JSON for backup
- Import previously exported data
- Easy data portability
- React 18 - UI library
- Vite - Lightning-fast build tool
- TypeScript - Type safety
- Tailwind CSS - Utility-first styling
- shadcn/ui - High-quality component library
- lucide-react - Beautiful icons
- Radix UI - Accessible component primitives
npm install
npm run dev
The app will open at
http://localhost:5173
npm run build
Output is in the
dist/
directory.
- Click "New Prompt" button
- Enter a title (e.g., "Cyberpunk City")
- Enter your AI image prompt content
- Optional: Click "Generate" to auto-generate title and tags via AI
- Upload an image reference (optional)
- Add custom tags
- Click "Save Prompt"
- Use the Search bar to filter by title or content
- Select tags in "Filter by Tags" dropdown (AND logic)
- Toggle "Favorites Only" for quick access
- Use Sort dropdown to order by newest, oldest, title, or favorites
- View Details: Click a prompt card to see full view with image
- Edit: Click edit icon to modify title, content, or tags inline
- Generate Summary: Click the sparkle icon to generate AI summary
- Copy: Click copy icon to copy prompt text
- Favorite: Click heart icon to favorite/unfavorite
- Delete: Click trash icon (with confirmation)
- Generate Titles & Tags: AI analyzes content to suggest title and relevant tags
- Generate Summaries: Creates 1-2 sentence punchy summaries for all prompts
- Bulk Operations: Generate summaries for all prompts at once
- Export: Click "Export" to download all prompts + images as JSON
- Import: Click "Import" and select a previously exported JSON file
- Useful for backup, migration, or sharing between devices
src/
├── components/
│ ├── ui/ # Shadcn/ui primitive components
│ ├── PromptForm.tsx # Create prompt form with image upload & AI generation
│ ├── PromptCard.tsx # Grid card with preview, tags, and actions
│ ├── PromptDetail.tsx # Full view with image, inline editing, and AI summary
│ ├── SearchBar.tsx # Search input
│ ├── TagFilter.tsx # Multi-select tag filter
│ ├── SortOptions.tsx # Sort dropdown
│ ├── SettingsPage.tsx # AI settings & bulk operations
│ └── ToastContainer.tsx # Toast notifications
├── hooks/
│ ├── usePromptStore.ts # Main state management (CRUD, search, filters, AI)
│ ├── useLocalStorage.ts # Browser storage abstraction with flushSync
│ ├── useIndexedDB.ts # IndexedDB for large image storage (50MB+)
│ └── useToast.ts # Toast notification system
├── lib/
│ ├── utils.ts # Helpers (cn, clsx + tailwind-merge)
│ └── imageCompression.ts # Image compression utilities
├── types/
│ └── index.ts # TypeScript interfaces
├── styles/
│ └── globals.css # Tailwind directives + global reset
├── App.tsx # Root component
└── main.tsx # Entry point
api/
└── generateTitleAndTags.ts # Vercel serverless function (OpenRouter API)
- Mobile (< 640px): Full-screen sidebar drawer, single-column layout
- Tablet (640px - 1024px): Sidebar visible, 2-column prompt grid
- Desktop (> 1024px): Sidebar visible, 3-column prompt grid
- Touch targets ≥44px, no hover-only interactions
Metadata (LocalStorage):
- Key:
"prompt-store"
- Stores: titles, content, tags, timestamps, favorites, purposes
- Race-condition safe with
flushSync
Images (IndexedDB):
- Database:
"prompt-store-db"
, Object Store: "images"
- Automatic JPEG compression (1024x1024, 0.8 quality)
- 50MB+ capacity for large image collections
- Lazy-loaded on demand, cached in memory
{
"prompts": [
{
"id": "uuid",
"title": "Cyberpunk City",
"content": "A neon cyberpunk...",
"tags": ["cyberpunk", "neon"],
"createdAt": 1704067200000,
"updatedAt": 1704067200000,
"favorite": true,
"purpose": "Vibrant neon-lit city with flying cars",
"imageStored": true
}
],
"lastUpdated": 1704067200000
}
- Text Search: Case-insensitive search across title and content
- Tag Filtering: AND logic—prompt must match all selected tags
- Favorites Filter: Shows only favorited prompts
- Combined Filters: All filters work together simultaneously
- Sorting: By creation date, modification date, title (A-Z), or favorites
All AI features use Google Gemini 3B model via OpenRouter API:
- Title & Tags Generation: Analyzes prompt content during creation
- Summary Generation: 1-2 sentence punchy summaries for quick scanning
- Bulk Operations: Generate summaries for all prompts at once
- Caching: Results cached in localStorage automatically
- Create
.env.local
:
OPENROUTER_API_KEY=sk_your_key_here
- Run
npm install && npm run dev
- Access at
http://localhost:5173
- Deploy to Vercel:
git push
- Configure environment variable in Vercel dashboard:
- Settings → Environment Variables →
OPENROUTER_API_KEY
- Build command:
npm run build
- Output directory:
dist/
- React.memo for card components to prevent re-renders
- Memoized computed values for tags and filtered lists
- Lazy-loaded detail view components
- Tailwind CSS for optimal bundle size
- IndexedDB for image storage (bypasses localStorage quota)
- Chrome/Edge (latest)
- Firefox (latest)
- Safari (latest)
- Mobile browsers (iOS Safari, Chrome Mobile)
- LocalStorage: ~5-10MB per domain (varies by browser)
- Sufficient for 500+ prompts with metadata
- IndexedDB: 50MB+ per domain
- Store large reference images without quota concerns
MIT