An intelligent bill-splitting application that uses AI to parse receipts and natural language to automatically calculate how much each person owes.
- πΈ Receipt Upload: Snap a photo of any receipt
- π€ AI-Powered Parsing: Automatically extracts items, prices, tax, and tip
- π¬ Natural Language Input: Describe the split in plain English (e.g., "Alice and Bob shared the apps")
- βοΈ Manual Editing: Fine-tune splits with an intuitive editor
- π° Smart Calculations: Automatically distributes tax and tip proportionally
- π± Venmo Integration: One-tap payment requests
- π Dark Mode: Full dark mode support
- βΏ Accessible: WCAG compliant with keyboard navigation and ARIA labels
- π± Responsive: Works seamlessly on mobile and desktop
- Framework: Next.js 16 with App Router
- UI: React 19 + Tailwind CSS 4
- Language: TypeScript
- AI: OpenRouter with Gemini 2.5 Flash
- Icons: Lucide React
- Node.js 20+ and npm
- An OpenRouter API key (Get one here)
git clone <your-repo-url>
cd ai-bill-splitternpm installCreate a .env.local file in the root directory:
OPENROUTER_API_KEY=your_api_key_hereTo get an OpenRouter API key:
- Visit openrouter.ai
- Sign up or log in
- Navigate to the API Keys section
- Create a new key and copy it to your
.env.localfile
npm run devOpen http://localhost:3000 in your browser.
- Upload a Receipt: Click or tap the upload area to select a receipt photo
- Describe the Split: Enter instructions like:
- "Alice and Bob split everything equally"
- "Alice had the burger, Bob had the salad, we shared the fries"
- "Add a 20% tip"
- Review & Edit: Fine-tune the AI's interpretation using the editor
- Request Payment: Tap the Venmo button to request payment from each person
Alice and Bob shared the appetizers.
Alice had the steak. Bob had the pasta.
We split the wine. Add 18% tip.
Me and Sarah split everything 60/40.
Add $5 tip.
Everyone splits equally. Add 20% tip.
app/
βββ actions.ts # Server actions (AI processing)
βββ types.ts # TypeScript type definitions
βββ lib/
β βββ constants.ts # App-wide constants
β βββ validation.ts # Input validation utilities
β βββ bill-utils.ts # Calculation logic
β βββ image-utils.ts # Image compression
β βββ env.ts # Environment validation
β βββ hooks.ts # Custom React hooks
βββ components/
βββ bill-splitter/
βββ index.tsx # Main component
βββ hooks/
β βββ useBillSplitter.ts # Main business logic hook
βββ views/
β βββ InputView.tsx # Upload & prompt screen
β βββ ProcessingView.tsx # Loading state
β βββ EditorView.tsx # Split editor screen
βββ ui/
βββ Header.tsx
βββ ParticipantsList.tsx
βββ LineItemsList.tsx
βββ ModifierSection.tsx
βββ ResultsPanel.tsx
βββ ItemModal.tsx
βββ MobileTabs.tsx
Items are split using a weight system:
- Weight of 1 = one portion
- Weight of 2 = two portions
- Fractional weights supported (0.5, 1.5, etc.)
Example: If Alice has weight 2 and Bob has weight 1 for an item:
- Alice pays 2/3 of the cost
- Bob pays 1/3 of the cost
Tax and tip are distributed proportionally based on each person's share of the subtotal. This ensures fair splitting even when people order different amounts.
Receipts are automatically compressed before upload to:
- Reduce API costs
- Speed up processing
- Stay within payload limits
Default: 1280px max width, 70% quality JPEG
npm run dev # Start development server
npm run build # Build for production
npm run start # Start production server
npm run lint # Run ESLintThis project includes:
- β TypeScript strict mode
- β ESLint with Next.js rules
- β Input validation and sanitization
- β Comprehensive error handling
- β Accessibility best practices
- β Performance optimizations (memoization, useCallback)
- Push your code to GitHub
- Import the project in Vercel
- Add your
OPENROUTER_API_KEYenvironment variable - Deploy!
Works with any Next.js-compatible hosting:
- Netlify
- Railway
- AWS Amplify
- Self-hosted with Node.js
Important: Ensure you set the OPENROUTER_API_KEY environment variable on your hosting platform.
Edit app/lib/constants.ts:
export const API_MODEL = "google/gemini-2.5-flash-preview-09-2025";See OpenRouter models for alternatives.
Edit app/lib/constants.ts:
export const IMAGE_MAX_WIDTH = 1280; // pixels
export const IMAGE_QUALITY = 0.7; // 0-1Edit app/lib/constants.ts:
export const APP_NAME = "FairShare";
export const APP_TAGLINE = "Snap a receipt, explain the split, done.";- Ensure
.env.localexists withOPENROUTER_API_KEY=your_key - Restart the development server after adding environment variables
- Check that the image is clear and readable
- Ensure you have sufficient OpenRouter credits
- Try a more detailed prompt
- Run
npm installto ensure all dependencies are installed - Check that you're using Node.js 20+
- Delete
.nextfolder and rebuild
Contributions are welcome! Areas for improvement:
- Add unit tests
- Support multiple currencies
- Add receipt history/persistence
- Support additional payment platforms (Cash App, Zelle)
- Export results as PDF
- Multi-language support
MIT License - feel free to use this project for personal or commercial purposes.
- Built with Next.js
- AI powered by OpenRouter
- Icons by Lucide
- Styled with Tailwind CSS