Skip to content
Β 
Β 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

60 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

spl1t

spl1t is an open source expense-tracking app based on Spliit. This fork deploys on Cloudflare Workers (via OpenNext) with Cloudflare KV as the database β€” not Vercel Postgres / Prisma.

Live: https://spl1t.pages.dev

spl1t.pages.dev is a Pages project that reverse-proxies Worker spl1t. OpenNext still deploys the Worker. App NEXT_PUBLIC_BASE_URL remains https://spl1t.USER.workers.dev until a Worker rebuild.

Features

Legend: 🟒 from original Spliit Β· πŸ”΄ new in this Cloudflare KV fork

  • 🟒 Create a group and share it with friends
  • 🟒 Create expenses with description
  • 🟒 Display group balances
  • 🟒 Create reimbursement expenses
  • 🟒 Progressive Web App
  • 🟒 Select all/no participant for expenses
  • 🟒 Split expenses unevenly
  • 🟒 Mark a group as favorite
  • 🟒 Tell the application who you are when opening a group
  • 🟒 Assign a category to expenses
  • 🟒 Search for expenses in a group
  • 🟒 Export a group to JSON or CSV
  • πŸ”΄ Import a group from a Spliit JSON export (creates a new group with remapped IDs)
  • πŸ”΄ Import a group from a Tricount GDPR CSV export (participants + expenses)
  • πŸ”΄ Notes + activity history + document links in JSON export/import (exportVersion: 3)
  • πŸ”΄ Copy an existing expense into a new draft
  • πŸ”΄ Math expressions in the amount field
  • πŸ”΄ Even-split cent remainder (no missing cents)
  • πŸ”΄ Group default split mode
  • πŸ”΄ Optional group PIN
  • πŸ”΄ Share group via QR code
  • πŸ”΄ Soft-delete / restore groups (30-day grace) + 24-month inactivity expiry
  • πŸ”΄ Security headers, CSV formula escape, Zod input caps, expense date bounds
  • πŸ”΄ Error boundaries + Drawer accessibility titles
  • πŸ”΄ Paste-friendly amount parsing (US/EU grouped currency)
  • πŸ”΄ Keyboard navigation restored in category/currency selectors
  • πŸ”΄ Mobile group tab icons
  • πŸ”΄ Stats: monthly spending (stacked category chart + breakdown) and balance timeline
  • πŸ”΄ Optional calendar-month expense grouping
  • πŸ”΄ Drag-reorder / Sort A–Z participants
  • πŸ”΄ Multiple payers per expense (legacy single paidById migrated on read)
  • πŸ”΄ Extra currencies: ARS, TRY, COP, JOD, MKD, MOP, MYR, VND
  • ❌ Upload and attach images to expenses (removed β€” see below)
  • ❌ Create expense by scanning a receipt (removed β€” see below)

Stack

Data model notes

  • Each group is stored as a single KV value under group:{groupId}.
  • Categories are seeded under the categories key.
  • Concurrent edits to the same group use last-write-wins (no Durable Objects / transactions).
  • Friend-sized groups fit this model; very large groups may hit KV value size limits.
  • Groups track lastActivityAt on expense create/update/delete and group settings updates. After 24 months without activity, cleanup soft-deletes them; soft-deleted groups can be restored for 30 days, then are hard-deleted. Call GET/POST /api/cron/cleanup-groups with Authorization: Bearer $CRON_SECRET (set CRON_SECRET in Worker env).

Extra UX (this fork)

Ideas below track community demand from Spliit Cloud’s roadmap, upstream Spliit issues/PRs, and hardening patterns from anon-spliit (reimplemented for KV β€” not a code port of their E2EE/auth stack).

Feature Notes Prior art
Copy expense From the expense list or edit header icon (opens create prefilled). Upstream #527; shipped in Spliit Cloud
Amount math Expressions in the amount field (10+5.50, 5*8, …) on blur/save. Upstream #184; shipped in Spliit Cloud
Default split mode Stored on the group (device localStorage can still override). Upstream #366; shipped in Spliit Cloud
Even-split cents Integer remainder allocation so balances don’t drop a cent. Upstream #374 / #427; tracked by Spliit Cloud
Share QR QR in the share popover. Upstream #500; on Spliit Cloud roadmap
Optional group PIN 4–8 digits; unlocks per browser session; hashed on the server, not returned to clients. Upstream #373; on Spliit Cloud roadmap
Notes + history + document links in JSON Export/import round-trips expense notes, group information, activity history, and document URLs (exportVersion: 3). Follow-up to upstream #546; expense notes also in #165
Soft-delete + inactivity expiry Manual soft-delete with 30-day restore; auto soft-delete after 24 months without activity; cron hard-deletes after grace. Inspired by anon-spliit deletion/auto-delete work and upstream #420
Paste amount parsing Normalizes pasted US/EU currency amounts in number fields. Upstream #531
Selector keyboard nav Category/currency pickers use cmdk CommandList. Upstream #491
Mobile tab icons Icon-only tabs on small screens; labels from sm. Upstream #539
Monthly spending + balance timeline CSS stacked category charts, category breakdown, and balance timeline on Stats. Upstream #532 / #555
Calendar month grouping Optional group setting for roommate-style monthly lists. Upstream #530
Multiple payers Split who paid an expense across several participants; balances/export/import aware. Legacy paidById migrates on read. Upstream #396
Reorder participants Drag-and-drop + Sort A–Z; order persisted in KV. Upstream #416
Tricount import GDPR CSV export via the same Import control as Spliit JSON. Upstream #526
Export / input hardening CSV formula escape, Zod max caps, expense date bounds, security headers, error boundaries. Patterns reviewed from anon-spliit (adapted for Workers/KV)

Stats (this fork)

On each group’s Stats tab:

  • Monthly spending β€” stacked category chart for calendar months, with a category breakdown and legend controls.
  • Balance timeline β€” cumulative balances over time for participants (engineering fixes on this fork for share math / timeline consistency).

Inspired by upstream #532 / #555; reimplemented for denormalized KV documents.

Group import JSON / Tricount (this fork)

On the Groups page, use Import JSON to upload:

  1. A Spliit JSON export (this fork or upstream Spliit), or
  2. A Tricount personal-data / GDPR CSV export (detected automatically).

Shared behavior:

  • Always creates a new group (does not overwrite an existing one).
  • Regenerates group, participant, and expense IDs so imports never collide with live data.
  • Does not import a group PIN (PIN must be set again after import).

Spliit JSON

  • Restores participants, expenses (including multiple payers when present), split modes, amounts, dates, notes, group information, and activity history (when present in the file).
  • Categories: match by id when present; otherwise by name / grouping against the seeded list (many exports omit id).
  • Newer exports include exportVersion: 3, expense ids (needed to re-link history), and expense document links (url / dimensions β€” not file bytes).
  • Document URLs round-trip for migration between Spliit forks; binaries are not embedded, and links may 404 if the original storage expires. Recurring-expense links are still not restored.

Tricount CSV

  • Imports participants and expenses (amounts by share / impacted amounts).
  • Uses the CSV default currency (Frankfurter .dev for missing cross-rates).
  • Notes and activity history are Spliit-only; Tricount imports leave them empty.
  • Prior art: upstream #526.

Removed / disabled upstream features (S3 & OpenAI)

Upstream Spliit optional features that depended on AWS S3 and OpenAI are not available in this Cloudflare KV fork:

Feature Upstream dependency Status here
Expense document / image uploads S3 (or compatible object storage) Removed from the critical path; UI/API stubs keep flags off. KV is not used for binaries.
Create expense from receipt scan OpenAI + storage Disabled; no OpenAI client or API keys.
Category extract from text/image OpenAI Disabled; same as above.

What changed vs upstream:

  • Prisma, Postgres, and Vercel-oriented DB wiring were replaced with the KV group-document API.
  • S3/OpenAI packages and env vars were dropped; keep NEXT_PUBLIC_ENABLE_EXPENSE_DOCUMENTS, NEXT_PUBLIC_ENABLE_RECEIPT_EXTRACT, and NEXT_PUBLIC_ENABLE_CATEGORY_EXTRACT unset or false (see .env.example).
  • Re-enabling uploads later would mean adding something like R2 (not stuffing files into KV). Receipt/category AI would need a Workers-compatible provider and explicit product work.

Run locally

  1. Clone the repository: git clone https://github.com/t0ma5/spl1t.git
  2. Copy .env.example to .env and .dev.vars as needed
  3. Create a KV namespace and put its id in wrangler.jsonc:
npx wrangler kv namespace create spl1t-db
npx wrangler kv namespace create spl1t-db --preview
  1. Run npm install (uses package-lock.json)
  2. Set NEXT_PUBLIC_BASE_URL (production default in wrangler.jsonc vars is https://spl1t.pages.dev)
  3. Run npm run dev for Next.js local development (bindings via OpenNext), or npm run preview to build and run in the Workers runtime

Note: Local OpenNext/Wrangler needs workerd, which does not support Windows ARM64. On those machines, develop against the remote Worker or deploy from an x64/Linux host.

Deploy to Cloudflare

Deploy directly to Cloudflare (no GitHub Actions).

Requires Node.js 22+ and a host where Wrangler/workerd runs (Linux / macOS / Windows x64 β€” not Windows ARM64).

npm run deploy

This runs opennextjs-cloudflare build then deploys Worker spl1t. Ensure:

  • DB KV binding in wrangler.jsonc points at your namespace (existing id kept so group data survives).
  • vars.NEXT_PUBLIC_BASE_URL matches the URL users open (https://spl1t.pages.dev).

Ops notes

  • Pushing code to GitHub does not update the live Worker until you run npm run deploy (or equivalent OpenNext/Wrangler upload) against Cloudflare.
  • Prefer git / GitHub CLI over the GitHub web β€œupload files” UI β€” uploads often drop directories.
  • Set Worker secret CRON_SECRET and schedule a daily call to /api/cron/cleanup-groups for inactivity cleanup.

Health check

  • GET /api/health/readiness or GET /api/health β€” app ready, including KV connectivity
  • GET /api/health/liveness β€” process alive only

Credits & provenance

  • Original Spliit β€” idea, UI, and core expense-splitting product by Sebastien Castiel and contributors: spliit-app/spliit Β· spliit.app.
  • Spliit Cloud (antonio-ivanovski/spliit-cloud) β€” community fork that continues Spliit with new features. Several UX improvements in this Workers/KV fork were prioritized from their roadmap and upstream issue links (reimplemented for denormalized KV documents, not a code port of their Postgres/API stack).
  • anon-spliit (sora-grayscale) β€” privacy-focused fork (E2EE, private instance, deletion/auto-delete). This Workers/KV fork adapted selected lifecycle and hardening ideas from that work; it does not port their end-to-end encryption or account/2FA stack.

License

MIT, see LICENSE. Same license family as upstream Spliit and Spliit Cloud; retain their copyright notices where applicable.

About

Spliit.app fork adapted to deploy on Cloudflare Workers via OpenNext w/Cloudflare KV as database

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages