A modern, real-time collaborative retrospective tool built with SvelteKit 5 and SQLite.
# Install dependencies
npm install
# Generate and apply SQLite schema
npm run db:push:sqlite
# Start development server
npm run dev
The application will be available at http://localhost:5173
# Install dependencies
npm install
# Set DATABASE_URL for PostgreSQL
export DATABASE_URL="postgresql://user:password@localhost/teambeat"
# Generate and apply PostgreSQL schema
npm run db:push:postgres
# Start development server with PostgreSQL
npm run dev
The database type is automatically detected from DATABASE_URL
:
postgres://
or postgresql://
→ PostgreSQL./teambeat.db
)Use the provided docker-compose.yml for easy deployment:
# Build and start the application
docker-compose up --build
# Run in background
docker-compose up -d --build
The application will be available at http://localhost:3000
with the database persisted in ./db/teambeat.db
.
# Build the Docker image
docker build -t teambeat .
# Create database directory
mkdir -p ./db
# Run the container
docker run -d \
--name teambeat \
-p 3000:3000 \
-v $(pwd)/db:/db \
-e DATABASE_URL=/db/teambeat.db \
teambeat
The Dockerfile uses a multi-stage build:
Key features:
/db
directoryDATABASE_URL
: Path to SQLite database file (default: /db/teambeat.db
)PORT
: Application port (default: 3000
)NODE_ENV
: Environment mode (set to production
in container)/db
: Database directory (required for data persistence)/app/logs
: Application logs (optional)# Generate SQLite migration from schema changes
npm run db:generate:sqlite
# Apply SQLite schema to database
npm run db:push:sqlite
# Open database studio
npm run db:studio
# Generate PostgreSQL migration from schema changes
DATABASE_URL="postgresql://localhost/teambeat" npm run db:generate:postgres
# Apply PostgreSQL schema to database
DATABASE_URL="postgresql://user:pass@host/db" npm run db:push:postgres
# Open database studio
DATABASE_URL="postgresql://user:pass@host/db" npm run db:studio
Both databases use the same schema with automatic type adaptation:
boolean
in PostgreSQL, integer
in SQLitesrc/
├── lib/
│ ├── server/
│ │ ├── db/ # Database schema and connection
│ │ ├── repositories/ # Data access layer
│ │ ├── sse/ # Server-Side Events handling
│ │ ├── auth/ # Authentication, sessions & WebAuthn
│ │ ├── performance/ # Performance tracking & persistence
│ │ ├── middleware/ # Request middleware (presence, etc.)
│ │ └── utils/ # Shared server utilities
│ ├── components/ # Reusable UI components
│ │ └── ui/ # Base UI components
│ ├── stores/ # Client-side state management
│ ├── utils/ # Shared utilities (RPN, data parsing)
│ ├── styles/ # LESS styles and mixins
│ ├── data/ # Static data (column presets)
│ └── types/ # TypeScript type definitions
├── routes/
│ ├── api/ # REST API endpoints
│ │ ├── auth/ # Authentication endpoints
│ │ ├── boards/ # Board management
│ │ ├── cards/ # Card operations
│ │ ├── comments/ # Comments & agreements
│ │ ├── series/ # Series management
│ │ ├── scenes/ # Scene configuration
│ │ ├── scorecards/ # Scorecard management
│ │ ├── admin/ # Admin-only endpoints
│ │ └── sse/ # Real-time events
│ ├── board/[id]/ # Board interface
│ ├── series/[id]/ # Series management pages
│ ├── admin/ # Admin pages
│ ├── login/ # Authentication pages
│ ├── register/
│ └── profile/
├── app.html # Root HTML template
└── hooks.server.ts # Server-side hooks
POST /api/auth/register
- Create accountPOST /api/auth/login
- Sign in with passwordPOST /api/auth/logout
- Sign outGET /api/auth/me
- Get current userPUT /api/auth/profile
- Update user profilePUT /api/auth/change-password
- Change passwordDELETE /api/auth/delete-account
- Delete user accountPOST /api/auth/dev-login
- Development login (dev only)POST /api/auth/webauthn/register/begin
- Start passkey registrationPOST /api/auth/webauthn/register/complete
- Complete passkey registrationPOST /api/auth/webauthn/authenticate/begin
- Start passkey authenticationPOST /api/auth/webauthn/authenticate/complete
- Complete passkey authenticationGET /api/auth/webauthn/passkeys
- List user's passkeysDELETE /api/auth/webauthn/passkeys/[id]
- Delete a passkeyGET /api/series
- List user's seriesPOST /api/series
- Create new seriesGET /api/series/[id]
- Get series detailsPUT /api/series/[id]
- Update seriesDELETE /api/series/[id]
- Delete seriesGET /api/series/[id]/users
- Get series usersPOST /api/series/[id]/users
- Add user to seriesGET /api/series/[seriesId]/columns
- Get series column presetsGET /api/series/[seriesId]/scorecards
- List series scorecardsPOST /api/series/[seriesId]/scorecards
- Create series scorecardPUT /api/series/[seriesId]/scorecards/[id]
- Update scorecardDELETE /api/series/[seriesId]/scorecards/[id]
- Delete scorecardGET /api/boards
- List user's recent boardsPOST /api/boards
- Create new boardGET /api/boards/[id]
- Get board detailsPUT /api/boards/[id]
- Update boardDELETE /api/boards/[id]
- Delete boardPOST /api/boards/[id]/clone
- Clone boardGET /api/boards/[id]/clone-sources
- Get available boards to clone fromPUT /api/boards/[id]/scene
- Change current scenePUT /api/boards/[id]/setup-template
- Setup board templateGET /api/boards/[id]/present-data
- Get present mode dataGET /api/boards/[id]/user-votes
- Get user's vote dataGET /api/boards/[id]/user-status
- Get voting status infoPUT /api/boards/[id]/share
- Update board sharing settingsGET /api/boards/[id]/scenes
- Get board scenesPOST /api/boards/[id]/scenes
- Create sceneGET /api/boards/[id]/scenes/[sceneId]
- Get scene detailsPUT /api/boards/[id]/scenes/[sceneId]
- Update sceneDELETE /api/boards/[id]/scenes/[sceneId]
- Delete scenePUT /api/boards/[id]/scenes/reorder
- Reorder scenesGET /api/boards/[id]/scenes/[sceneId]/columns
- Get scene columnsGET /api/scenes/[id]/select-card
- Select presentation cardGET /api/boards/[id]/columns
- Get board columnsPOST /api/boards/[id]/columns
- Create columnPUT /api/boards/[id]/columns/[columnId]
- Update columnDELETE /api/boards/[id]/columns/[columnId]
- Delete columnPUT /api/boards/[id]/columns/reorder
- Reorder columnsGET /api/boards/[id]/cards
- Get all cards for boardPOST /api/boards/[id]/cards
- Create new cardPOST /api/boards/[id]/cards/group
- Group multiple cardsGET /api/cards/[id]
- Get card detailsPUT /api/cards/[id]
- Update card contentDELETE /api/cards/[id]
- Delete cardPUT /api/cards/[id]/move
- Move card between columnsPUT /api/cards/[id]/group
- Group cards togetherPUT /api/cards/[id]/group-onto
- Group card onto anotherPOST /api/cards/[id]/vote
- Toggle vote on cardGET /api/boards/[id]/voting-stats
- Facilitator voting dashboardPOST /api/boards/[id]/votes/clear
- Clear all votesPOST /api/boards/[id]/votes/increase-allocation
- Increase vote allocationGET /api/boards/[id]/comments
- Get board commentsPOST /api/cards/[id]/comments
- Add comment to cardGET /api/comments/[id]
- Get comment detailsPUT /api/comments/[id]
- Update commentDELETE /api/comments/[id]
- Delete commentPOST /api/comments/[id]/toggle-agreement
- Toggle agreement on commentPOST /api/comments/[id]/complete
- Mark comment as completePOST /api/comments/[id]/copy-to-card
- Convert comment to cardGET /api/boards/[id]/agreements
- Get board agreementsGET /api/agreements/[id]
- Get agreement detailsPUT /api/agreements/[id]
- Update agreementDELETE /api/agreements/[id]
- Delete agreementPOST /api/agreements/[id]/complete
- Mark agreement as completePOST /api/agreements/[id]/copy-to-card
- Convert agreement to cardGET /api/cards/[id]/notes
- Get card notesPUT /api/cards/[id]/notes
- Update card notesPOST /api/cards/[id]/notes/lock
- Lock/unlock notes editingGET /api/scorecards/[scorecardId]/datasources
- List scorecard data sourcesPOST /api/scorecards/[scorecardId]/datasources
- Create data sourcePUT /api/scorecards/[scorecardId]/datasources/[id]
- Update data sourceDELETE /api/scorecards/[scorecardId]/datasources/[id]
- Delete data sourcePUT /api/scorecards/[scorecardId]/datasources/reorder
- Reorder data sourcesGET /api/scenes/[sceneId]/scorecards
- List scene scorecardsPOST /api/scenes/[sceneId]/scorecards
- Add scorecard to sceneGET /api/scene-scorecards/[id]
- Get scene scorecard detailsPUT /api/scene-scorecards/[id]
- Update scene scorecardDELETE /api/scene-scorecards/[id]
- Remove scorecard from scenePOST /api/scene-scorecards/[id]/collect-data
- Trigger data collectionGET /api/scene-scorecards/[id]/results
- Get scorecard resultsPOST /api/scene-scorecard-results/[resultId]/flag
- Flag a resultGET /api/sse
- Server-Side Events endpointPUT /api/boards/[id]/presence
- Update user presencePOST /api/boards/[id]/timer
- Start/vote on timerDELETE /api/boards/[id]/timer
- Stop timerPOST /api/timer/vote
- Vote on timer extensionGET /api/admin/performance
- Get performance metrics (admin only)POST /api/admin/performance
- Reset performance metrics (admin only)GET /api/admin/performance/history
- Get historical performance data (admin only)GET /api/admin/performance/timeseries
- Get time series data (admin only)GET /api/health
- Health check endpointGET /api/templates
- Get available board templatesThe application uses Server-Side Events streamed on the same port as the web application for real-time updates:
card_created
- New card added to boardcard_updated
- Card content or properties changedcard_deleted
- Card removed from boardcard_moved
- Card moved between columnscards_grouped
- Multiple cards grouped togethervote_changed
- Vote count updated on cardcomment_added
- New comment added to cardcomment_updated
- Comment content changedcomment_deleted
- Comment removedagreement_toggled
- Agreement status changed on commentvoting_stats_updated
- Facilitator voting statistics changedscene_changed
- Meeting phase changedboard_updated
- Board settings or metadata changedcolumns_updated
- Column configuration changedupdate_presentation
- Present mode display updateduser_joined
- User joined boarduser_left
- User left boardpresence_update
- User activity changed (includes presence_data)presence_ping
- Server ping to maintain presencetimer_update
- Timer status changedtimer_started
- Timer startedtimer_stopped
- Timer stoppedtimer_vote
- Vote cast on timer extensionscorecard_data_collected
- Scorecard data collection completedscorecard_result_added
- New scorecard result availableCore Retrospective:
Data Collection & Analysis:
Administration:
Infrastructure:
User Experience:
Features:
Security & Integration:
Performance:
Built according to CLAUDE.md development guidelines emphasizing explicit over implicit code, libraries over custom solutions, and human-maintainable architecture.
MIT License. See LICENSE
file for details.
The DiceBear avatar style Adventurer is a remix of: Adventurer by Lisa Wischofsky, licensed under CC BY 4.0.