kimai-plugin-heatmap/CLAUDE.md

134 lines
8.2 KiB
Markdown

<!-- GSD:project-start source:PROJECT.md -->
## Project
**Kimai Heatmap Plugin**
A Kimai dashboard widget that displays a GitHub-style activity heatmap visualizing time tracking data. Built as a Symfony bundle plugin for personal time tracking use, rendering an interactive d3.js calendar heatmap on the Kimai dashboard.
**Core Value:** At a glance, see where your time went — a visual map of tracking activity that makes patterns obvious without clicking through reports.
### Constraints
- **Tech stack**: Symfony bundle (PHP) + d3.js (JavaScript), must conform to Kimai plugin architecture
- **Testing**: TDD approach — PHPUnit for backend, JS tests for frontend heatmap
- **Dev environment**: Nix flake/devshell with local Kimai and seeded DB for manual testing
- **Compatibility**: Must work with current Kimai release
<!-- GSD:project-end -->
<!-- GSD:stack-start source:research/STACK.md -->
## Technology Stack
## Recommended Stack
### Core Framework (Kimai Plugin)
| Technology | Version | Purpose | Why | Confidence |
|------------|---------|---------|-----|------------|
| PHP | 8.2+ | Plugin runtime | Kimai 2.x requires PHP 8.1 minimum; 8.2 for current features and performance. Verify against Kimai's composer.json. | MEDIUM |
| Symfony | 6.4 LTS | Bundle framework | Kimai 2.x is built on Symfony 6.4 LTS. Plugins must match the host Symfony version exactly. | MEDIUM |
| Kimai | 2.x (latest) | Host application | Target the current stable release. Check github.com/kimai/kimai/releases before starting. | MEDIUM |
### Visualization
| Technology | Version | Purpose | Why | Confidence |
|------------|---------|---------|-----|------------|
| d3 | ^7.9 | Core visualization library | d3 v7 is the current stable. ESM-native, tree-shakeable. Use specific sub-modules, not the full bundle. | HIGH |
| d3-scale | ^4.0 | Color and position scales | Needed for mapping hours/counts to color intensities and day positions. | HIGH |
| d3-selection | ^3.0 | DOM manipulation | Core d3 pattern for binidng data to SVG elements. | HIGH |
| d3-time | ^3.1 | Date calculations | Week/day grid layout calculations for the calendar. | HIGH |
| d3-time-format | ^4.1 | Date formatting | Tooltip and axis labels. | HIGH |
| d3-scale-chromatic | ^3.1 | Color schemes | Provides sequential color scales (Greens, Blues) as starting points before mapping to Kimai theme vars. | HIGH |
| d3-shape | ^3.2 | Rect generation | For the heatmap cell rectangles. | HIGH |
- `cal-heatmap` or other d3-wrapper heatmap libraries: They add abstraction over d3 that limits customization (Kimai theme integration, click-to-navigate, toggle modes). Rolling your own with raw d3 modules is straightforward for a calendar heatmap and gives full control.
- `d3` full bundle import: Import only the sub-modules you need. Keeps the asset small and avoids polluting the Kimai frontend.
### Testing
| Technology | Version | Purpose | Why | Confidence |
|------------|---------|---------|-----|------------|
| PHPUnit | ^10.5 or ^11.0 | Backend tests | Kimai uses PHPUnit for its own tests. Match the version Kimai ships with in its dev dependencies. | MEDIUM |
| Vitest | ^3.0 | JS heatmap tests | Fast, ESM-native, works with d3's ESM modules out of the box. Jest struggles with ESM d3 imports without transformation config. | HIGH |
| jsdom | (via vitest) | DOM environment | Vitest's jsdom environment provides enough DOM for d3 selection/rendering tests without a browser. | HIGH |
- `Jest` for JS tests: d3 v7 is ESM-only. Jest's ESM support requires `--experimental-vm-modules` and transform config. Vitest handles ESM natively.
- `Cypress`/`Playwright` for the heatmap: Overkill for a single widget. SVG output assertions via jsdom + snapshot testing covers the rendering. Save E2E for integration testing against a running Kimai instance if needed later.
### Development Environment
| Technology | Version | Purpose | Why | Confidence |
|------------|---------|---------|-----|------------|
| Nix flake | - | Reproducible dev env | Matches Toph's NixOS infra. Provides PHP, Node, Composer, and a local Kimai instance. | HIGH |
| Composer | ^2.7 | PHP dependency management | Standard for Symfony/Kimai. | HIGH |
| npm | ^10.x | JS dependency management | For d3 modules and Vitest. Simpler than yarn/pnpm for a single-widget plugin. | HIGH |
| esbuild | ^0.24 | JS bundling | Bundle d3 modules into a single file for Kimai's asset pipeline. Faster than webpack, simpler config, handles ESM natively. | HIGH |
- `Webpack Encore`: Kimai's own frontend uses it, but for a plugin shipping a single JS file, esbuild is simpler. One build command, no Symfony Encore config to maintain.
- `Docker` for dev: The project spec calls for Nix flake. Docker would work but adds friction on NixOS and doesn't match the user's infrastructure.
### Database
## Kimai Plugin Structure
### Directory Layout
### Bundle Registration
### Dashboard Widget Registration
### Twig Template Pattern
## Alternatives Considered
| Category | Recommended | Alternative | Why Not |
|----------|-------------|-------------|---------|
| JS Visualization | d3 sub-modules | cal-heatmap | Limits customization for Kimai theme integration, click navigation, and mode toggling |
| JS Visualization | d3 sub-modules | Chart.js matrix | Less control over calendar layout, weaker SVG customization |
| JS Bundler | esbuild | Webpack Encore | Overkill for bundling a single widget's JS. Encore adds Symfony config overhead. |
| JS Testing | Vitest | Jest | d3 v7 is ESM-only; Jest's ESM support requires workarounds |
| JS Language | TypeScript | Plain JS | Type safety for the d3 code, catches data shape mismatches at build time |
| PHP Testing | PHPUnit | Pest | Kimai's own tests use PHPUnit. Consistency with the host app matters. |
| Dev Env | Nix flake | Docker Compose | User runs NixOS; Nix is native. Docker adds a layer. |
## TypeScript for d3
## Installation Commands
# PHP dependencies (in the plugin directory)
# No extra PHP packages needed beyond Kimai's own dependencies
# JS dependencies
## Nix Flake Approach
## Key Version Verification Checklist
- [ ] Kimai latest stable version (check GitHub releases)
- [ ] Kimai's required PHP version (check `composer.json`)
- [ ] Kimai's Symfony version (check `composer.lock`)
- [ ] Kimai's `WidgetInterface` API (check `src/Widget/` in Kimai source)
- [ ] Kimai's Twig widget template blocks (check existing dashboard widgets in Kimai source)
- [ ] Kimai's asset serving mechanism for plugins (may use Symfony AssetMapper now instead of Encore)
- [ ] d3 v7 latest patch version on npm
## Sources
- Kimai plugin documentation: https://www.kimai.org/documentation/plugin-development.html
- Kimai GitHub: https://github.com/kimai/kimai
- d3.js documentation: https://d3js.org/
- d3 calendar heatmap examples: https://observablehq.com/@d3/calendar
- Vitest documentation: https://vitest.dev/
- esbuild documentation: https://esbuild.github.io/
<!-- GSD:stack-end -->
<!-- GSD:conventions-start source:CONVENTIONS.md -->
## Conventions
Conventions not yet established. Will populate as patterns emerge during development.
<!-- GSD:conventions-end -->
<!-- GSD:architecture-start source:ARCHITECTURE.md -->
## Architecture
Architecture not yet mapped. Follow existing patterns found in the codebase.
<!-- GSD:architecture-end -->
<!-- GSD:skills-start source:skills/ -->
## Project Skills
No project skills found. Add skills to any of: `.claude/skills/`, `.agents/skills/`, `.cursor/skills/`, or `.github/skills/` with a `SKILL.md` index file.
<!-- GSD:skills-end -->
<!-- GSD:workflow-start source:GSD defaults -->
## GSD Workflow Enforcement
Before using Edit, Write, or other file-changing tools, start work through a GSD command so planning artifacts and execution context stay in sync.
Use these entry points:
- `/gsd-quick` for small fixes, doc updates, and ad-hoc tasks
- `/gsd-debug` for investigation and bug fixing
- `/gsd-execute-phase` for planned phase work
Do not make direct repo edits outside a GSD workflow unless the user explicitly asks to bypass it.
<!-- GSD:workflow-end -->
<!-- GSD:profile-start -->
## Developer Profile
> Profile not yet configured. Run `/gsd-profile-user` to generate your developer profile.
> This section is managed by `generate-claude-profile` -- do not edit manually.
<!-- GSD:profile-end -->