Skip to content

Repository files navigation

split

split turns a receipt photo into an exact, participant-by-participant bill split. An authenticated organizer reviews the extraction, assigns individual and shared items, publishes private guest links, resolves disputes, and tracks simulated payments. No real payment rail or banking system is connected.

The repository includes two complementary experiences:

  • A deterministic, public North Market walkthrough that works without external services.
  • A live organizer workflow backed by Auth0, MongoDB Atlas, Gemini, and Backboard.

What is implemented

  • Mobile camera capture and device upload for JPEG, PNG, WebP, HEIC, and HEIF receipts up to 10 MB.
  • Gemini vision extraction into a strict server-validated receipt schema.
  • Editable merchant, date, category, currency, receipt rows, signed discounts/fees/adjustments, tax, tip, and total.
  • One-person, equal, custom-weight/quantity, and whole-group assignments.
  • Server-authoritative integer-cent calculations with deterministic largest-remainder allocation and visible rounding traces.
  • Auth0 organizer sessions and owner-scoped APIs.
  • Opaque, hashed, expiring, revocable guest tokens exchanged for HttpOnly participant sessions.
  • Participant-scoped itemization, payment explanation, dispute submission, and simulated payment transitions.
  • Transactional dispute reassignment, recalculation, payment-request supersession, and audit history.
  • MongoDB collections for users, bills, participants, receipt items, assignments, payment requests/events, disputes, audit logs, and rate limits; receipt images use GridFS.
  • Four Backboard advisory workflows: Receipt Review, Split Verification, Payment Explanation, and Dispute Resolution.
  • Deterministic fallback behavior that is explicitly labeled and never invents values for an unknown receipt.

Stack

  • Next.js 16, React 19, TypeScript, and Tailwind CSS 4
  • MongoDB Atlas and the MongoDB Node driver
  • Auth0 Next.js SDK
  • Google Gen AI SDK using gemini-3.5-flash by default
  • Backboard HTTPS API through a server-only adapter
  • Vitest and Playwright

All secrets are read only by server modules. Do not prefix any secret with NEXT_PUBLIC_.

Prerequisites

  • Node.js 20.19+, 22.13+, or 24+ (odd-numbered Node releases are intentionally excluded)
  • npm
  • A MongoDB Atlas cluster and database user
  • An Auth0 Regular Web Application
  • Gemini and Backboard API keys for the live AI path

Local setup

  1. Install dependencies:

    npm install
  2. Copy the environment template and fill in the values locally. The repository ignores .env files.

    cp .env.example .env
  3. Configure MongoDB Atlas:

    • Create a database user with read/write access to the splitai database.
    • Add the public IP of the network running split under Network Access. If Wi-Fi changes, Atlas may require the new IP.
    • Use the Atlas SRV connection string as MONGODB_URI.
    • Atlas must support transactions; a normal Atlas replica-set cluster does.
  4. Configure Auth0:

    • Application type: Regular Web Application.
    • Allowed Callback URL: http://localhost:3000/auth/callback
    • Allowed Logout URL: http://localhost:3000
    • Allowed Web Origin: http://localhost:3000
    • Set APP_BASE_URL=http://localhost:3000 and AUTH0_DOMAIN=<tenant>.auth0.com.
    • Generate AUTH0_SECRET with openssl rand -hex 32.

    AUTH0_BASE_URL and AUTH0_ISSUER_BASE_URL are accepted as legacy aliases for the current APP_BASE_URL and AUTH0_DOMAIN names.

  5. Start the app:

    npm run dev
  6. Open http://localhost:3000.

Environment variables

Variable Required for live flow Purpose
MONGODB_URI Yes Atlas SRV connection string
MONGODB_DB_NAME No Database name; defaults to splitai
AUTH0_SECRET Yes Auth0 session encryption secret
APP_BASE_URL Yes Current SDK application URL
AUTH0_DOMAIN Yes Auth0 tenant domain, without a path
AUTH0_CLIENT_ID Yes Auth0 application client ID
AUTH0_CLIENT_SECRET Yes Auth0 application client secret
AUTH0_BASE_URL Alias Legacy alias for APP_BASE_URL
AUTH0_ISSUER_BASE_URL Alias Legacy issuer URL alias for AUTH0_DOMAIN
GEMINI_API_KEY Yes Server-side Gemini receipt extraction
GEMINI_MODEL No Defaults to gemini-3.5-flash
BACKBOARD_API_KEY Yes Server-side workflow advisories
BACKBOARD_BASE_URL No Defaults to https://app.backboard.io/api
DEMO_MODE No Allows the seed route in production only when explicitly true
DEMO_FALLBACK_ENABLED No Allows the exact known fixture fallback; defaults to true
RECEIPT_MAX_BYTES No Upload limit; defaults to 10 MiB

GET /api/health reports only whether integrations are configured; it never returns secret values.

Demo walkthrough

Prepared public walkthrough

