An infinite canvas image editor with AI transformations using fal.ai. Built with Next.js, React Konva, and tRPC.
- Infinite canvas with pan/zoom
- Drag & drop image upload
- AI style transfer via Flux Kontext LoRA
- Background removal and object isolation
- Real-time streaming of AI results
- Multi-selection and image manipulation
- Auto-save to IndexedDB
- Undo/redo support
React Konva for 2D canvas rendering with viewport culling for performance.
The app integrates with fal.ai's API in several clever ways:
To bypass Vercel's 4.5MB request body limit, we implement a proxy pattern:
// Client uploads through proxy
const uploadResult = await falClient.storage.upload(blob);
// Proxy endpoint at /api/fal handles the request
export const POST = route.POST; // fal.ai's Next.js proxy
This allows users to upload large images that would otherwise be rejected by Vercel's edge runtime.
The application implements a three-tier rate limiting system for users without API keys:
const limiter = {
perMinute: createRateLimiter(5, "60 s"), // 10 requests per minute
perHour: createRateLimiter(15, "60 m"), // 30 requests per hour
perDay: createRateLimiter(50, "24 h"), // 100 requests per day
};
Users can bypass rate limits by adding their own fal.ai API key, which switches them to their own quota.
Image generation uses fal.ai's streaming API to provide live updates:
// Server-side streaming with tRPC
const stream = await falClient.stream("fal-ai/flux-kontext-lora", {
input: { image_url, prompt, loras },
});
for await (const event of stream) {
yield tracked(eventId, { type: "progress", data: event });
}
The client receives these updates via a tRPC subscription and updates the canvas in real-time, creating a smooth user experience where images gradually appear as they're being generated.
The application uses a combination of React state and IndexedDB for persistence:
- Canvas State: Images, positions, and transformations stored in React state
- History: Undo/redo stack maintained in memory
- Persistence: Auto-saves to IndexedDB with debouncing
- Image Storage: Original image data stored separately in IndexedDB to handle large files
Built with tRPC for type-safe API calls:
removeBackground
: Uses fal.ai's Bria background removal modelisolateObject
: Leverages EVF-SAM for semantic object segmentationgenerateTextToImage
: Text-to-image generation with FluxgenerateImageStream
: Streaming image-to-image transformations
Uses fal.ai's Flux Kontext LoRA model to apply artistic styles:
- User selects an image and a style (or provides custom LoRA URL)
- Image is uploaded to fal.ai storage via proxy
- Streaming transformation begins, updating canvas in real-time
- Final high-quality result replaces the preview
Powered by EVF-SAM (Enhanced Visual Foundation Segment Anything Model):
- User describes object in natural language (e.g., "the red car")
- EVF-SAM generates a segmentation mask
- Server applies mask to original image using Sharp
- Isolated object with transparent background returned to canvas
Uses Bria's specialized background removal model:
- Automatic subject detection
- Clean edge preservation
- Transparent PNG output
- Viewport Culling: Only renders visible images
- Streaming Images: Custom hook prevents flickering during updates
- Debounced Saving: Reduces IndexedDB writes
- Image Resizing: Automatically resizes large images before upload
- Lazy Loading: Default images load asynchronously
-
Clone the repository
-
Install dependencies:
npm install
-
Add your fal.ai API key to
.env.local
:FAL_KEY=your_fal_api_key_here NEXT_PUBLIC_APP_URL=http://localhost:3000 # Optional KV_REST_API_URL= KV_REST_API_TOKEN=
-
Run development server:
npm run dev
The project uses Husky and lint-staged for automated code formatting and linting before commits.
Pre-commit hooks are automatically installed when you run npm install
(via the prepare
script).
The hooks will:
- Run Prettier formatting on staged files
- Run ESLint with auto-fix on staged files
- Only process files that are staged for commit (more efficient than processing all files)
If you need to manually run the pre-commit checks:
npx lint-staged
- Next.js 15: React framework with App Router
- React Konva: Canvas rendering engine
- tRPC: Type-safe API layer
- fal.ai SDK: AI model integration
- Tailwind CSS: Styling
- IndexedDB: Client-side storage
- Sharp: Server-side image processing
The app is optimized for Vercel deployment:
- Uses edge-compatible APIs
- Implements request proxying for large files
- Automatic image optimization disabled for canvas compatibility
- Bot protection via BotId integration
MIT