It was a Wednesday afternoon retro. Ten engineers and functional consultants. We opened the planning poker tool. Six people could join on the free plan. The other six stared at a paywall.

I have spent fifteen years shipping ERP migrations for banks, payment platforms for scale-ups, and compliance systems for regulated industries. I have spent a career obsessing over user friction. Yet every time I needed to run a basic agile ceremony, I ended up fighting the tools instead of running the ceremony itself.

So I built Agile Ceremonies. Here is the product thinking behind it, the full technical architecture, and every decision I made along the way.

Engineer UUID · localStorage Consultant UUID · localStorage Product Manager UUID · localStorage Next.js 16 · Vercel SERVER Components API Routes 8 CEREMONY HOOKS usePokerRoom · useRetroRoom useHealthRoom · useLeanCoffeeRoom useFistRoom · useCapacityRoom useDemoRoom · useAgreementRoom Presence tracking · Typed broadcast events Supabase Realtime WebSocket Channels Presence · Broadcast events Neon PostgreSQL Prisma 7 ORM 8 isolated ceremony schemas 6-char codes · 24h auto-expiry HTTP request DB query (Prisma) Broadcast event WebSocket push

The Market Was Broken in Specific, Predictable Ways

Before writing a single line of code, I spent two weeks mapping the landscape. Not the marketing pages. The actual behaviour of the tools under conditions a real team encounters on a Friday afternoon.

The patterns were consistent across every tool I evaluated.

Free tiers are designed to fail publicly. PlanningPoker.com, Scrum Poker Online, and most competitors cap free rooms at four to eight participants. This is not accidental. It is a deliberate forcing function to trigger an upgrade conversation mid-ceremony, in front of the whole team. The pain is timed for maximum social pressure. As a PM who has run agile ceremonies for cross-functional teams across multiple time zones, I recognise this as a dark pattern.

Credit card requirements gate the free tier. The majority of tools that advertise a free plan require payment details upfront. This is a procurement blocker in enterprise environments, and a trust barrier for everyone else. No team should need to involve their finance department to run a fifteen-minute planning session.

Miro and equivalents are priced per seat, not per ceremony. Miro is a genuinely excellent product. It is also priced at levels that require a procurement sign-off for a team of twelve. The result: half the team has access, half does not. The facilitator ends up screensharing while everyone else watches passively. A collaborative ceremony becomes a presentation.

Sign-up friction kills participation before it starts. When you send a join link to twelve engineers and three cannot be bothered to create an account, verify their email, and set up a profile before the ceremony starts, the tool has already failed. A planning poker session with five absent voters is worse than no session at all.

The real problem was not that free tools had limits. It was that those limits were designed to appear at exactly the moment they would cause the most disruption: mid-ceremony, in front of the whole team.

The Product Decision: Radical Simplicity as Strategy

Once I had a clear problem definition, the product decisions were straightforward. Every feature choice had to pass one test: does this remove friction, or does it add it?

No accounts. Ever. The facilitator opens a room. The team gets a six-character code. They type it in. They are in. No email verification, no password, no profile, no onboarding wizard, no "you are on the free plan" banner. This is not a missing feature. It is a deliberate architectural constraint that shapes every other decision.

Unlimited participants on every plan, because there is only one plan. Agile ceremonies are team activities. A tool that works for five people but fails for twelve is not a team tool. The free tier is the only tier. Monetisation is not the goal of this product.

All eight ceremonies in one place. Planning poker gets the headlines, but a sprint team runs eight distinct ceremony types: planning poker, retrospective, team health check, lean coffee, fist of five, capacity planning, sprint review, and working agreement. Forcing context-switches between four different tools for a two-week sprint creates ceremony debt. One URL for all eight ceremonies eliminates that overhead.

Ephemeral by design. Rooms expire after twenty-four hours. There is no archive. There is no history. This is not a limitation. It is a GDPR strategy. No persistent user data means no data protection obligations beyond session duration. The legal surface area stays minimal.

EU hosted, GDPR compliant, no tracking. The tool runs on European infrastructure. No analytics cookies, no third-party tracking pixels, no user profiles. A product aimed at European engineering teams should be built to European data standards from the start, not retrofitted with a cookie banner six months later.

The Architecture: Full-Stack Next.js on Serverless Infrastructure

The technology choices followed directly from the product constraints. Zero accounts meant no auth infrastructure. Ephemeral rooms meant no long-lived storage. Unlimited participants meant the real-time layer needed to be robust under load. EU hosting shaped the infrastructure vendor selection.

Next.js 16 with React 19 as the full-stack framework. Next.js App Router gives a single codebase for server-rendered pages, API routes, and client-side interactivity. There is no separate backend service, no GraphQL layer, no BFF. API routes live alongside their UI in the same deployment. For a product this focused, that simplicity is the right call.

PostgreSQL via Neon with Prisma 7 as the ORM. Neon is a serverless PostgreSQL provider optimised for the connection patterns that serverless functions generate: short-lived, high-concurrency, unpredictable. Prisma provides type-safe query generation from the schema, which matters significantly when you have eight separate ceremony data models and want compile-time guarantees that your queries are valid.

Each ceremony type has its own isolated set of database models. Planning poker has Room, RoomParticipant, PokerRound, and Vote. Retrospectives have RetroRoom, RetroParticipant, RetroCard, and RetroVote. And so on across all eight types. This is deliberate: cross-ceremony contamination is eliminated at the schema level. A bug in the retro voting logic cannot corrupt a poker round.

Supabase Realtime for WebSocket-based presence and event streaming. The real-time layer is the most architecturally interesting decision. Every ceremony needs participants to see each other's actions immediately: votes cast, cards added, phases advanced. The naive approach is polling. The problem with polling at scale is that it is expensive, laggy, and punishes large rooms disproportionately.

Instead, every ceremony uses a dedicated Supabase Realtime channel. When a participant casts a vote, two things happen simultaneously: the vote is written to the database via the API route, and a broadcast event is published to the channel. Every other participant in the room receives the event via WebSocket within milliseconds and updates their local state. No polling. No page refresh. No perceptible latency.

Each ceremony type has its own React hook (usePokerRoom, useRetroRoom, useHealthRoom, and so on) that manages the Supabase channel lifecycle. The hook connects on mount, tracks presence (who is online, their display name, whether they are the facilitator), and listens for broadcast events. On unmount, the channel is cleanly unsubscribed.

Anonymous identity via localStorage UUID. When a user first visits, a UUID is generated via crypto.randomUUID() and stored in localStorage as their clientId. This ID is their identity for the session. The facilitator's clientId is stored on the room record at creation time. API routes that require facilitator privileges verify that the request's clientId matches the room's facilitatorId. No JWT. No session token. No cookie. One UUID in localStorage.

Six-character room codes with collision-resistant generation. Room codes are six alphanumeric characters, with visually ambiguous characters (O, 0, I, 1) excluded. Generation uses a retry loop: generate a candidate, check for uniqueness, retry up to ten times. The code space is large enough that collisions are negligible at current scale, and the retry loop handles them gracefully if they occur.

Vercel for deployment. Next.js API routes deploy as Vercel Functions: serverless, auto-scaling, zero configuration. The build step runs prisma generate before next build, ensuring the generated Prisma client is always in sync with the deployed schema.

The Engineering Details That Were Actually Product Decisions

Several technical choices in this project look like engineering decisions on the surface but are fundamentally product decisions about what kind of tool this is.

ERP mode for planning poker. Standard planning poker has a well-known bias problem: when a senior engineer votes first, everyone anchors to their estimate. ERP mode separates the functional/commercial stakeholders (FC) from the development team (DEV). Each group votes independently, then the results are compared. I added it because I had run ERP planning sessions where the estimate quality was measurably better when the two groups voted without seeing each other's numbers first. The name reflects where I first noticed the problem.

Dot voting limits per person across retro, lean coffee, and working agreement. Unlimited voting degenerates into popularity contests. A configurable votes-per-person limit forces prioritisation. Teams that have used this tool report that the constraint changes the quality of the conversation. Instead of voting for everything they agree with, participants have to decide what matters most.

Anonymous card authorship in retrospectives. Cards in retrospectives are not attributed to their author in the voting phase. Author identity is stored in the database for delete permissions, but it is not displayed to other participants during the voting round. Psychological safety in retrospectives is not a nice-to-have. It is the prerequisite for honest feedback.

Twenty-four-hour room expiry as a default. Teams occasionally ask if rooms can persist longer. My answer is no, and the reason is product philosophy rather than technical constraint: ceremonies are bounded events. A retro that is still accessible two weeks later is a retro that someone will go back and edit, screenshot, or use for retrospective accountability in ways the original participants did not consent to. Expiry is a design principle.

What I Would Do Differently

Shipping this product taught me things I could not have learned from planning it.

The Supabase Realtime channel architecture scales well within a ceremony, but I underestimated how much ceremony-specific state management complexity would live in the custom hooks. Each of the eight use*Room hooks is independently correct, but they share patterns that could be abstracted into a common base. This is a refactor I have deferred deliberately. Premature abstraction across ceremony types would have slowed the initial build significantly, and the shared patterns only became clear after all eight ceremonies were complete.

The absence of any analytics is both a virtue and a blindspot. I know rooms are being created (the daily counter on the homepage queries the database in real time). I do not know completion rates, drop-off points, or which ceremony types are most used. This was a deliberate choice: no tracking, no analytics, no user profiling. The cost is that I am building the product on instinct and user feedback rather than behavioural data. For a privacy-first tool, that is the correct trade-off.

Integrations with Jira, Linear, and Slack are the most-requested features. I have not built any of them. My view is that integrations are scope creep that would require me to negotiate with external APIs, maintain tokens, handle webhook failures, and suddenly own a data pipeline. The product is better for not having them.

The most important product decision I made was deciding what not to build. No accounts. No history. No integrations. No analytics. Constraints are not limitations. They are the product.

The Stack, Summarised

For engineers who want the specifics:

Frontend: Next.js 16 App Router, React 19, TypeScript 5, Tailwind CSS 4, shadcn/ui components.

Backend: Next.js API Routes (serverless), Prisma 7 ORM, PostgreSQL on Neon, Supabase Realtime for WebSocket presence and broadcast.

Data model: Eight isolated ceremony schemas. All rooms use six-character codes, twenty-four-hour expiry, and facilitator-as-clientId ownership. No user table. No auth table.

Real-time: Supabase channels with presence tracking and typed broadcast events. Optimistic UI updates: the client broadcasts immediately after the API call, so the UI updates before the server round-trip completes.

Deployment: Vercel Functions for API routes, Vercel Edge CDN for static assets. Build pipeline: prisma generate && next build.

Privacy: No cookies, no analytics, no email capture, EU-hosted infrastructure, GDPR compliant by design.

The tool is live and free at agileceremonies.com. No account required. No credit card. No onboarding wizard. Share a code and your team is in.