Choose Explore the demo on the landing page. The prepared North Market flow demonstrates:

  1. Nine editable grocery receipt items for Alex, Priya, Jordan, and Sam.
  2. Individual, shared, quantity-based, and everyone assignments.
  3. Exact CAD totals of $37.48, $16.68, $9.59, and $25.38, totaling $89.13.
  4. Participant-only payment pages with Interac e-Transfer-style instructions.
  5. A resolved salsa dispute, two simulated paid participants, one pending participant, and one unopened link.

This is clearly marked sample data and never writes payment activity or moves money.

Live organizer workflow

  1. Sign in through Auth0 and choose New split.
  2. Upload a receipt or use the mobile camera input.
  3. Review Gemini fields, confidence, reconciliation, and the Receipt Review advisory.
  4. Correct any uncertain rows and add participants.
  5. Assign every item, then run the server calculation and Split Verification advisory.
  6. Publish the bill and save the one-time private guest URLs.
  7. Open a guest URL, review the participant-scoped calculation, and simulate pending/paid/failed status.
  8. Submit a dispute for an eligible whole item, approve a reassignment as organizer, and save the replacement links.
  9. Track link views, disputes, simulated payments, and outstanding totals on the live status screen.

In development, POST /api/demo/seed can create the complete persistent demo against the configured Atlas database. Its response contains temporary plaintext guest URLs, so treat the response as sensitive and do not paste it into logs or tickets. Reusing the seed rotates those URLs.

Commands and verification

Install the Playwright browser once before the end-to-end suite:

npx playwright install chromium
npm run lint
npm run typecheck
npm test
npm run build
npm run test:e2e

The unit suite covers, among other cases:

  • residual-cent allocation across four participants;
  • signed discounts and double-entry manual adjustments;
  • forged client totals and reconciliation mismatches;
  • missing, duplicate, or stale assignments;
  • invalid payment-state transitions and dispute blocking;
  • concurrent/stale dispute reassignment policy;
  • client API error, upload, guest-session, and idempotency contracts;
  • best-effort removal of ephemeral Backboard threads.

Architecture and important files

Area Location
App Router pages and API routes src/app
Live and deterministic UI screens src/components
Exact allocation and payment state machines src/domain
Server orchestration services src/services
MongoDB repositories and document contracts src/repositories
Gemini, image, fallback, and Backboard adapters src/adapters
Auth0, MongoDB, request, transaction, and error utilities src/lib/server
Typed browser client src/lib/client
API/domain validation src/schemas
Canonical demo fixture public/demo and src/data/demo

The server is the source of truth. Clients submit revisions, assignments, and requested transitions, not final totals. Financial mutations use optimistic revision checks, MongoDB transactions where multiple records change, and append-only audit entries.

Security and privacy boundaries

  • Payments are simulation-only. split never requests passwords, card numbers, account numbers, or banking credentials.
  • Guest tokens use 32 random bytes; only token hashes are stored. Exchange produces a scoped HttpOnly, Secure in production, same-site session cookie.
  • Guest responses are allow-listed to one participant's merchant/date, assigned rows, calculation, instructions, disputes, and status.
  • Guest mutations are same-origin checked, rate-limited, lifecycle validated, and idempotent.
  • Receipt bytes are type-sniffed, pixel-limited, normalized server-side, stored privately, and served only to the bill owner.
  • Backboard receives minimized workflow context with sensitive keys removed. Provider-created ephemeral threads are deleted best-effort after each advisory.
  • Security headers deny framing, MIME sniffing, and unrelated browser permissions.

Known limitations

  • There is no real Interac, bank, card, email, or SMS integration. Organizers copy and distribute guest links themselves.
  • Automated financial dispute acceptance is intentionally limited to one standard item assigned wholly to the disputing participant. Shared-item or overall-total questions require the organizer to correct the underlying receipt/assignments separately.
  • Plaintext guest URLs are shown only on publish, dispute-recalculation, or explicit rotation responses; the database stores hashes only.
  • The exact known demo receipt can use a deterministic extraction fallback. An unfamiliar failed extraction opens a blank manual-review path rather than invented receipt data.
  • Backboard suggestions are advisory and may fall back to explicitly labeled deterministic local guidance. They never change totals or authorize a payment.
  • The current build does not deliver notifications or automatically close a fully settled bill.

Sponsor integrations and data references

  • MongoDB Atlas: persistent application state, transactions, indexes, rate limits, and private GridFS receipt storage.
  • Auth0: organizer identity and encrypted server sessions.
  • Gemini: vision receipt extraction with JSON-schema-constrained output and server-side semantic validation.
  • Backboard: four limited, advisory workflow agents with deterministic fallbacks.
  • Interac-style demo: familiar Canadian transfer instructions with no real payment connection.
  • Receipt references: local data/groceries images plus schema/OCR variation research from Goodspot EU/NA Receipts and docjay131 Receipts OCR. The full datasets are not bundled or downloaded.

For production deployment, use production callback URLs, a narrowly scoped Atlas access list, managed secrets, HTTPS, monitoring, backups, and a deliberate retention/deletion policy for receipts and audit data.

About

A browser-based secure way to split receipt items among people

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages