[ PRODUCT PAPER 01 — JUDGEMENT ]
Find the thing everyone can nod to
The concept, design decisions, and technical architecture behind Nod Together — a group-decision tool with no accounts, private ballots, and a consensus engine that favours what everyone can live with over what a few people love.
Nod Together is a small web application for a familiar problem: a group of two to twenty people needs to pick a restaurant, a film, a date, a plan — and the group chat has stalled. Someone lists options, three people react, two go quiet, and the loudest preference wins by exhaustion.
The product is deliberately narrow. A host shares one link, everyone reacts to every option in private, and the group gets one answer with a plain-language explanation of why. No sign-up, no app install, no vote-shaming, no data that outlives its usefulness.
This paper describes the idea, the consensus algorithm, the design decisions and their trade-offs, and the architecture it runs on. Nod Together is live at nodtogether.app.
What this demonstrates
Nod Together is a working example of how Eirvanta approaches commissioned products: understand the underlying problem, remove unnecessary complexity, design the full experience, build in testable vertical slices, and deliver a production system with an operating cost you can understand before launch. The rest of this paper is that approach, shown rather than claimed.
The problem
Low-stakes group decisions fail in predictable ways, and most tools make the failure modes worse rather than better:
- Public votes create social pressure — people agree with whoever answered first
- Plurality polls crown intense minorities over broadly acceptable options
- A quiet, serious objection carries the same weight as a mild preference
- Sign-up walls kill participation before it starts
- The decision never actually closes — it just fades until someone gives up
Nod Together treats each of these as a design constraint rather than an afterthought.
When a chat poll is enough — and when it isn't
The honest comparison is not to other decision apps but to the tool every group already has: a poll in the chat. For "pizza or sushi?" among five close friends, a WhatsApp poll is the right tool — zero friction, and the answer lives where the conversation is. Nod Together exists for the situations where that poll quietly fails:
- Someone has a real constrainteight votes for curry and one coeliac — in a tally that vote is one of nine; here a Hard No means the option cannot win
- Voting is socially loaded"stay at Dave's place" versus "get a hotel", with Dave in the chat — names attached to votes mean nobody answers honestly
- The group spans more than one chathalf on WhatsApp, two on iMessage, one email-only — a chat poll cannot leave its chat; a link goes anywhere
- The decision needs to actually enda poll scrolls away and the trip never gets booked; a deadline and a one-way reveal produce an answer with a date on it
None of these situations is exotic — they are precisely the decisions that stall. A chat poll counts preferences in public and leaves the question open; Nod Together finds what the group can live with, in private, and then closes it.
The idea
Instead of asking "which one do you want?", Nod Together asks a gentler and more honest question about every option: could you live with this? Each participant reacts to each option with one of four reactions — Yes, Maybe, No, or Hard No.
The distinction between No and Hard No is the heart of the product. A No is a preference; a Hard No is an incompatibility — a dietary restriction, a budget limit, a genuine "this does not work for me." The algorithm treats Hard No as a veto, not a strong dislike, so one person's real constraint can never be steamrolled by four people's enthusiasm.
Three further commitments define the concept:
- No accountsa link is the entire product surface
- Private ballotsnobody — including the host — sees individual votes
- One shared outcomethe group sees the result and why, never the raw votes
The scope is explicitly small groups making reversible, social decisions. It is not for elections, governance, or anything binding — and the product says so.
The consensus engine
The algorithm, versioned as consensus-v1, is a pure, deterministic function with no dependencies and no randomness. Each reaction maps to a fit value:
- Yes — happy with itfit 100
- Maybe — can go along with itfit 60
- No — would prefer notfit 15
- Hard No — does not workfit 0, and a veto
An option's Group Fit is the average fit across everyone who completed their ballot. Selection happens in three steps:
- Build the candidate pool: options with zero Hard Nos if any exist, otherwise those with the fewest
- Rank candidates by raw Group Fit, then acceptance rate (Yes + Maybe share), then Yes count, then fewest Nos, then original option order
- Classify the outcome: The Nod (zero vetoes, fit ≥ 65), Best Fit (fit 45–64), Close Call (winner and runner-up within 5 points), Tie, or No Clear Nod (every option vetoed, or nothing reaches fit 45)
Worked example
Option A gets 3 Yes, 1 No and 1 Hard No — intense support, one veto, fit 63. Option B gets 2 Yes and 3 Maybe — nobody's favourite, nobody's problem, fit 76 with zero vetoes.
B wins. Broad acceptance beats narrow enthusiasm, and a veto is never outvoted. This is the single most opinionated choice in the product.
When there is no clear winner, the product says so honestly — "No clear nod — yet" — and suggests a runoff with the least controversial options instead of manufacturing a hollow victory.
Design decisions
No accounts, by design
Group decisions do not need persistent identity, so Nod Together never asks for one. A host receives two links at creation: a public participant link built from a 12-character code (~60 bits of entropy, ambiguous characters removed) and a private management link built from a 32-byte secret. Participants type a display name and vote. Sessions live in HttpOnly cookies scoped to a single decision; a "This isn't me" button hands a shared device cleanly to the next person.
Private votes, public outcomes
The host sees who has joined and who has finished — never how anyone voted. The result page shows the outcome, the Group Fit, and a plain-language explanation. Per-reaction breakdowns are hidden entirely when fewer than four people completed, because in a group of three a breakdown is a de-anonymiser. Raw votes are deleted 24 hours after the reveal; only the aggregate snapshot survives.
The link is the product
Since everything travels through chat, the share experience is treated as a first-class surface. Participant links live at the domain root (nodtogether.app/{code}) to stay short and clean. Link unfurls carry the decision question itself, so an invitation reads as an invitation — "Where are we eating tonight? — vote on Nod Together" — rather than a generic app card. Hosts also get a QR code for people-in-the-same-room decisions.
Decisions that end
A decision moves through a strict lifecycle — open, closed, revealed, expired — and the reveal is a one-way door: the result is computed once, stamped with the algorithm version, and stored as an immutable snapshot. Optional deadlines close voting automatically. Undecided decisions expire after seven days, results after thirty, and a scheduled cleanup job makes the forgetting real rather than aspirational.
Warmth as a spec, not a garnish
The copy is written for friends deciding, not committees resolving. The winner gets "the nod," not a victory; a failed round is "no clear nod — yet." Motion is restrained, confetti respects reduced-motion preferences, and the whole flow works one option per screen on a phone — because that is where these decisions actually happen.
Technical architecture
The stack is deliberately boring in the best sense — a small number of well-understood pieces:
- ApplicationNext.js 15 (App Router), React 19, TypeScript strict
- StylingTailwind CSS 4 over design-token custom properties
- DataPostgreSQL with Drizzle ORM and forward-only migrations
- ValidationZod schemas shared between client and server
- TestingVitest units, Playwright end-to-end on desktop and mobile
- HostingDocker on Azure Container Apps, Azure PostgreSQL, Cloudflare edge
- DeliveryGitHub Actions — lint, typecheck, migrate, test, deploy, smoke test
The consensus engine lives in a pure domain module with no framework or database imports, covered by its own unit-test suite. Every stored result records which algorithm version produced it, so the engine can evolve without silently rewriting history.
Real-time updates are polling-first: the waiting room refreshes every few seconds through the same API the page loads with. A push channel (Azure Web PubSub) is designed in behind an adapter so it can be added later without touching callers — and polling remains the fallback if the push layer ever fails. For a twenty-person ceiling, this ordering of effort is the honest one.
The dependency list is as notable for what is absent: no Redis, no email service, no analytics SDK, no AI, no payments. Each absence is a feature the product does not have to operate, secure, or explain.
What it costs to run
Architecture claims are cheap; bills are not. At its current early-stage usage — dozens of decisions and voters a week, not thousands — Nod Together runs in production for under $40 a month, all-in — compute, database, TLS, bot protection, daily backups, a full deployment pipeline, retention jobs, and privacy-safe usage analytics. Nothing in that figure is subsidised or temporary; it is what a small, honest architecture costs when nothing is added for show.
The figure will grow with real usage — but it grows with users, not with time. A product like this should never cost more to keep alive than it costs to ignore.
Privacy and security model
A no-account product earns trust through architecture rather than a login screen:
- Host and participant tokens are HMAC-SHA256-hashed with a server-side pepper before storage and compared in constant time — a database leak exposes no usable links
- Management pages send no referrer, so host links do not leak through outbound clicks
- Error responses never reveal whether a token exists — a wrong code and a missing decision look identical
- Rate limiting, a honeypot field, and Cloudflare Turnstile guard creation and joining
- Telemetry is an allowlist of content-free events with counts only — question text, names, and votes never enter logs or analytics
- Only strictly necessary cookies are used, so there is no consent banner because there is nothing to consent to
The privacy promise shown to every participant — "Your vote is private; only the group outcome is shared" — is enforced by the schema and retention policy, not just the interface.
What it deliberately is not
Most of Nod Together's shape comes from refusals. There are no accounts, no social graph, no history beyond a device-local list of your own recent decisions, no comments, no notifications, and no growth loops. It is not a polling platform, a governance tool, or a survey product.
The bet is that a tool which does one small social thing gracefully — and then gets out of the way and deletes the evidence — is worth more than a bigger tool that does the same thing while asking for your email address.
Try it
Nod Together is live and free. Create a decision, share the link, and see the nod for yourself.
Open Nod TogetherAbout Eirvanta
Every purposeful product begins with judgement. Nod Together is built and operated by Eirvanta LLC, an independent software studio. We build small, purposeful products and learn through real use.
We also build products like this for others. The approach documented here — a tight written spec, vertical slices, tests at every milestone, and an architecture that costs tens of dollars a month rather than thousands — is how we deliver commissioned work: a clearly defined scope, transparent fixed pricing for each delivery stage, and an operating cost you can understand before launch. If you have a product that deserves this treatment, talk to us.
More at https://www.eirvanta.com