Skip to content

Case study · Community finance

A ledger every member can read.

Collective Ledger runs the money of small communities: monthly installments that compound, late fees that calculate themselves, investments on the record, and an admin the members elect.

October · Installment

₹2,122.00 each

Sample ledger entries for one month
DateMemberStatusAmount
03 OctAarav M.Paid2,122.00
05 OctPriya N.Paid2,122.00
10 OctKabir S.Paid2,122.00
14 OctRhea K.Paid2,122.00+80.00 late
—Dev P.Pending2,122.00

Collected

₹8,568.00

Sample entries for illustration. Real figures appear after sign-in.

Role
Product design and full-stack engineering
Client
Next.js 16, React 19, Zustand
Server
Express, Mongoose, MongoDB
Access
JWT with email OTP verification

The problem

Shared money breaks on trust.

Spreadsheets drift, someone forgets who paid, and the person holding the cash is never questioned. Four decisions shaped the product.

  1. 01

    Money is an integer.

    Every amount is stored and calculated in whole paise on the server. The interface only formats what it is given, so there is no floating-point drift between what a member sees and what the books say.

  2. 02

    Installments compound.

    Each month starts from the previous month’s amount and adds a bounded random rise, inside a range the community’s admin sets once. The first month never rises.

  3. 03

    Admins are elected.

    With up to five members, the founding admin runs the books. Past five, the community votes, one member one vote, and privileged actions wait for a result.

  4. 04

    Every action leaves a trail.

    Approvals, bulk payments and investments are recorded against the admin who made them, and payments, investments and the audit log export as CSV.

The mechanics

Two rules carry the whole ledger.

Pick a month, then drag the day it’s paid. This runs the same arithmetic the API does: whole paise, a due date on the 10th, ₹20 for each day after.

Installment schedule

Illustrative

MonthRiseBaseDue

Each month starts from the last one and adds a bounded random rise. Six months take ₹2,000.00 to ₹2,317.45 (+15.9%).

If paid on day

14

Apr · 4 days late

Installment
₹2,206.26
Late fee (4 × ₹20)
+₹80.00
Total due
₹2,286.26

Computed on the server in whole paise; the interface only displays it.

The flow

From a payment to the books.

Members never edit the ledger. They ask, an admin confirms, and the server does the arithmetic.

  1. 01

    Member pays

    Outside the app, directly to the community. Then taps “Mark paid”, which files a payment request.

  2. 02

    Admin reviews

    The request lands in the admin’s queue with the member, month and amount.

  3. 03

    Approval records it

    On approve, the server writes the payment and calculates any late fee itself.

  4. 04

    Totals recompute

    Collected, pending and unallocated surplus refresh for the whole community.

  5. 05

    Trail is written

    The action is logged against the admin who took it, and can be exported as CSV.

Engineering

Small system, strict edges.

System architectureNext.js client, then Express API, then MongoDB. The API also sends email and runs a daily installment job.Next.js 16 clientReact 19 · Zustand · MotionExpress APIJWT · Zod · helmet · limitsMongoDBMongoose · integer paiseJobdailyEmailOTP · invitesREST · JWT + communityqueries
Two repositories: a Next.js App Router client and an Express + Mongoose API. The client never computes money — it formats what the server returns.
Client state
Zustand stores per domain (installments, payments, requests, investments, votes), with the session persisted and rehydrated safely.
Money
Integer paise end to end. Late fees, overpayment limits and bulk writes are validated server-side.
Auth
JWT bearer tokens, email OTP verification, role checks on the API and mirrored in the interface.
Tenancy
A community id travels with every request, so one deployment serves many communities.
Onboarding
Invite links, or a join request with a three-minute approval window the client polls.
Operations
Rate limiting, secure headers, schema validation and structured logging on the API.

Roles

Members see. Admins act.

Past five members, admin powers stay locked until an election has a winner.

What members and admins can do
CapabilityMemberAdmin
See own installments, penalties and historyYesYes
Request confirmation of a paymentYesYes
Vote in admin electionsYesYes
See community investmentsYesYes
Approve or decline payment requestsNoYes
Mark payments in bulkNoYes
Approve join requests and send invitesNoYes
Record investmentsNoYes
Export CSV and read the audit logNoYes
Portrait of Nirmal Ranpariya

Built by

Nirmal Ranpariya

Designed and engineered end to end: the interface, the client state, the API and the data model. The brief was a tool a community would actually trust with its money, so the product leans on plain language, visible arithmetic and no hidden steps.

Questions

Asked and answered.

How does someone join a community?

By invite link from the admin, or by asking to join. A join request waits up to three minutes for the admin; once approved, the member confirms their email with a one-time code.

What happens when a payment is late?

Installments are due by the 10th. After that the server adds ₹20 for every day late, and the member sees the same figure the admin does.

How is the admin chosen?

A community of five or fewer is run by its founding admin. Once it grows past five, members vote and the winner holds the admin role.

Can the books be exported?

Yes. Payments for a month, investments and the audit log each download as CSV from the admin console.

Is my community’s data separate from others?

Every request carries the community it belongs to, and the API scopes reads and writes to that community.

Is there a mobile app?

There’s no native app. The site is responsive and every screen, including the admin console, works at phone width.