githubEdit

Receipt Extractor with Next JS

Build an AI-powered receipt extraction app with Next.js and JamAI Base

1. Introduction

This comprehensive tutorial will guide you through building a full-stack receipt extraction application using Next.js and the JamAI Base TypeScript SDK. The application uses AI to automatically extract key information from receipt images.

What We'll Build

An AI-powered web application that allows users to:

  1. Upload receipt images through drag-and-drop or file selection

  2. Extract information automatically using JamAI Base Action Tables:

    • Shop/Store Name

    • Category (Groceries, Restaurant, Retail, etc.)

    • Total Amount

  3. View processing history with pagination

  4. Display results in a modern, responsive UI

Key Features

  • Modern Next.js 16 with App Router and React Server Components

  • TypeScript for type safety

  • Tailwind CSS 4 for styling with dark mode support

  • SWR for efficient data fetching and caching

  • Real-time Processing with loading states

  • Responsive Design for mobile and desktop

  • Image Upload with validation and preview

Prerequisites

Before starting, you'll need:

  • Node.js 16.x or higher installed

  • Basic knowledge of React and TypeScript

  • Project ID and Personal Access Token (PAT) from JamAI Base

  • A code editor (VS Code recommended)

2. Project Setup

2.1 Create Next.js Project

First, create a new Next.js project with TypeScript:

When prompted, select:

  • TypeScript: Yes

  • ESLint: Yes

  • Tailwind CSS: Yes

  • src/ directory: Yes

  • App Router: Yes

  • Import alias: Yes (@/*)

2.2 Install Dependencies

Install the required packages:

Dependencies:

  • jamaibase - JamAI Base TypeScript SDK for AI operations

  • swr - React hooks for data fetching with caching

2.3 Project Structure

Create the following folder structure:

3. Getting Your Credentials

3.1 Get Your Personal Access Token (PAT)

  1. Click on your username in the top right

  2. Select Account Settings

  3. Navigate to Personal Access Token section

  4. Click Create Personal Access Token

  5. Copy and save your token securely

3.2 Get Your Project ID

  1. In the JamAI Base dashboard, navigate to your project

  2. Look at the browser URL: https://cloud.jamaibase.com/project/{PROJECT_ID}

  3. Copy the Project ID from the URL

3.3 Configure Environment Variables

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

Also create a .env.example file for reference:

circle-info

Important: Never commit .env.local to version control. Add it to your .gitignore file.

4. Core Configuration

4.1 Create Type Definitions

Create src/lib/types.ts:

4.2 Initialize JamAI Client

Create src/lib/jamai.ts:

Key Points:

  • Uses singleton pattern for the JamAI client

  • Validates environment variables on initialization

  • Automatically creates the Action Table if it doesn't exist

  • Configures three LLM output columns with specific prompts

  • Uses Qwen3-VL-30B (embedded LLM) for cost-effective, fast processing

  • Prompts include table context and use ${Image} variable reference

5. Building the API Routes

5.1 File Upload Route

Create src/app/api/jamai/upload/route.ts:

What this does:

  • Accepts multipart form data with an image file

  • Validates file type (images only) and size (10MB max)

  • Uploads the file to JamAI Base storage

  • Returns a URI for the uploaded file

5.2 Receipt Processing Route

Create src/app/api/jamai/process/route.ts:

What this does:

  • Receives the uploaded image URI

  • Ensures the Action Table exists

  • Adds a row to the table with the image

  • JamAI Base automatically processes the image through LLMs

  • Extracts the AI-generated outputs (shop name, category, total)

  • Returns the structured receipt data

5.3 History Retrieval Route

Create src/app/api/jamai/history/route.ts:

What this does:

  • Accepts pagination parameters (offset, limit)

  • Fetches historical receipts from the Action Table

  • Unwraps JamAI's nested data structure

  • Returns paginated results

  • Handles the case when the table doesn't exist yet

6. Building the UI Components

6.1 Loading Spinner Component

Create src/components/LoadingSpinner.tsx:

6.2 Receipt Upload Component

Create src/components/ReceiptUpload.tsx:

Key Features:

  • Drag-and-drop file upload

  • Click to select file

  • Image preview before processing

  • Client-side validation

  • Visual loading states with progress messages

  • Error handling

6.3 Receipt Results Component

Create src/components/ReceiptResults.tsx:

6.4 Receipt History Component

Create src/components/ReceiptHistory.tsx:

Key Features:

  • Uses SWR for data fetching with caching

  • Auto-refreshes when new receipts are added

  • Responsive design (table on desktop, cards on mobile)

  • Pagination support

  • Empty state handling

6.5 Custom Hook for Data Fetching

Create src/hooks/useReceipts.ts:

7. Building the Main Page

7.1 Update Layout

Update src/app/layout.tsx:

7.2 Create Main Page

Update src/app/page.tsx:

8. Running the Application

8.1 Start Development Server

The application will start at http://localhost:3000arrow-up-right

8.2 Test the Application

  1. Upload a Receipt

    • Drag and drop a receipt image, or click to select a file

    • Supported formats: JPEG, PNG, WebP, GIF (max 10MB)

  2. Process Receipt

    • Click "Process Receipt" button

    • Watch the progress indicators:

      • "Uploading image..."

      • "Extracting receipt data..."

  3. View Results

    • See extracted information:

      • Shop Name

      • Category

      • Total Amount

  4. Check History

    • Scroll down to see all processed receipts

    • Navigate through pages if you have more than 50 receipts

8.3 First Run

On the first API call, the application will automatically:

  1. Connect to JamAI Base using your credentials

  2. Create the "receipt" Action Table if it doesn't exist

  3. Configure the LLM columns with extraction prompts

Check your terminal logs to see:

9. How It Works

9.1 Architecture Overview

9.2 Data Flow

  1. Upload Phase

    • User selects/drops an image file

    • Client validates file type and size

    • FormData sent to /api/jamai/upload

    • Image stored in JamAI Base, returns URI

  2. Processing Phase

    • Client sends image URI to /api/jamai/process

    • API ensures Action Table exists

    • Row added to table with image URI

    • JamAI Base triggers LLM processing:

      • Qwen3-VL-30B (embedded LLM) analyzes the image

      • Three separate prompts extract different fields

      • Results stored in table columns

  3. Display Phase

    • API returns structured receipt data

    • Client displays results

    • History automatically refreshes

9.3 JamAI Base Action Table Structure

The "receipt" table has the following schema:

Column Name
Type
Description

Image

Input (image)

Receipt image file

Shop Name

LLM Output (str)

Extracted store name

Category

LLM Output (str)

Receipt category

Total

LLM Output (str)

Total amount with currency

Each LLM Output column has:

  • Model: ellm/Qwen/Qwen3-VL-30B-A3B-Instruct (embedded vision LLM)

  • Temperature: 0.1 (for consistency)

  • Custom Prompts: Specialized for each field with table context and variable references

10. Customization

10.1 Modify Extraction Prompts

To change what information is extracted, edit the prompts in src/lib/jamai.ts:

10.2 Add New Fields

To extract additional information:

  1. Add the column definition in ensureTableExists():

  1. Update the Receipt interface in src/lib/types.ts:

  1. Update extraction in the process route

  2. Update UI components to display the new field

10.3 Change LLM Model

You can use different models for different accuracy and cost trade-offs:

Note: When using different models, remember to include proper context in prompts. For vision models, use the ${Image} variable reference as shown in the examples.

10.4 Styling Customization

The app uses Tailwind CSS. Customize colors, spacing, and styles:

11. Deployment

11.1 Deploy to Vercel

  1. Push to GitHub

  2. Deploy on Vercel

    • Click "Import Project"

    • Select your GitHub repository

    • Add environment variables:

      • JAMAI_API_KEY

      • JAMAI_PROJECT_ID

    • Click "Deploy"

  3. Verify Deployment

    • Visit your deployment URL

    • Test receipt upload and processing

11.2 Environment Variables in Production

circle-exclamation

12. Troubleshooting

Common Issues

Issue: "Missing JamAI credentials" error

Solution:

  • Verify .env.local exists in project root

  • Check that variables are named correctly:

    • JAMAI_API_KEY (not JAMAI_TOKEN)

    • JAMAI_PROJECT_ID (not PROJECT_ID)

  • Restart development server after adding env variables


Issue: Upload fails with "File too large"

Solution:

  • Ensure image is under 10MB

  • Compress image before uploading

  • Or increase MAX_FILE_SIZE in src/app/api/jamai/upload/route.ts


Issue: Processing takes too long

Solution:

  • This is normal for first request (table creation)

  • Subsequent requests are faster

  • Consider using concurrent: true for background processing


Issue: Extraction accuracy is poor

Solution:

  • Use higher quality images (clear, well-lit receipts)

  • Try different vision models (e.g., openai/gpt-4o for better accuracy)

  • Refine prompts to be more specific

  • Ensure prompts include proper table context and variable references like ${Image}

  • Adjust temperature slightly (lower for consistency, higher for variety)


Issue: History not refreshing

Solution:

  • Check browser console for errors

  • Verify refreshTrigger is incrementing

  • Clear browser cache

  • Check API route returns valid data

13. Best Practices

Security

  1. Protect API Keys

    • Never commit .env.local

    • Use environment variables in production

    • Rotate API keys periodically

  2. Validate Input

    • Always validate file types and sizes

    • Sanitize user inputs

    • Implement rate limiting for production

  3. Error Handling

    • Never expose sensitive error details to users

    • Log errors server-side

    • Provide user-friendly error messages

Performance

  1. Optimize Images

    • Compress images before upload

    • Consider image optimization libraries

  2. Caching

    • SWR handles client-side caching

    • Consider server-side caching for frequently accessed data

  3. Concurrent Processing

    • For bulk uploads, use concurrent: true in addRow()

    • Implement queue system for large batches

Code Quality

  1. TypeScript

    • Define interfaces for all data structures

    • Avoid any types

    • Use strict mode

  2. Components

    • Keep components focused and reusable

    • Extract common logic into hooks

    • Use proper TypeScript types for props

  3. Testing

    • Add unit tests for utility functions

    • Test API routes

    • Implement E2E tests for critical flows

14. Next Steps

Enhancements to Try

  1. Multi-file Upload

    • Process multiple receipts at once

    • Show progress for batch processing

  2. Export Functionality

    • Export history to CSV

    • Generate expense reports

    • Integration with accounting software

  3. Advanced Features

    • Receipt search and filtering

    • Date range selection

    • Analytics dashboard

    • Monthly/yearly summaries

  4. Mobile App

    • Build React Native app

    • Use device camera for capture

    • Offline support with sync

  5. Authentication

    • Add user accounts

    • Personal receipt history

    • Multi-user support

15. Resources

16. Support

If you encounter issues or have questions:

  1. Review this tutorial's troubleshooting section

  2. Contact JamAI Base support

Conclusion

You've successfully built a full-stack receipt extraction application using:

  • Next.js 16 with App Router

  • JamAI Base for AI-powered data extraction

  • TypeScript for type safety

  • Tailwind CSS for modern UI

  • SWR for efficient data fetching

The application demonstrates how easy it is to integrate AI capabilities into web applications using JamAI Base Action Tables. You can now extend this foundation to build more complex document processing applications.

Happy building!

Last updated

Was this helpful?