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.