The previous SELECT → compare → UPDATE sequence let two concurrent login requests with the same valid 6-digit code both observe a stale lastTotpAt, both pass the in-JS replay check, and both succeed. A stolen TOTP (shoulder- surf, phishing-proxy replay) was usable twice within its 30 s window. Replace the three callsites (login authorize, self-service enable, self- service verify) with a shared consumeTotpWindow() helper: a single updateMany() expresses "window unused" as a SQL WHERE clause, so Postgres' row lock serialises concurrent writers and whichever commits second sees count=0 and is treated as a replay. Backup codes (ticket part 2) are tracked as follow-up work. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
CapaKraken
Resource & Capacity Planning for 3D Production Studios
Plan teams. Track chargeability. Forecast budgets. Staff smarter.
About
CapaKraken is a full-stack resource planning and project staffing application built for 3D production environments -- VFX studios, animation houses, and automotive visualization teams. It replaces spreadsheet-based capacity planning with a real-time, multi-user web application that provides a single source of truth for who is working on what, when, and at what cost.
The application was designed from the ground up for the unique challenges of creative production: fluctuating team sizes, overlapping project phases, mixed chargeability models (client-billable vs. internal vs. BD), complex holiday calendars across multiple countries, and the need to forecast resource availability months in advance.
Feature Overview
Interactive Timeline
The timeline is the centerpiece of CapaKraken. It provides a visual, interactive view of all resource allocations across projects.
- Resource View -- see all allocations for each person, with color-coded project bars stacked in sub-lanes when they overlap
- Project View -- flip the perspective to see all resources assigned to each project
- Zoom Levels -- switch between day, week, and month granularity; the grid adapts automatically
- Drag-and-Drop -- click and drag on empty timeline cells to create new allocations; existing bars can be moved or resized
- Heatmap Overlay -- toggle a per-day utilization heatmap that colors cells from green (underbooked) through yellow to red (overbooked), with configurable color schemes
- Vacation Integration -- approved and pending vacations overlay as semi-transparent bars; public holidays are shown per-country with federal state and city awareness
- Weekend Highlighting -- weekend columns follow the configurable accent/brand color for instant visual orientation
- Filters -- filter by project, client, chapter, country, role, order type, and more; toggle visibility of completed/cancelled projects, draft projects, and vacation blocks
- Overbooking Detection -- days where a resource exceeds their available hours flash with a warning overlay
Chargeability Forecasting
The chargeability module provides monthly forecasts comparing actual allocation against targets.
- Standard Available Hours (SAH) -- automatically calculated per resource, per month, accounting for weekends, public holidays (country/state/city-level), annual leave, sick days, and custom deductions
- Holiday Deduction Rules -- configurable per location: which holiday types to deduct, which calendars to apply, with a visual breakdown of gross days, holiday counts, and resulting net working days
- Target Comparison -- set chargeability targets at group or individual level; the report shows actual vs. target with color-coded variance
- Drill-Down Grouping -- group by chapter, role, management level, country, or custom dimensions
- Active Filters -- same powerful filter set as the timeline, applied consistently
- Export -- one-click Excel and CSV export with all visible data, formatting preserved
Chargeability Overview
A high-level view showing per-resource utilization as a color-coded heatmap across months, making it easy to spot under- or over-utilized team members at a glance.
Allocations
A structured list view of all allocations with:
- Status Workflow -- allocations move through Proposed, Confirmed, Active, Completed, and Cancelled states
- Grouping -- view by resource or by project, with expandable/collapsible groups
- Inline Editing -- quick-edit hours, dates, and status directly from the list
- Bulk Operations -- multi-select allocations for batch status changes or deletion
- Data Density Toggle -- switch between compact and detailed views; hide/show metadata columns
- New Planning Entry -- create allocations from a floating action button with project and resource pickers
Customizable Dashboards
Each user gets a personal dashboard they can customize with drag-and-drop widgets:
| Widget | Description |
|---|---|
| Overview Stats | Total resources, active projects, allocations, and budget utilization at a glance |
| My Projects | Quick access to projects where the current user is assigned or responsible |
| Resource Table | Filterable EID list with utilization percentages and chargeability indicators |
| Project Overview | All projects with cost, person days, and status badges |
| Peak Times | Bar chart showing booked hours vs. capacity over time, with department breakdown |
| Demand View | Staffing demand vs. supply by project, with unfilled headcount tracking |
| Chargeability Overview | Leaderboard of resources ranked by chargeability score |
| Budget Forecast | Budget burn rate and projected cost per active project |
| Skill Gap Analysis | Top skill shortages comparing open demand against available supply |
| Project Health | Composite health score per project (budget, staffing, timeline) |
Widgets are resizable, and the layout persists per user. An Add Widget catalog lets users browse available widgets with descriptions and default sizes.
Estimating System
A full project estimation workflow:
- Estimate Workspaces -- create, version, and compare estimates with full CRUD
- Scope Items -- break down deliverables into line items with assumptions and constraints
- Demand Lines -- define required roles, hours, and rates per scope item
- Rate Cards -- client-specific rate cards with experience multipliers and shoring ratios (onshore/nearshore/offshore)
- Version Control -- save snapshots, compare versions side-by-side, and track what changed
- Approval Workflow -- submit estimates for approval; approved versions can be handed off to create actual project allocations
- Planning Handoff -- one-click conversion from approved estimate to live project allocations with resource assignment
Staffing & Demand Management
- Open Demand Tracking -- projects can declare required roles and headcount; unfilled positions show as dashed bars on the timeline
- AI-Assisted Matching -- when filling demand, the system suggests best-fit resources based on skills, availability, cost, and location
- Skill Gap Analysis -- dashboard widget comparing aggregate demand against available supply, highlighting bottleneck roles
- Demand-to-Assignment -- convert demand entries into confirmed allocations with a guided workflow
Scenario Planning
- What-If Scenarios -- create sandbox copies of the current allocation state
- Simulation -- add, move, or remove allocations in the scenario without affecting production data
- Baseline Comparison -- see what changed between the scenario and the current baseline
- Apply or Discard -- promote a scenario to production or delete it
Admin & Configuration
- Client Hierarchy -- nested client/chapter/sub-chapter tree with drag-and-drop reordering; clients scope chargeability and project assignment
- Blueprints -- define custom field schemas (text, number, select, date, etc.) that attach to projects or resources; field values are validated, searchable, and filterable
- Roles & Management Levels -- hierarchical role tree with cost rates; management levels for organizational reporting
- Rate Cards -- global and per-client rate tables with currency support
- Vacations & Holidays -- manage public holiday calendars per country/state/city; approve/reject leave requests; import calendars from external sources
- Calculation Rules -- configure SAH parameters, chargeability targets, and deduction policies
- Users & Auth -- invite users by email, Argon2 password hashing, optional TOTP two-factor authentication, role-based access control (Admin, Manager, Viewer, User)
- Settings -- SMTP configuration (also configurable via env vars), notification preferences, accent color theme
- Broadcasts -- send system-wide announcements to all users
- Webhooks -- configure outgoing webhook notifications for key events
- Activity Log -- audit trail of significant actions across the system
Real-Time Collaboration
- Server-Sent Events (SSE) -- allocation changes, project updates, and notifications are pushed to all connected clients in real time via Redis pub/sub
- Notification Center -- in-app notification bell with unread count, grouped by category, with click-to-navigate
- Optimistic Updates -- UI reflects changes immediately while the server confirms in the background
Theming
- Dark Mode -- full dark theme with CSS variable-based surface system; all components adapt automatically
- Accent Colors -- choose from multiple accent color presets (Sky, Indigo, Emerald, Rose, Amber, Violet) that flow through the entire UI: buttons, links, timeline highlights, charts, and badges
- Responsive Layout -- collapsible sidebar, adaptive grid layouts, mobile-aware touch interactions
Tech Stack
| Layer | Technology | Purpose |
|---|---|---|
| Frontend | Next.js 15 (App Router), React 19 | Server components, streaming, file-based routing |
| Styling | Tailwind CSS v4 | Utility-first CSS with custom design tokens |
| API | tRPC v11 | End-to-end type-safe RPC between client and server |
| Database | PostgreSQL 16 via Prisma ORM | Relational data with JSONB for dynamic fields |
| Auth | Auth.js v5 | Session management, Argon2 passwords, TOTP MFA |
| Realtime | SSE + Redis pub/sub | Live updates without WebSocket complexity |
| AI | Azure OpenAI / Gemini | Staffing suggestions, skill profile generation |
| Monorepo | pnpm workspaces + Turborepo | Incremental builds, shared configs, dependency isolation |
| Testing | Vitest + Playwright | Unit tests (engine, shared) and E2E browser tests |
| Containerization | Docker Compose | Dev and production stacks with health checks |
Monorepo Structure
capakraken/
|
+-- apps/
| +-- web/ Next.js 15 application (frontend + API routes)
| +-- src/
| +-- app/ App Router pages and layouts
| +-- components/ React components organized by domain
| +-- hooks/ Custom React hooks
| +-- lib/ Client utilities, formatters, constants
| +-- server/ Server-side auth, tRPC context
|
+-- packages/
| +-- shared/ Types, Zod schemas, constants (zero dependencies)
| +-- db/ Prisma schema, migrations, seed scripts
| +-- engine/ Pure calculation logic (SAH, chargeability, budget, allocation)
| +-- staffing/ AI-assisted staffing, capacity analysis, profile matching
| +-- application/ Use-case orchestration layer (business workflows)
| +-- api/ tRPC routers, procedures, middleware
| +-- ui/ Shared UI component library (planned)
|
+-- tooling/
| +-- docker/ Container entrypoint scripts
| +-- deploy/ Production deployment automation
| +-- eslint/ Shared ESLint configuration
| +-- typescript/ Shared tsconfig bases
|
+-- scripts/ Lifecycle scripts (start, stop, DB management)
+-- docs/ Product docs, architecture decisions, screenshots
Architecture
+---------------------------------------------------------------+
| Browser (React 19) |
| Dashboard | Timeline | Allocations | Chargeability |
+------+-----+-----+------+-------+-------+--------+-----------+
| | | |
| tRPC (type-safe RPC over HTTP) |
| | | |
+------+-----------+---------------+----------------+-----------+
| Next.js 15 App Router |
| (Server Components + API Routes) |
+------+-----+-----+------+-------+-------+--------+-----------+
| | | |
+------+-----------+---------------+----------------+-----------+
| packages/api (tRPC v11) |
| allocation.* | project.* | chargeability.* | estimate.*|
+------+-----+---+-----+------+-------+-----------+-----------+
| | | |
+------+-----------+-------+ +----+----------------+-----------+
| packages/application | | packages/engine |
| (use-case orchestration) | | (pure calculations, no I/O) |
| - estimate workflows | | - SAH calculator |
| - dashboard aggregation | | - chargeability engine |
| - staffing use-cases | | - budget monitor |
+------+-------------------+ | - allocation calculator |
| +----+----------------------------+
| |
+------+---------------------------+----------------------------+
| packages/db (Prisma ORM) |
| schema.prisma | migrations | seed | queries |
+------+-------------------------------------------------------+
|
+------+-------------------------------------------------------+
| PostgreSQL 16 + Redis 7 |
+---------------------------------------------------------------+
Getting Started
Prerequisites
| Requirement | Minimum Version | Check |
|---|---|---|
| Node.js | 20.x | node --version |
| pnpm | 9.x | pnpm --version |
| Docker | 24+ | docker --version |
| Docker Compose | v2 | docker compose version |
1. Clone and configure
git clone https://gitea.hartmut-noerenberg.com/Hartmut/plANARCHY.git capakraken
cd capakraken
Create your environment file:
cp .env.example .env
Edit .env and fill in the required values:
# Required -- generate with: openssl rand -base64 32
NEXTAUTH_SECRET=<your-generated-secret>
# Required -- your app URL
NEXTAUTH_URL=http://localhost:3100
# Required for the pgAdmin web UI
PGADMIN_PASSWORD=admin
Note: The database connection (
DATABASE_URL), Redis, and SMTP (MailHog) are pre-configured for Docker Compose and work out of the box. See.env.examplefor the full reference with all optional variables.
2. Start with Docker (recommended)
bash scripts/start.sh
This single command will:
- Pull and start PostgreSQL 16 and Redis 7 containers
- Build the application Docker image (first run: ~2 minutes)
- Run Prisma migrations automatically against the database
- Validate workspace exports and imports
- Start the Next.js dev server with hot reload on port 3100
You'll see output like:
Starting CapaKraken...
Starting PostgreSQL + Redis...
Waiting for PostgreSQL...
Starting app container on port 3100...
Waiting for server (up to 90s)...
CapaKraken is running!
{
"status": "ok",
"database": "connected",
"redis": "connected"
}
URL: http://localhost:3100
3. Start without Docker (host-native)
If you prefer running Node.js directly on your machine:
# Install all workspace dependencies
pnpm install
# Start only the infrastructure via Docker
docker compose up -d postgres redis
# Generate the Prisma client and apply migrations
pnpm db:generate
pnpm db:migrate
# Start the Next.js dev server with hot reload
pnpm dev
4. Create your first user
- Open http://localhost:3100 in your browser
- Click Sign up on the login page
- Enter your name, email, and password
- The first registered user is automatically granted Admin privileges
- Explore the sidebar to discover all features
5. Load demo data (optional)
pnpm db:seed
This populates the database with sample clients, projects, resources, allocations, and roles so you can immediately explore all features without manual setup.
Available Services
When running with Docker Compose, the following services are available:
| Service | URL | Purpose |
|---|---|---|
| CapaKraken App | localhost:3100 | Main application |
| MailHog | localhost:8025 | Email testing UI -- catches all outgoing emails (invitations, password resets, notifications) |
| pgAdmin | localhost:5050 | Visual database administration |
| PostgreSQL | localhost:5433 |
Direct database access (user: capakraken, db: capakraken) |
| Redis | localhost:6380 |
Cache, rate limiting, and SSE pub/sub |
Scripts Reference
Application Lifecycle
| Command | Description |
|---|---|
bash scripts/start.sh |
Start all services (PostgreSQL, Redis, app) |
bash scripts/stop.sh |
Stop all services gracefully |
bash scripts/restart.sh |
Full stop + start cycle |
Development
| Command | Description |
|---|---|
pnpm dev |
Start Next.js dev server with hot reload (host-native) |
pnpm build |
Production build (standalone output) |
pnpm lint |
Run ESLint across all packages |
pnpm format |
Format all files with Prettier |
pnpm test:unit |
Run unit tests via Vitest |
pnpm test:e2e |
Run end-to-end tests via Playwright |
pnpm typecheck |
TypeScript type checking across all packages |
pnpm check:architecture |
Verify architecture guardrails (import boundaries, etc.) |
Database
| Command | Description |
|---|---|
pnpm db:generate |
Regenerate Prisma client after schema changes |
pnpm db:migrate |
Create and apply new migrations |
pnpm db:push |
Push schema changes directly (no migration file) |
pnpm db:studio |
Open Prisma Studio (visual data browser) |
pnpm db:seed |
Seed the database with demo data |
pnpm db:doctor |
Run health checks on database state |
pnpm db:seed:export |
Export current DB state as a seed file |
pnpm db:seed:import |
Import a previously exported seed file |
Production Deployment
CapaKraken ships with a production-ready Docker Compose stack and deployment automation.
Quick Deploy
# Configure required secrets
export APP_IMAGE=ghcr.io/your-org/capakraken-app:latest
export MIGRATOR_IMAGE=ghcr.io/your-org/capakraken-migrator:latest
export POSTGRES_PASSWORD=$(openssl rand -hex 32)
export REDIS_PASSWORD=$(openssl rand -hex 32)
export NEXTAUTH_SECRET=$(openssl rand -base64 32)
# Deploy with readiness verification
bash tooling/deploy/deploy-compose.sh production
Production Stack Features
- Multi-stage Docker build -- optimized standalone Next.js output (~150 MB image)
- Sidecar migrator -- runs Prisma migrations before the app starts, then exits
- Redis authentication -- password-protected with
--requirepass - Health probes --
/api/health(liveness) and/api/ready(readiness with DB + Redis checks) - Automatic rollback -- deployment script verifies readiness; on failure, logs are captured for debugging
- Environment separation -- configure via
.env.productionanddeploy.envfiles - Container registry -- configurable via
DOCKER_REGISTRY(defaults toghcr.io)
Environment Variables
See .env.example for the complete reference with inline documentation. Summary of key variables:
| Variable | Required | Default | Description |
|---|---|---|---|
NEXTAUTH_URL |
Yes | -- | Public URL of the application |
NEXTAUTH_SECRET |
Yes | -- | Secret for JWT signing and session encryption |
DATABASE_URL |
Yes | localhost:5433 |
PostgreSQL connection string |
REDIS_PASSWORD |
Prod | -- | Redis authentication password |
REDIS_URL |
No | redis://redis:6379 |
Redis connection (auto-configured in Docker) |
SMTP_HOST |
No | -- | SMTP server for email delivery |
SMTP_PORT |
No | 587 |
SMTP port |
SMTP_FROM |
No | noreply@capakraken.dev |
Sender address for outgoing emails |
AZURE_OPENAI_API_KEY |
No | -- | Enables AI-assisted staffing features |
GEMINI_API_KEY |
No | -- | Alternative AI provider |
LOG_LEVEL |
No | info |
Logging verbosity (trace/debug/info/warn/error) |
CRON_SECRET |
No | -- | Authenticates scheduled job endpoints |
Design Principles
| Principle | Implementation |
|---|---|
| Money as integer cents | All monetary values stored and calculated in cents to eliminate floating-point drift |
| Strict TypeScript | No any types, strict null checks, explicit Prisma casts at package boundaries |
| Domain-driven packages | Each bounded context (estimating, chargeability, staffing) lives in its own package with clear exports |
| Pure engine logic | Calculation packages have zero I/O dependencies -- they take data in and return results |
| Real-time by default | SSE pushes changes to all clients via Redis pub/sub; no polling |
| Theme-aware UI | CSS variable-based surface system with configurable accent colors and full dark mode |
| Defensive data handling | Nullable foreign keys handled explicitly; Prisma enums and JSONB cast at boundaries |
| No speculative abstractions | Build what's needed now; three similar lines beat a premature abstraction |
Contributing
- Create a feature branch from
main - Follow the existing code style -- ESLint and Prettier enforce it automatically
- Add unit tests for new business logic, especially in
packages/engine - Run quality gates before submitting:
pnpm test:unit pnpm --filter @capakraken/web exec tsc --noEmit pnpm lint pnpm check:architecture - Keep commits focused with descriptive messages
- Open a pull request with a clear description of what changed and why
License
Proprietary. All rights reserved.
Built with TypeScript, Next.js, and a lot of coffee.






