Skip to content

realsudarshan/extracter

Repository files navigation

Extracter β€” AI-Powered Receipt Scanner

Extracter is a full-stack web application that uses AI to automatically scan and extract structured data from receipt images and PDFs. Upload a receipt, and within seconds the app surfaces the merchant name, transaction details, itemised line items, and a plain-English summary β€” all stored securely in the cloud and tied to your account.


Table of Contents


Features

  • Drag-and-drop upload β€” Drop a receipt image (JPEG, PNG, WebP) or PDF directly onto the upload zone.
  • AI data extraction β€” Google Gemini automatically parses merchant information, transaction dates, amounts, currency, and individual line items.
  • Receipt dashboard β€” Browse all your uploaded receipts with at-a-glance status indicators (Pending / Processed / Error).
  • Receipt detail view β€” Inspect every extracted field and read a human-friendly summary of the receipt.
  • Download & delete β€” Download the original file or permanently remove a receipt from storage and the database.
  • Authentication β€” Secure sign-up / sign-in via Clerk; each user can only access their own receipts.
  • Usage-based billing β€” Tiered pricing (Free, Basic, Team) enforced through Schematic feature flags.
  • Real-time updates β€” Convex pushes database changes to the UI instantly without polling.

Tech Stack

Layer Technology
Framework Next.js 15 (App Router)
UI React 19, Tailwind CSS v4, shadcn/ui
Database & Backend Convex
Authentication Clerk
AI Processing Google Gemini 2.0 Flash Lite via Inngest Agent Kit
Background Jobs Inngest
Feature Flags / Billing Schematic
Language TypeScript

Architecture Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        Browser                          β”‚
β”‚  Landing Page  β”‚  Dashboard  β”‚  Receipt Detail          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                       β”‚  HTTPS
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β”‚      Next.js Server     β”‚
          β”‚  (App Router / API)     β”‚
          β””β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚          β”‚
      β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”  β”Œβ”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
      β”‚  Convex   β”‚  β”‚     Inngest       β”‚
      β”‚ (DB + RPC)β”‚  β”‚ (background jobs) β”‚
      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚       Agent Network        β”‚
              β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
              β”‚  β”‚ Receipt Scanning   β”‚    β”‚
              β”‚  β”‚      Agent         β”‚    β”‚
              β”‚  β”‚  (Gemini + OCR)    β”‚    β”‚
              β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
              β”‚           β”‚ extracted JSON  β”‚
              β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
              β”‚  β”‚  Database Agent    β”‚    β”‚
              β”‚  β”‚ (saves to Convex)  β”‚    β”‚
              β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

How It Works

  1. Upload β€” The user drags a receipt file onto the upload zone. The file is uploaded directly to Convex Storage via a pre-signed URL, and a receipt record is inserted into the recipts table with status: "pending".

  2. Trigger β€” The upload action fires an Inngest event (extract-data-from-pdf-and-save-to-database) carrying the temporary file URL and the receipt's database ID.

  3. AI Agent Network β€” Inngest runs the agent network:

    • Receipt Scanning Agent downloads the file, converts it to base64, and sends it to Gemini with a structured extraction prompt. The model returns a JSON object containing merchant details, transaction info, line items, and totals.
    • Database Agent receives the extracted JSON and calls the Convex updateReceiptWithExtractData mutation to persist the data and flip the record's status to "proceed".
  4. Real-time update β€” Because Convex is reactive, the dashboard and detail pages update automatically when the record changes β€” no page reload required.

  5. Usage tracking β€” Each successful scan is tracked via Schematic so that plan limits can be enforced.


Data Model

The recipts table (Convex schema):

Field Type Description
userId string Clerk user subject (owner of the receipt)
fileName string Original file name
fileDisplayName string? Human-readable name assigned by the AI
fileId Id<"_storage"> Convex Storage reference
uploadedAt number Unix timestamp of upload
size number File size in bytes
mimeType string MIME type (e.g. image/jpeg, application/pdf)
status string "pending" β†’ "proceed" β†’ "error"
merchantName string? Extracted merchant / store name
merchantAddress string? Extracted merchant address
merchantContact string? Extracted phone / email
transactionDate string? Date of the transaction (YYYY-MM-DD)
transactionAmount string? Total amount paid
currency string? Currency code (e.g. USD)
reciptSummary string? Plain-English AI-generated summary
items array Line items β€” { name, quantity, unitPrice, totalPrice }

Convex Queries & Mutations

Name Type Description
generateUploadUrl mutation Returns a short-lived upload URL for Convex Storage
storeReciepts mutation Inserts a new receipt record
getRecipts query Returns all receipts for a given user (descending order)
getReceiptById query Returns a single receipt (auth-checked)
getReceiptDownloadUrl query Returns a temporary download URL for the stored file
updateReceiptsStatus mutation Updates only the status field (auth-checked)
deleteReciept mutation Deletes the file from Storage and the DB record (auth-checked)
updateReceiptWithExtractData mutation Persists all AI-extracted fields and sets status to "proceed"

Project Structure

extracter/
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ actions/                  # Next.js Server Actions
β”‚   β”‚   β”œβ”€β”€ getFileDownloadUrl.ts
β”‚   β”‚   └── getTemporaryAcessToken.ts
β”‚   β”œβ”€β”€ dashboard/                # Protected dashboard page
β”‚   β”œβ”€β”€ manage-plan/              # Billing / plan management page
β”‚   β”œβ”€β”€ receipt/[id]/             # Dynamic receipt detail page
β”‚   β”œβ”€β”€ server/                   # Inngest serve endpoint
β”‚   β”œβ”€β”€ layout.tsx                # Root layout (Clerk + Convex providers)
β”‚   └── page.tsx                  # Landing page
β”œβ”€β”€ components/
β”‚   β”œβ”€β”€ Dashboard/                # Dashboard-specific components
β”‚   β”œβ”€β”€ Landing/                  # Landing page sections (Hero, Feature, Pricing, Footer)
β”‚   β”œβ”€β”€ schematic/                # Schematic billing components
β”‚   β”œβ”€β”€ ui/                       # shadcn/ui primitive components
β”‚   β”œβ”€β”€ comp-145.tsx              # Feature card component
β”‚   β”œβ”€β”€ comp-548.tsx              # Custom dropzone component
β”‚   └── ConvexClientProvider.tsx  # Convex React provider wrapper
β”œβ”€β”€ convex/
β”‚   β”œβ”€β”€ schema.ts                 # Database schema
β”‚   β”œβ”€β”€ recipts.ts                # All queries & mutations
β”‚   └── auth.config.ts            # Clerk JWT configuration
β”œβ”€β”€ inngest/
β”‚   β”œβ”€β”€ agents/
β”‚   β”‚   β”œβ”€β”€ receiptScanningAgent.ts  # Gemini-powered OCR agent
β”‚   β”‚   └── databaseAgent.ts         # Convex persistence agent
β”‚   β”œβ”€β”€ agent.ts                  # Agent network + Inngest function
β”‚   β”œβ”€β”€ client.ts                 # Inngest client
β”‚   └── constants.ts              # Event name constants
β”œβ”€β”€ hooks/                        # Custom React hooks
β”œβ”€β”€ lib/                          # Shared utilities (Convex client, Schematic client)
β”œβ”€β”€ middleware.ts                 # Clerk auth middleware
β”œβ”€β”€ next.config.ts
└── package.json

Prerequisites


Getting Started

1. Clone the repository

git clone https://github.com/realsudarshan/extracter.git
cd extracter

2. Install dependencies

pnpm install

3. Set up Convex

npx convex dev --until-success

This will prompt you to log in and create a new Convex project. After it succeeds, a .env.local file is created with NEXT_PUBLIC_CONVEX_URL.

4. Configure Clerk

  1. Create an application in the Clerk dashboard.
  2. Add your Clerk publishable and secret keys to .env.local (see Environment Variables).
  3. In the Clerk dashboard, create a JWT template named convex following the Convex + Clerk guide.
  4. In convex/auth.config.ts, uncomment the Clerk provider and paste your Clerk Issuer URL.
  5. Add CLERK_JWT_ISSUER_DOMAIN to your Convex deployment environment variables via the Convex dashboard.

5. Configure Gemini (Google AI)

  1. Generate an API key at aistudio.google.com/apikey.
  2. Add it to .env.local as GOOGLE_AI_API_KEY.

6. Configure Inngest

  1. Sign up at app.inngest.com and create an app.
  2. Copy your Event Key and Signing Key.
  3. Add them to .env.local (see Environment Variables).

7. Configure Schematic (optional)

  1. Create an account at schematichq.com and set up your plans.
  2. Add your Schematic API key to .env.local.

8. Start the development servers

pnpm dev

This runs the Next.js frontend (next dev) and the Convex backend (convex dev) in parallel.

Open http://localhost:3000 in your browser.


Environment Variables

Create a .env.local file in the project root:

# Convex (auto-generated by `npx convex dev`)
NEXT_PUBLIC_CONVEX_URL=https://<your-deployment>.convex.cloud

# Clerk
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...

# Google AI (Gemini)
GOOGLE_AI_API_KEY=AIza...

# Inngest
INNGEST_EVENT_KEY=...
INNGEST_SIGNING_KEY=...

# Schematic (optional)
NEXT_PUBLIC_SCHEMATIC_PUBLISHABLE_KEY=...
SCHEMATIC_API_KEY=...

Available Scripts

Command Description
pnpm dev Start Next.js and Convex dev servers concurrently
pnpm build Build the Next.js app for production
pnpm start Start the production server
pnpm lint Run ESLint

Pricing Plans

Plan Price Users
Free Free forever 1
Basic $4 / month or $40 / year 2
Team $7 / month or $70 / year 5

Plan management is handled on the /manage-plan page and enforced via Schematic feature flags.


Deployment

Convex

The Convex backend is deployed automatically when you run npx convex deploy or link your repository in the Convex dashboard.

Next.js

Deploy the Next.js app to Vercel (recommended):

  1. Push the repository to GitHub.
  2. Import the project in the Vercel dashboard.
  3. Add all environment variables from .env.local to the Vercel project settings.
  4. Deploy.

Inngest

Register the Inngest serve endpoint with your production app URL in the Inngest dashboard. The endpoint is hosted at /api/inngest (configured in app/server/).

About

A modern ,AI full stack app that extract bill,receipts,invoice and provide summary and data in structured format. Implemented metered billing using stripe.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors