Zapnin, the social planning app

Zapnin

Plans leave the group chat.

Studio
A Pivot & Anchor product
Platform
iOS & Android
Category
Social planning
Stack
Expo, Node, Postgres, Redis
Get it
App Store & Google Play
Status
Live, free, no ads

Selected work

Zapnin is a chat-first social planning app. Drop a plan in the group, everyone answers In, Maybe or Out, and a resolution engine untangles the “I'll go if you go” loops until the plan is actually on. Around the plan sits its own chat, a guest list, shared expenses that settle up over UPI, and an archive of the ones that happened.

Visit Zapnin
Built by , a design and engineering studio.

Zapnin is the most fun thing we've built, and the one that fought back hardest. It is a chat-first social planning app for the oldest problem in any group chat: the plan that never happens.

You know the failure. Someone says “we should hang out,” three people say “maybe,” one says “I'm down if everyone else is,” and the thread dies. Zapnin replaces the maybe. Everyone answers In, Maybe or Out. Conditions stay private. A resolution engine works out who is waiting on whom, breaks the loops, and the moment it tips, the plan is on.

How it works

Twelve vibes, and no form screen

01 — The first decision

Twelve vibes, and no form

A plan starts with what kind of thing it is, not with a date. One tap sets the artwork and the invite wording, and decides whether the plan even needs a place at all. Everything after this screen is optional.

02 — Enough to answer

A plan you can reply to

Photo, title, who is coming and when all sit on one card, and the time can be left as let everyone decide. The invite goes out with enough context that nobody has to ask the host what the plan actually is.

03 — The part that stalls

Pick a day, or deliberately don't

Some plans have a date. Most do not, and that is where group chats go to die. The host can leave the time open on purpose, and the app collects real availability instead of four people saying they are flexible.

04 — The other part that stalls

A place, online, or undecided

Location gets the same treatment. Undecided is a state the plan is allowed to hold, so everyone can see what still needs input rather than guessing whether anyone has booked anything.

05 — Sent

Now it is a thing, not a message

The plan becomes an object with its own chat, its own guest list and its own answer state. It stops being the fourteenth message in a thread that scrolls away by Thursday.

What we built

  • Honest responses

    In, Maybe or Out. Maybe is the wedge: an answer that keeps the plan alive instead of stalling it, and a private condition underneath it that nobody else ever sees.

  • The resolution engine

    A graph that maps conditions, detects circular dependencies, and resolves chains automatically from confirmed anchors outward.

  • Live status

    Every response propagates to every device in real time, so the plan's state is always honest and shared.

  • Split the bill

    In-chat expenses, simplified-debt settlement to the fewest transfers, and circles that remember your groups.

  • Privacy by default

    Show the status, not the story. Conditions stay private; only the outcome is shared.

Zapnin looks like a chat app. Underneath, it is a coordination engine.

The mobile app is React Native on Expo SDK 54, one TypeScript codebase across iOS and Android, on the New Architecture. State is local-first: Zustand stores hydrated from encrypted on-device storage, updated optimistically, with a query cache as a warm fallback. A socket layer keeps it honest. Every plan and every chat is a live room, and responses reach every invitee the instant they happen.

The resolution lives on the server, never the client. The client renders state; it does not compute it. A “depends on Priya” can resolve from any device without races. The engine builds a dependency graph per plan, detects cycles, anchors on the hard confirmations, and propagates outward until the plan finalizes. That is the piece everything else hangs off.

The backend is Node and Express on PostgreSQL with Drizzle, twenty-three tables modelling plans, invitees, conditions, chat, bills, and circles. Socket.IO runs behind a Redis adapter so it scales across instances. Background work runs on BullMQ: nudges to non-responders, day-of reminders, deadline checks, auto-completion, and a settlement cascade across circles.

It runs on Railway, with Postgres, Redis, and a multi-stage Docker build that migrates on deploy. There is a web layer too: a marketing site plus invite links that let someone RSVP and vote on the venue from a browser before they ever install, and a private operations dashboard for the team.

The hard parts

  • The resolution engine

    Graph-based dependency propagation with cycle detection and anchor-based confirmation. The maybe-loop, solved in code.

  • Real time at scale

    Socket.IO behind a Redis adapter, every plan and chat a live room, state broadcast cleanly across instances.

  • Notifications that respect you

    Escalation-based push batching with atomic Redis operations. A busy chat sends one digest, not forty pings, and a mention always breaks through.

  • Money math, instant

    Simplified-debt settlement and a layered, stampede-proof cache so balances across every plan stay instant.

  • Honest offline

    Optimistic UI with rollback, a message queue for dead zones, and a reachability check tuned for real-world networks.

Zapnin pairs a loud display face with a calm body. Righteous carries the headlines, round and confident, the way the product talks. Plus Jakarta Sans does the reading, neutral and modern.

  • RighteousDisplay & headings
    Regular
  • Plus Jakarta SansBody & UI
    Regular · Medium · SemiBold · Bold

Electric azure leads, the current colour of the brand and every primary action. Then a pair you read without thinking: emerald means In, red means Out. Amber warns, and true black carries the dark mode.

  • AzurePrimary. The current brand and every key action.#3D6BFF
  • Azure deepAccessible text and solid controls on light surfaces.#2C53E0
  • EmeraldSuccess, and the colour of “In”.#10B981
  • RedErrors, and the colour of “Out”.#EF4444
  • AmberWarnings and pending states.#F59E0B
  • InkTrue-black dark-mode background.#0A0A0A
  • PaperLight-mode background; dark-mode text.#FAFAFA