A modern, real-time Scrum Retrospective tool for agile teams — anonymous, secure, and simple. Built with Nuxt 4, TypeScript, and WebSockets. Part of the growing scrum app stack alongside Planning Poker.
Write → Group → Vote → Discuss → Act
| Phase | Description |
|---|---|
| Set the Stage | Check-in with emoji moods to warm up the team |
| Gather Data | Submit anonymous cards to three columns |
| Generate Insights | Drag & drop cards into thematic groups |
| Dot Voting | Distribute votes freely across cards and groups |
| Decide Actions | Define action items with assignees and due dates |
| Close Retro | Review summary, export results, and give feedback |
- Real-time sync — All changes broadcast instantly via WebSocket
- Anonymous cards — No author information revealed to participants
- Join codes — Easy 6-character codes (non-confusable charset, no
O/0/I/1/l) - Session timer — Built-in countdown with audio chime notification
- Export — Download results as JSON, Markdown, or high-quality PNG image
- Responsive design — Optimized for desktop and mobile
- 12 languages — EN, DE, ES, FR, IT, JA, NL, PL, PT-BR, RU, SV, ZH-CN
- Zero persistence — Sessions live in memory only, no database
- No authentication — Friction-free access, nothing stored
- Input sanitization — Server-side HTML stripping with iterative bypass protection
- Rate limiting — Action item and card creation limits prevent abuse
- Phase enforcement — Server validates all operations against the current session phase
| Layer | Technology |
|---|---|
| Framework | Nuxt 4 (Vue 3 + Nitro) |
| Language | TypeScript (strict mode, vue-tsc) |
| Styling | Tailwind CSS + custom semantic tokens |
| Real-time | WebSocket via crossws |
| Runtime | Bun |
| Icons | Heroicons via @nuxt/icon |
| i18n | @nuxtjs/i18n with 12 locales |
| Sanitization | DOMPurify (client) + custom stripHtml (server) |
- Bun ≥ 1.0
bun installbun run dev
# → http://localhost:3000bun run build
bun run previewbun test # Run test suite
bun run typecheck # Type-check (vue-tsc --noEmit)
bun run lint:fix # ESLint with auto-fixretro-rumble/
├── app/
│ ├── components/ # Vue components (RetroBoard, VotingBoard, ClusterCanvas, …)
│ ├── composables/ # Reusable logic (useWebSocket, useRetroSession, useExport, …)
│ ├── pages/ # Single-page route (index.vue)
│ ├── types/ # TypeScript interfaces & constants
│ │ ├── retro.ts # Domain types (IRetroSession, IRetroCard, ICardGroup, …)
│ │ └── websocket.ts # Client/server message protocol types
│ ├── utils/ # Shared OOP classes & config
│ │ ├── RetroSession.ts # Core session logic (used by client & server)
│ │ ├── Participant.ts # Participant model
│ │ └── columnConfig.ts # Centralized column metadata (DRY)
│ └── assets/css/ # Global Tailwind styles
├── i18n/locales/ # 12 translation files (en, de, es, fr, it, ja, nl, pl, pt-BR, ru, sv, zh-CN)
├── server/
│ ├── routes/_ws.ts # WebSocket message dispatcher (30+ handlers)
│ └── utils/sessionStore.ts # In-memory session store singleton
├── tests/ # Bun test suite (222 tests)
├── nuxt.config.ts
├── tailwind.config.ts
└── package.json
Vue Components → useRetroSession → useWebSocket → WebSocket Server (_ws.ts) → SessionStore → Broadcast
- Interface-first types — All domain types in
app/types/, prefixed withI. Constants useas constarrays with derived union types. - Shared OOP models —
RetroSessionandParticipantclasses implement interfaces, providetoJSON()/fromJSON()serialization, and are shared between client and server. - Composables —
useWebSocket(connection singleton with auto-reconnect),useRetroSession(session state + all actions),useExport(JSON/Markdown/PNG export),useClusterCanvas(drag & drop). - WebSocket protocol — Typed messages
{ type, payload, timestamp }with separate client/server message type unions inapp/types/websocket.ts.
create → set-the-stage → gather-data → generate-insights → voting → decide-action → close-retro
Sessions auto-delete when the last participant disconnects and the idle TTL (30 min) expires. Participants can rejoin within this window.
All user-facing strings are localized via @nuxtjs/i18n. Currently supported:
| Language | Code | File |
|---|---|---|
| English | en |
en.json |
| Deutsch | de |
de.json |
| Español | es |
es.json |
| Français | fr |
fr.json |
| Italiano | it |
it.json |
| 日本語 | ja |
ja.json |
| Nederlands | nl |
nl.json |
| Polski | pl |
pl.json |
| Português (BR) | pt-BR |
pt-BR.json |
| Русский | ru |
ru.json |
| Svenska | sv |
sv.json |
| 中文 (简体) | zh-CN |
zh-CN.json |
The project includes a comprehensive test suite using bun:test:
bun test
# 222 tests, 0 failures, 524 expect() calls across 4 filesCoverage includes:
RetroSession— Phase management, card CRUD, voting, groups, action items, timer, deep copy safetyParticipant— Serialization and state transitionsSessionStore— Full server-side logic including phase restrictions, rate limiting,stripHtmledge cases, host authorization- Type validation — Constant correctness, validator functions
MIT License