feat: Add GlowTrack mood and habit wellbeing grid specifications
- Introduced export schema for JSON data structure. - Created renderer contract detailing canvas/SVG rendering requirements. - Defined IndexedDB storage schema and migration strategies. - Documented data model including entities and relationships. - Developed implementation plan outlining execution flow and project structure. - Provided quickstart guide for development environment setup. - Compiled research documentation on performance, accessibility, and theming. - Established feature specification with user scenarios and functional requirements.
This commit is contained in:
75
specs/001-glowtrack-a-mood/contracts/export.schema.json
Normal file
75
specs/001-glowtrack-a-mood/contracts/export.schema.json
Normal file
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "https://glowtrack.app/schema/export.json",
|
||||
"title": "GlowTrack Export",
|
||||
"type": "object",
|
||||
"required": ["version", "app", "exportedAt", "data"],
|
||||
"properties": {
|
||||
"version": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$" },
|
||||
"app": {
|
||||
"type": "object",
|
||||
"required": ["name", "version"],
|
||||
"properties": {
|
||||
"name": { "const": "GlowTrack" },
|
||||
"version": { "type": "string" }
|
||||
}
|
||||
},
|
||||
"exportedAt": { "type": "string", "format": "date-time" },
|
||||
"data": {
|
||||
"type": "object",
|
||||
"required": ["settings", "habits", "days"],
|
||||
"properties": {
|
||||
"settings": { "type": "object" },
|
||||
"habits": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["id", "type", "label", "defaultWeight", "archived"],
|
||||
"properties": {
|
||||
"id": { "type": "string" },
|
||||
"type": { "enum": ["positive", "negative"] },
|
||||
"label": { "type": "string" },
|
||||
"icon": { "type": ["string", "null"] },
|
||||
"defaultWeight": { "type": "number", "minimum": 0 },
|
||||
"archived": { "type": "boolean" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"days": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["date", "mood", "entries"],
|
||||
"properties": {
|
||||
"date": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$" },
|
||||
"mood": {
|
||||
"type": "object",
|
||||
"required": ["hue", "intensity"],
|
||||
"properties": {
|
||||
"hue": { "type": "number", "minimum": 0, "maximum": 360 },
|
||||
"intensity": { "type": "number", "minimum": 0, "maximum": 1 },
|
||||
"note": { "type": ["string", "null"] }
|
||||
}
|
||||
},
|
||||
"entries": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["id", "type", "habitId", "label", "weight", "timestamp"],
|
||||
"properties": {
|
||||
"id": { "type": "string" },
|
||||
"type": { "enum": ["positive", "negative"] },
|
||||
"habitId": { "type": "string" },
|
||||
"label": { "type": "string" },
|
||||
"weight": { "type": "number", "minimum": 0 },
|
||||
"timestamp": { "type": "string", "format": "date-time" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
31
specs/001-glowtrack-a-mood/contracts/renderer.md
Normal file
31
specs/001-glowtrack-a-mood/contracts/renderer.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Renderer Contract — Canvas/SVG
|
||||
|
||||
## Purpose
|
||||
Render a grid of DayTiles with mood hue, glow intensity from net habit score, negative overlay static, and glyph counts.
|
||||
|
||||
## Inputs
|
||||
- containerSize: { width: px, height: px, devicePixelRatio }
|
||||
- days: DayTile[] (ordered by date)
|
||||
- theme: palette + CSS variables
|
||||
- options:
|
||||
- showLegend: boolean
|
||||
- pngScale: number (for export)
|
||||
|
||||
## Outputs
|
||||
- On-screen render at 60 fps target
|
||||
- Exported PNG at screen resolution (pngScale defaults to 1.0)
|
||||
|
||||
## Rules
|
||||
- Base hue from mood.hue; luminance curve f(netScore) with easing and clamping
|
||||
- Negative entries: apply subtle static texture overlay (non-hue-altering)
|
||||
- Glyphs: ticks = count(positive), dots = count(negative)
|
||||
- No hue change from overlays; only luminance/texture affected
|
||||
|
||||
## Performance
|
||||
- Batch draw tiles; minimize layout/paint; avoid per-frame allocations
|
||||
- Prefer Canvas for tiles; SVG for glyph overlays and interactive focus rings
|
||||
- Ensure keyboard focus indicators meet WCAG AA contrast
|
||||
|
||||
## Accessibility
|
||||
- Keyboard navigable tiles (tab/arrow); ARIA labels describing day, mood, counts
|
||||
- High-contrast theme variant; color-blind palettes via CSS variables
|
||||
34
specs/001-glowtrack-a-mood/contracts/storage.schema.md
Normal file
34
specs/001-glowtrack-a-mood/contracts/storage.schema.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Storage Schema — IndexedDB (idb)
|
||||
|
||||
## DB Name
|
||||
- glowtrack
|
||||
|
||||
## Versioning
|
||||
- Start at version 1; bump on schema changes
|
||||
- Provide forward-only migrations for v1 → v2 → ...
|
||||
|
||||
## Object Stores
|
||||
- settings (key: 'singleton')
|
||||
- value: GridSettings
|
||||
- habits (keyPath: 'id')
|
||||
- indexes: by_type (type)
|
||||
- days (keyPath: 'date')
|
||||
- value: DayTile without entries
|
||||
- entries (keyPath: 'id')
|
||||
- indexes:
|
||||
- by_date (date)
|
||||
- by_habit (habitId)
|
||||
|
||||
## Transactions
|
||||
- Log habit: readwrite on entries, days (update netScore)
|
||||
- Edit/delete: readwrite on entries, days
|
||||
- Import JSON: version check, bulk put within a single transaction per store
|
||||
|
||||
## Migrations
|
||||
- v1: create stores and indexes above
|
||||
- Future: add derived caches (e.g., monthly aggregates) — must be rebuildable
|
||||
|
||||
## Data Integrity
|
||||
- Enforce unique DayTile.date
|
||||
- Recompute DayTile.netScore after entry mutations
|
||||
- Maintain referential link of HabitEntry.habitId to habits store
|
||||
79
specs/001-glowtrack-a-mood/data-model.md
Normal file
79
specs/001-glowtrack-a-mood/data-model.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# Data Model — GlowTrack
|
||||
|
||||
## Entities
|
||||
|
||||
### WellbeingGrid
|
||||
- id: string (stable UUID)
|
||||
- createdAt: ISO datetime
|
||||
- updatedAt: ISO datetime
|
||||
- settings: GridSettings
|
||||
- days: DayTile[]
|
||||
|
||||
### GridSettings
|
||||
- startDate: ISO date
|
||||
- endDate: ISO date
|
||||
- theme: string (palette id)
|
||||
- colorBlindMode: 'none' | 'protanopia' | 'deuteranopia' | 'tritanopia'
|
||||
- export: ExportSettings
|
||||
|
||||
### ExportSettings
|
||||
- pngScale: number (1.0 = screen resolution)
|
||||
- includeLegend: boolean
|
||||
|
||||
### DayTile
|
||||
- date: ISO date (YYYY-MM-DD)
|
||||
- mood: Mood
|
||||
- entries: HabitEntry[]
|
||||
- netScore: number (derived: sum(positive weights) - sum(negative weights))
|
||||
|
||||
### Mood
|
||||
- hue: number (0–360)
|
||||
- intensity: number (0–1)
|
||||
- note?: string
|
||||
|
||||
### HabitEntry
|
||||
- id: string (UUID)
|
||||
- type: 'positive' | 'negative'
|
||||
- habitId: string
|
||||
- label: string
|
||||
- weight: number (default 1; negative weights discouraged — use type)
|
||||
- timestamp: ISO datetime
|
||||
|
||||
### HabitDefinition
|
||||
- id: string (UUID)
|
||||
- type: 'positive' | 'negative'
|
||||
- label: string
|
||||
- icon?: string (for UI glyphs)
|
||||
- defaultWeight: number (default 1)
|
||||
- archived: boolean
|
||||
|
||||
## Relationships
|
||||
- WellbeingGrid has many DayTile
|
||||
- DayTile has many HabitEntry
|
||||
- HabitEntry references HabitDefinition via habitId
|
||||
|
||||
## Derived/Display Rules
|
||||
- Base hue = mood.hue
|
||||
- Glow luminance = function(netScore) with gentle easing; clamp to range
|
||||
- Negative entries add subtle static texture overlay
|
||||
- Glyphs: ticks for positive count; dots for negative count
|
||||
|
||||
## Validation Rules
|
||||
- Dates must be valid ISO; no duplicates for DayTile.date
|
||||
- HabitEntry.weight > 0; type determines sign for net score
|
||||
- netScore recomputed on add/update/delete of entries
|
||||
- Schema version must be present in exported JSON
|
||||
|
||||
## JSON Export Structure (high level)
|
||||
- version: string (semver)
|
||||
- app: { name: 'GlowTrack', version: string }
|
||||
- exportedAt: ISO datetime
|
||||
- data: { settings, habits: HabitDefinition[], days: DayTile[] }
|
||||
|
||||
## IndexedDB Stores (overview)
|
||||
- stores:
|
||||
- settings (key: 'singleton')
|
||||
- habits (key: id)
|
||||
- days (key: date)
|
||||
- entries (key: id, index: date, index: habitId)
|
||||
- versioning: bump on schema change; write migrations per version
|
||||
195
specs/001-glowtrack-a-mood/plan.md
Normal file
195
specs/001-glowtrack-a-mood/plan.md
Normal file
@@ -0,0 +1,195 @@
|
||||
|
||||
# Implementation Plan: GlowTrack — Mood & Habit Wellbeing Grid
|
||||
|
||||
**Branch**: `001-glowtrack-a-mood` | **Date**: 18 September 2025 | **Spec**: `/home/jawz/Development/Projects/GlowTrack/specs/001-glowtrack-a-mood/spec.md`
|
||||
**Input**: Feature specification from `/home/jawz/Development/Projects/GlowTrack/specs/001-glowtrack-a-mood/spec.md`
|
||||
|
||||
## Execution Flow (/plan command scope)
|
||||
```
|
||||
1. Load feature spec from Input path
|
||||
→ If not found: ERROR "No feature spec at {path}"
|
||||
2. Fill Technical Context (scan for NEEDS CLARIFICATION)
|
||||
→ Detect Project Type from context (web=frontend+backend, mobile=app+api)
|
||||
→ Set Structure Decision based on project type
|
||||
3. Fill the Constitution Check section based on the content of the constitution document.
|
||||
4. Evaluate Constitution Check section below
|
||||
→ If violations exist: Document in Complexity Tracking
|
||||
→ If no justification possible: ERROR "Simplify approach first"
|
||||
→ Update Progress Tracking: Initial Constitution Check
|
||||
5. Execute Phase 0 → research.md
|
||||
→ If NEEDS CLARIFICATION remain: ERROR "Resolve unknowns"
|
||||
6. Execute Phase 1 → contracts, data-model.md, quickstart.md, agent-specific template file (e.g., `CLAUDE.md` for Claude Code, `.github/copilot-instructions.md` for GitHub Copilot, `GEMINI.md` for Gemini CLI, `QWEN.md` for Qwen Code or `AGENTS.md` for opencode).
|
||||
7. Re-evaluate Constitution Check section
|
||||
→ If new violations: Refactor design, return to Phase 1
|
||||
→ Update Progress Tracking: Post-Design Constitution Check
|
||||
8. Plan Phase 2 → Describe task generation approach (DO NOT create tasks.md)
|
||||
9. STOP - Ready for /tasks command
|
||||
```
|
||||
|
||||
**IMPORTANT**: The /plan command STOPS at step 7. Phases 2-4 are executed by other commands:
|
||||
- Phase 2: /tasks command creates tasks.md
|
||||
- Phase 3-4: Implementation execution (manual or via tools)
|
||||
|
||||
## Summary
|
||||
GlowTrack is a browser-first PWA that turns daily mood and habit inputs into a vibrant, artistic wellbeing grid. Each day is a tile whose mood defines base hue; positive habits increase glow, negative habits reduce it and add a subtle static overlay, with glyphs indicating counts. The app is offline-first, private (no accounts, no servers), and supports PNG export of the grid and JSON import/export for full data portability.
|
||||
|
||||
Technical approach: SvelteKit + TypeScript using `@sveltejs/adapter-static` (no backend). Local-first storage with IndexedDB via `idb`. Grid visualization via a lightweight Canvas/SVG renderer tuned for mobile. Styling with Tailwind CSS and CSS variables for theming (including color-blind modes). PWA with SvelteKit service worker and minimal runtime cache. Tooling and reproducible builds via Nix flakes (devShell and build). CI executes Nix builds, Vitest unit tests, and Playwright smoke tests.
|
||||
|
||||
## Technical Context
|
||||
**Language/Version**: TypeScript (ES2022), SvelteKit
|
||||
**Primary Dependencies**: SvelteKit, `@sveltejs/adapter-static`, `idb`, Tailwind CSS, `@tailwindcss/forms`, Vite, `svelte-check`, ESLint, Prettier
|
||||
**Storage**: IndexedDB via `idb` with versioned schema; JSON import/export
|
||||
**Testing**: Vitest (unit), Playwright (e2e smoke), svelte-check (types)
|
||||
**Target Platform**: Modern browsers (mobile and desktop) as a PWA, offline-capable
|
||||
**Project Type**: Web (frontend-only PWA)
|
||||
**Performance Goals**: 60 fps interactions and animations on mid-range mobile; initial interactive < 2s on 3G-like; maintain smooth canvas/SVG rendering for up to 365 tiles
|
||||
**Constraints**: No servers or accounts; full offline read/write; local-only data; small bundle; accessible (WCAG AA); keyboard-first interactions
|
||||
**Scale/Scope**: Single-user, local dataset (1–3 years of daily entries, dozens of habits)
|
||||
|
||||
## Constitution Check
|
||||
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
||||
|
||||
The constitution file contains placeholders and no explicit project principles. Adopt default gates aligned with simplicity and test-first intent:
|
||||
- Tests-first mindset captured in plan (Vitest/Playwright before features land)
|
||||
- Simplicity: no backend, minimal dependencies, static hosting
|
||||
- Observability via simple structured logs in dev and explicit export/import contracts
|
||||
|
||||
Initial Constitution Check: PASS (no violations detected)
|
||||
|
||||
## Project Structure
|
||||
|
||||
### Documentation (this feature)
|
||||
```
|
||||
specs/[###-feature]/
|
||||
├── plan.md # This file (/plan command output)
|
||||
├── research.md # Phase 0 output (/plan command)
|
||||
├── data-model.md # Phase 1 output (/plan command)
|
||||
├── quickstart.md # Phase 1 output (/plan command)
|
||||
├── contracts/ # Phase 1 output (/plan command)
|
||||
└── tasks.md # Phase 2 output (/tasks command - NOT created by /plan)
|
||||
```
|
||||
|
||||
### Source Code (repository root)
|
||||
```
|
||||
apps/
|
||||
└── web/ # SvelteKit PWA (UI & routes)
|
||||
|
||||
packages/
|
||||
├── viz/ # Tile/grid renderer (Canvas/SVG)
|
||||
├── storage/ # IndexedDB schema, migrations, import/export
|
||||
└── theme/ # Palettes, CSS variables, color-blind modes
|
||||
|
||||
tools/
|
||||
└── ci/ # CI configs/scripts (Nix, Vitest, Playwright)
|
||||
```
|
||||
|
||||
**Structure Decision**: Custom web monorepo (frontend-only) with shared packages for viz, storage, and theme per requirements
|
||||
|
||||
## Phase 0: Outline & Research
|
||||
1. **Extract unknowns from Technical Context** above:
|
||||
- For each NEEDS CLARIFICATION → research task
|
||||
- For each dependency → best practices task
|
||||
- For each integration → patterns task
|
||||
|
||||
2. **Generate and dispatch research agents**:
|
||||
```
|
||||
For each unknown in Technical Context:
|
||||
Task: "Research {unknown} for {feature context}"
|
||||
For each technology choice:
|
||||
Task: "Find best practices for {tech} in {domain}"
|
||||
```
|
||||
|
||||
3. **Consolidate findings** in `research.md` using format:
|
||||
- Decision: [what was chosen]
|
||||
- Rationale: [why chosen]
|
||||
- Alternatives considered: [what else evaluated]
|
||||
|
||||
**Output**: research.md with all NEEDS CLARIFICATION resolved
|
||||
|
||||
## Phase 1: Design & Contracts
|
||||
*Prerequisites: research.md complete*
|
||||
|
||||
1. **Extract entities from feature spec** → `data-model.md`:
|
||||
- Entity name, fields, relationships
|
||||
- Validation rules from requirements
|
||||
- State transitions if applicable
|
||||
|
||||
2. **Generate API contracts** from functional requirements:
|
||||
- For each user action → endpoint
|
||||
- Use standard REST/GraphQL patterns
|
||||
- Output OpenAPI/GraphQL schema to `/contracts/`
|
||||
|
||||
3. **Generate contract tests** from contracts:
|
||||
- One test file per endpoint
|
||||
- Assert request/response schemas
|
||||
- Tests must fail (no implementation yet)
|
||||
|
||||
4. **Extract test scenarios** from user stories:
|
||||
- Each story → integration test scenario
|
||||
- Quickstart test = story validation steps
|
||||
|
||||
5. **Update agent file incrementally** (O(1) operation):
|
||||
- Run `.specify/scripts/bash/update-agent-context.sh copilot` for your AI assistant
|
||||
- If exists: Add only NEW tech from current plan
|
||||
- Preserve manual additions between markers
|
||||
- Update recent changes (keep last 3)
|
||||
- Keep under 150 lines for token efficiency
|
||||
- Output to repository root
|
||||
|
||||
**Output**: data-model.md, /contracts/*, quickstart.md, agent-specific file
|
||||
|
||||
## Phase 2: Task Planning Approach
|
||||
*This section describes what the /tasks command will do - DO NOT execute during /plan*
|
||||
|
||||
**Task Generation Strategy**:
|
||||
- Load `.specify/templates/tasks-template.md` as base
|
||||
- Generate tasks from Phase 1 design docs (contracts, data model, quickstart)
|
||||
- Each contract → contract test task [P]
|
||||
- Each entity → model creation task [P]
|
||||
- Each user story → integration test task
|
||||
- Implementation tasks to make tests pass
|
||||
|
||||
**Ordering Strategy**:
|
||||
- TDD order: Tests before implementation
|
||||
- Dependency order: Models before services before UI
|
||||
- Mark [P] for parallel execution (independent files)
|
||||
|
||||
**Estimated Output**: 25-30 numbered, ordered tasks in tasks.md
|
||||
|
||||
**IMPORTANT**: This phase is executed by the /tasks command, NOT by /plan
|
||||
|
||||
## Phase 3+: Future Implementation
|
||||
*These phases are beyond the scope of the /plan command*
|
||||
|
||||
**Phase 3**: Task execution (/tasks command creates tasks.md)
|
||||
**Phase 4**: Implementation (execute tasks.md following constitutional principles)
|
||||
**Phase 5**: Validation (run tests, execute quickstart.md, performance validation)
|
||||
|
||||
## Complexity Tracking
|
||||
*Fill ONLY if Constitution Check has violations that must be justified*
|
||||
|
||||
| Violation | Why Needed | Simpler Alternative Rejected Because |
|
||||
|-----------|------------|-------------------------------------|
|
||||
| [e.g., 4th project] | [current need] | [why 3 projects insufficient] |
|
||||
| [e.g., Repository pattern] | [specific problem] | [why direct DB access insufficient] |
|
||||
|
||||
|
||||
## Progress Tracking
|
||||
*This checklist is updated during execution flow*
|
||||
|
||||
**Phase Status**:
|
||||
- [x] Phase 0: Research complete (/plan command)
|
||||
- [x] Phase 1: Design complete (/plan command)
|
||||
- [ ] Phase 2: Task planning complete (/plan command - describe approach only)
|
||||
- [ ] Phase 3: Tasks generated (/tasks command)
|
||||
- [ ] Phase 4: Implementation complete
|
||||
- [ ] Phase 5: Validation passed
|
||||
|
||||
**Gate Status**:
|
||||
- [x] Initial Constitution Check: PASS
|
||||
- [x] Post-Design Constitution Check: PASS
|
||||
- [x] All NEEDS CLARIFICATION resolved
|
||||
- [ ] Complexity deviations documented
|
||||
|
||||
---
|
||||
*Based on Constitution v2.1.1 - See `/memory/constitution.md`*
|
||||
35
specs/001-glowtrack-a-mood/quickstart.md
Normal file
35
specs/001-glowtrack-a-mood/quickstart.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Quickstart — GlowTrack
|
||||
|
||||
## Prerequisites
|
||||
- Nix installed (flakes enabled)
|
||||
|
||||
## Dev Environment
|
||||
- Enter dev shell:
|
||||
- nix develop
|
||||
- Install JS deps (first time):
|
||||
- pnpm install
|
||||
- Run typecheck and lints:
|
||||
- pnpm run svelte-check
|
||||
- pnpm run lint
|
||||
|
||||
## Run App (dev)
|
||||
- Start web app:
|
||||
- pnpm run dev
|
||||
- Open in browser (URL printed by dev server)
|
||||
|
||||
## Build (static site)
|
||||
- Build via Nix flake:
|
||||
- nix build .#app
|
||||
- Or via pnpm:
|
||||
- pnpm run build
|
||||
|
||||
## Tests
|
||||
- Unit tests:
|
||||
- pnpm run test
|
||||
- E2E smoke (headed/CI):
|
||||
- pnpm run test:e2e
|
||||
|
||||
## Export/Import
|
||||
- Export JSON (in-app): Settings → Export → JSON
|
||||
- Import JSON: Settings → Import → select file
|
||||
- Export PNG: Share/Export → PNG (screen resolution)
|
||||
79
specs/001-glowtrack-a-mood/research.md
Normal file
79
specs/001-glowtrack-a-mood/research.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# Research — GlowTrack
|
||||
|
||||
## Decisions
|
||||
- Framework: SvelteKit + TypeScript with `@sveltejs/adapter-static` (no backend)
|
||||
- Storage: IndexedDB via `idb`; JSON import/export with versioning
|
||||
- Visualization: Lightweight Canvas/SVG hybrid renderer optimized for mobile
|
||||
- Styling: Tailwind CSS with CSS variables; color-blind friendly palettes
|
||||
- Accessibility: Target WCAG AA; keyboard-first interactions
|
||||
- PWA: SvelteKit service worker with minimal runtime cache for full offline
|
||||
- Tooling/Reproducibility: Nix flake provides devShell and build
|
||||
- CI: Nix build + Vitest unit tests + Playwright smoke tests
|
||||
- Hosting: GitHub Pages or Netlify (static hosting) from Nix build output
|
||||
|
||||
## Rationales
|
||||
- SvelteKit offers SSR/SSG flexibility and first-class PWA support while remaining light for static export
|
||||
- `idb` simplifies IndexedDB usage and supports versioned migrations for local-first data
|
||||
- Canvas/SVG hybrid provides high-performance drawing with crisp glyph overlays and accessibility-friendly fallbacks
|
||||
- Tailwind accelerates consistent UI while CSS variables enable theming and low-cost runtime adjustments
|
||||
- Keeping everything client-side preserves privacy and enables offline-by-default usage
|
||||
- Nix ensures reproducible dev environments and CI builds across machines
|
||||
|
||||
## Alternatives Considered
|
||||
- React/Vite: viable but SvelteKit yields smaller bundles and simpler reactivity
|
||||
- LocalStorage/WebSQL: insufficient for structured data and migrations; IndexedDB preferred
|
||||
- Pure Canvas or pure SVG: hybrid approach chosen to balance performance with resolution-independent elements
|
||||
- Service worker libraries (e.g., Workbox): SvelteKit’s built-in SW is sufficient given minimal caching needs
|
||||
|
||||
## Open Questions (Resolved by requirements/spec)
|
||||
- Export format: PNG at screen resolution for sharing/wallpaper
|
||||
- Sharing: JSON export/import only; no hosted links or image sharing by app
|
||||
- Tile visual rules: Base hue by mood; net habit score controls luminance; negative = static overlay; glyph counts
|
||||
|
||||
---
|
||||
|
||||
## Additional Research Backlog (Prioritized)
|
||||
|
||||
1) Canvas/SVG performance on mobile (P1)
|
||||
- Goal: 60 fps for 150–365 tiles with glow/overlay; define rendering budget and fallbacks
|
||||
- Deliverable: Benchmark results, thresholds, viz package notes
|
||||
- Method: Build FPS harness; test mid/low-end Android + iOS
|
||||
|
||||
2) IndexedDB schema + import/migration performance (P1)
|
||||
- Goal: Reliable imports for multi-year datasets; smooth migrations; responsive UI
|
||||
- Deliverable: Import chunk size, transaction strategy, migration template, storage footprint
|
||||
- Method: Seed 3-year dataset; time import/migration; measure DB size/quota
|
||||
|
||||
3) Accessibility palettes and glyph legibility (P1)
|
||||
- Goal: WCAG AA contrast; color-blind safe palettes; legible glyphs at small sizes
|
||||
- Deliverable: Approved palettes, CSS vars, glyph sizing spec
|
||||
- Method: Simulators + Axe checks; user testing if possible
|
||||
|
||||
4) PWA SW update + offline write safety (P1)
|
||||
- Goal: Safe app update with pending writes and schema changes
|
||||
- Deliverable: SW update policy, cache versioning, migration + rollback checklist
|
||||
- Method: Offline simulation during schema bump; verify no data loss
|
||||
|
||||
5) PNG export fidelity and limits (P2)
|
||||
- Goal: Fast, reliable PNG export with crisp glyphs; cap size to prevent OOM
|
||||
- Deliverable: Use toBlob/toDataURL guidance, max dimensions, UX for progress/errors
|
||||
- Method: Export month/year grids; measure time/memory/file size
|
||||
|
||||
6) Keyboard-first grid navigation + SR UX (P2)
|
||||
- Goal: Intuitive keyboard nav with correct ARIA; SR speaks mood and counts
|
||||
- Deliverable: Roving tabindex model, ARIA roles/labels, SR strings
|
||||
- Method: Prototype navigation + Playwright+Axe tests
|
||||
|
||||
7) Tailwind + CSS variables theming (P2)
|
||||
- Goal: Minimal CSS output with dynamic theming; safe class generation
|
||||
- Deliverable: Theming tokens and example; purge-safe patterns
|
||||
- Method: Prototype theme switcher; inspect bundle size
|
||||
|
||||
### Active Research Tasks (links)
|
||||
- 01: /home/jawz/Development/Projects/GlowTrack/specs/001-glowtrack-a-mood/research/01-viz-performance.md
|
||||
- 02: /home/jawz/Development/Projects/GlowTrack/specs/001-glowtrack-a-mood/research/02-indexeddb-imports-migrations.md
|
||||
- 03: /home/jawz/Development/Projects/GlowTrack/specs/001-glowtrack-a-mood/research/03-a11y-palettes-glyphs.md
|
||||
- 04: /home/jawz/Development/Projects/GlowTrack/specs/001-glowtrack-a-mood/research/04-pwa-sw-offline-safety.md
|
||||
- 05: /home/jawz/Development/Projects/GlowTrack/specs/001-glowtrack-a-mood/research/05-png-export-fidelity.md
|
||||
- 06: /home/jawz/Development/Projects/GlowTrack/specs/001-glowtrack-a-mood/research/06-keyboard-sr-grid.md
|
||||
- 07: /home/jawz/Development/Projects/GlowTrack/specs/001-glowtrack-a-mood/research/07-tailwind-css-vars.md
|
||||
41
specs/001-glowtrack-a-mood/research/01-viz-performance.md
Normal file
41
specs/001-glowtrack-a-mood/research/01-viz-performance.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Research: Canvas/SVG Performance on Mobile
|
||||
|
||||
## Hypothesis
|
||||
We can sustain 60 fps for 150–365 tiles with glow/overlay on mid-range devices by batching draws and minimizing per-frame allocations.
|
||||
|
||||
## Questions
|
||||
- FPS across tile counts (30, 90, 180, 365) and DPR (1.0, 2.0, 3.0)
|
||||
- Cost of static overlay and glyph rendering
|
||||
- Breakpoints for reduced motion or static rendering
|
||||
|
||||
## Method
|
||||
- Use `/packages/viz/poc/index.html` harness
|
||||
- Test devices: low-end Android, mid Android, iPhone
|
||||
- Record FPS and memory; profile with devtools
|
||||
|
||||
## Test Matrix (fill during runs)
|
||||
| DPR | Animate | Tiles | FPS | Notes |
|
||||
|-----|---------|-------|-----|-------|
|
||||
| 1 | false | 30 | | |
|
||||
| 1 | false | 90 | | |
|
||||
| 1 | false | 180 | | |
|
||||
| 1 | false | 365 | | |
|
||||
| 1 | true | 30 | | |
|
||||
| 1 | true | 90 | | |
|
||||
| 1 | true | 180 | | |
|
||||
| 1 | true | 365 | | |
|
||||
| 2 | false | 30 | | |
|
||||
| 2 | false | 90 | | |
|
||||
| 2 | false | 180 | | |
|
||||
| 2 | false | 365 | | |
|
||||
| 2 | true | 30 | | |
|
||||
| 2 | true | 90 | | |
|
||||
| 2 | true | 180 | | |
|
||||
| 2 | true | 365 | | |
|
||||
|
||||
## Acceptance
|
||||
- 55–60 fps at 180 tiles on mid devices
|
||||
- Document fallback thresholds and settings
|
||||
|
||||
## Deliverables
|
||||
- Metrics table; recommendations for renderer design
|
||||
@@ -0,0 +1,31 @@
|
||||
# Research: IndexedDB Imports & Migrations
|
||||
|
||||
## Hypothesis
|
||||
Chunked transactions and store-per-entity design yield responsive imports and safe migrations for 3-year datasets.
|
||||
|
||||
## Questions
|
||||
- Import throughput (items/sec) for days vs entries
|
||||
- Optimal chunk size per transaction
|
||||
- Quota usage for 3-year dataset
|
||||
- Migration time and error handling patterns
|
||||
|
||||
## Method
|
||||
- Use `/packages/storage/poc/import-benchmark.html`
|
||||
- Measure timings, DB size; simulate version bump
|
||||
|
||||
## Test Matrix (fill during runs)
|
||||
| Chunk | Days(ms) | Entries(ms) | Notes |
|
||||
|-------|----------|-------------|-------|
|
||||
| 100 | | | |
|
||||
| 250 | | | |
|
||||
| 500 | | | |
|
||||
| 1000 | | | |
|
||||
| 2000 | | | |
|
||||
| 5000 | | | |
|
||||
|
||||
## Acceptance
|
||||
- Import < 5s for 3-year synthetic dataset on mid device
|
||||
- Migrations complete without UI lockup and preserve data
|
||||
|
||||
## Deliverables
|
||||
- Import strategy, migration template, data integrity checklist
|
||||
@@ -0,0 +1,20 @@
|
||||
# Research: Accessibility Palettes & Glyph Legibility
|
||||
|
||||
## Hypothesis
|
||||
CSS variable-driven palettes can satisfy WCAG AA while remaining legible for common color-blind conditions.
|
||||
|
||||
## Questions
|
||||
- Contrast ratios for default and high-contrast themes
|
||||
- Visibility of mood hue under protanopia/deuteranopia/tritanopia
|
||||
- Glyph legibility at small tile sizes
|
||||
|
||||
## Method
|
||||
- Prototype palettes; run through color-blind simulators and Axe
|
||||
- Validate glyph size/contrast on sample tiles
|
||||
|
||||
## Acceptance
|
||||
- AA contrast for focus indicators and glyphs
|
||||
- Verified palettes for three color-blind modes
|
||||
|
||||
## Deliverables
|
||||
- Approved palettes, token list, glyph sizing guidance
|
||||
@@ -0,0 +1,19 @@
|
||||
# Research: PWA SW Updates & Offline Write Safety
|
||||
|
||||
## Hypothesis
|
||||
With cache versioning and cautious update prompts, we can avoid data loss during app updates and schema bumps while offline.
|
||||
|
||||
## Questions
|
||||
- Best timing for SW activation without disrupting writes
|
||||
- Handling schema migrations when a stale SW is cached
|
||||
- Safe rollback strategy
|
||||
|
||||
## Method
|
||||
- Simulate offline state; bump schema; observe SW activation and data integrity
|
||||
|
||||
## Acceptance
|
||||
- No data loss or corruption across update/migration
|
||||
- Clear UX for update available and post-update state
|
||||
|
||||
## Deliverables
|
||||
- SW update policy, cache naming, migration/rollback checklist
|
||||
@@ -0,0 +1,19 @@
|
||||
# Research: PNG Export Fidelity & Limits
|
||||
|
||||
## Hypothesis
|
||||
Canvas toBlob can reliably export year-scale grids at screen resolution with acceptable memory and time on mid devices.
|
||||
|
||||
## Questions
|
||||
- toBlob vs toDataURL performance/memory
|
||||
- Max safe export dimensions before OOM
|
||||
- Glyph/text crispness at DPR > 1
|
||||
|
||||
## Method
|
||||
- Extend viz harness to export PNG; measure time and size
|
||||
|
||||
## Acceptance
|
||||
- Export < 2s for year grid at scale 1.0 on mid device
|
||||
- Document caps and UX messaging for long exports
|
||||
|
||||
## Deliverables
|
||||
- Export pipeline guidance; caps; progress/error UX recommendations
|
||||
19
specs/001-glowtrack-a-mood/research/06-keyboard-sr-grid.md
Normal file
19
specs/001-glowtrack-a-mood/research/06-keyboard-sr-grid.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Research: Keyboard-first Grid & Screen Reader UX
|
||||
|
||||
## Hypothesis
|
||||
A roving tabindex grid with appropriate ARIA roles can provide intuitive keyboard navigation and informative SR output.
|
||||
|
||||
## Questions
|
||||
- Best roles: grid vs listgrid vs table
|
||||
- Roving tabindex vs per-cell tab stops
|
||||
- SR announcement strings for date, mood, positive/negative counts
|
||||
|
||||
## Method
|
||||
- Create minimal prototype; test with Axe and at least one SR (NVDA/VoiceOver)
|
||||
|
||||
## Acceptance
|
||||
- Arrow navigation works; SR reads context and counts
|
||||
- Meets WCAG AA navigability and focus visibility
|
||||
|
||||
## Deliverables
|
||||
- ARIA mapping and strings; nav model; test checklist
|
||||
18
specs/001-glowtrack-a-mood/research/07-tailwind-css-vars.md
Normal file
18
specs/001-glowtrack-a-mood/research/07-tailwind-css-vars.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Research: Tailwind & CSS Variables Theming
|
||||
|
||||
## Hypothesis
|
||||
We can keep CSS output small while supporting dynamic theming via CSS variables and Tailwind utilities.
|
||||
|
||||
## Questions
|
||||
- Mapping CSS variables to Tailwind utilities without bloating CSS
|
||||
- Safe patterns for dynamic classes and purge
|
||||
- Runtime theme switching performance cost
|
||||
|
||||
## Method
|
||||
- Prototype theme tokens and a toggle; inspect CSS size
|
||||
|
||||
## Acceptance
|
||||
- Minimal CSS growth; smooth theme switching
|
||||
|
||||
## Deliverables
|
||||
- Token design, Tailwind config guidance, sample components
|
||||
103
specs/001-glowtrack-a-mood/spec.md
Normal file
103
specs/001-glowtrack-a-mood/spec.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# Feature Specification: GlowTrack — Mood & Habit Wellbeing Grid
|
||||
|
||||
**Feature Branch**: `001-glowtrack-a-mood`
|
||||
**Created**: 18 September 2025
|
||||
**Status**: Draft
|
||||
**Input**: User description: "GlowTrack — a mood and habit tracker that transforms daily inputs into a vibrant wellbeing grid. Each tile in the grid represents a day, glowing brighter as positive habits are built and dimming or distorting when negative habits are logged. The goal is to make personal growth feel rewarding, visual, and artistic, rather than like a clinical spreadsheet. Unlike typical habit apps that only encourage building routines, GlowTrack also supports tracking bad habits users want to reduce or quit. This makes the grid an honest reflection of both struggles and progress: good habits make the day shine, while harmful ones visibly dull the pattern. Over time, users see their grid evolve into a mosaic of resilience, balance, and self-improvement. The emphasis is on keeping GlowTrack lightweight, private, and beautiful. It should work directly in the browser as a PWA, require no accounts or servers, and let users export/share their wellbeing grids as personal artwork. The focus is motivation through aesthetics — turning daily check-ins into a canvas of personal growth."
|
||||
|
||||
## Execution Flow (main)
|
||||
```
|
||||
1. Parse user description from Input
|
||||
→ If empty: ERROR "No feature description provided"
|
||||
2. Extract key concepts from description
|
||||
→ Identify: actors, actions, data, constraints
|
||||
3. For each unclear aspect:
|
||||
→ Mark with [NEEDS CLARIFICATION: specific question]
|
||||
4. Fill User Scenarios & Testing section
|
||||
→ If no clear user flow: ERROR "Cannot determine user scenarios"
|
||||
5. Generate Functional Requirements
|
||||
→ Each requirement must be testable
|
||||
→ Mark ambiguous requirements
|
||||
6. Identify Key Entities (if data involved)
|
||||
7. Run Review Checklist
|
||||
→ If any [NEEDS CLARIFICATION]: WARN "Spec has uncertainties"
|
||||
→ If implementation details found: ERROR "Remove tech details"
|
||||
8. Return: SUCCESS (spec ready for planning)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## User Scenarios & Testing
|
||||
|
||||
### Primary User Story
|
||||
A user opens GlowTrack in their browser and is greeted by a visually engaging grid representing their days. Each day, the user logs both positive and negative habits. As positive habits are built, the corresponding day's tile glows brighter; negative habits cause the tile to dim or distort. Over time, the user sees their grid evolve into a unique mosaic reflecting both their struggles and progress. The user can export or share their grid as personal artwork, all without creating an account or sharing data with a server.
|
||||
|
||||
### Acceptance Scenarios
|
||||
1. **Given** a new user, **When** they open GlowTrack, **Then** they see an empty wellbeing grid ready for input.
|
||||
2. **Given** a day in the grid, **When** the user logs a positive habit, **Then** the tile glows brighter.
|
||||
3. **Given** a day in the grid, **When** the user logs a negative habit, **Then** the tile dims or distorts.
|
||||
4. **Given** a completed grid, **When** the user chooses to export/share, **Then** the grid is saved as personal artwork.
|
||||
5. **Given** a user, **When** they use GlowTrack, **Then** no account or server interaction is required.
|
||||
|
||||
### Edge Cases
|
||||
- What happens if a user logs both positive and negative habits for the same day?
|
||||
Conflicting habits in a single tile: The tile uses mood as the base hue. Glow intensity is based on the net habit score, where positive habits add glow and negative habits reduce it. Negative habits also add a subtle static overlay. Small glyphs indicate counts (ticks for positives, dots for negatives). Mood hue always remains clear, with overlays only affecting luminance or texture.
|
||||
- How does the system handle days with no input?
|
||||
a dim square.
|
||||
- What if the user wants to edit or delete a habit entry?
|
||||
allow editing.
|
||||
- How is privacy maintained if the user shares their grid?
|
||||
Export formats: Export is supported as PNG in screen resolution (suitable for sharing and wallpaper use), the user is responsible by whom he shares their grid, and is not hosted on any invasive servers.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Functional Requirements
|
||||
- **FR-001**: System MUST allow users to log both positive and negative habits for each day.
|
||||
- **FR-002**: System MUST visually represent each day as a tile in a grid, with brightness and distortion reflecting habit quality.
|
||||
- **FR-003**: Users MUST be able to export/share their wellbeing grid as personal artwork.
|
||||
- **FR-004**: System MUST operate fully in-browser as a PWA, with no account or server required.
|
||||
- **FR-005**: System MUST ensure user data is private and stored locally.
|
||||
- **FR-006**: System MUST allow users to edit or delete habit entries for any day.
|
||||
- **FR-007**: System MUST allow users to customize which habits are tracked.
|
||||
- **FR-008**: System MUST provide a visually engaging, artistic interface for motivation.
|
||||
- **FR-009**: System MUST allow users to reset or clear their grid if desired.
|
||||
- **FR-010**: System MUST allow users to view their progress over time as a mosaic.
|
||||
- **FR-011**: System MUST support offline usage.
|
||||
- **FR-012**: System MUST allow users to select which days to display (e.g., week, month, year).
|
||||
- **FR-013**: System MUST provide guidance or onboarding for first-time users.
|
||||
- **FR-014**: System MUST allow users to share their grid without exposing personal habit details. Sharing is limited to JSON export. Users can back up, move, or import their full data through this format. No images or public links are generated automatically.
|
||||
|
||||
### Key Entities
|
||||
- **DayTile**: Represents a single day in the grid; attributes include date, brightness, distortion, and habit entries.
|
||||
- **HabitEntry**: Represents a logged habit; attributes include type (positive/negative), description, and timestamp.
|
||||
- **WellbeingGrid**: Represents the user's overall grid; attributes include collection of DayTiles, export status, and visual style.
|
||||
|
||||
---
|
||||
|
||||
## Review & Acceptance Checklist
|
||||
|
||||
### Content Quality
|
||||
- [x] No implementation details (languages, frameworks, APIs)
|
||||
- [x] Focused on user value and business needs
|
||||
- [x] Written for non-technical stakeholders
|
||||
- [x] All mandatory sections completed
|
||||
|
||||
### Requirement Completeness
|
||||
- [x] No [NEEDS CLARIFICATION] markers remain
|
||||
- [x] Requirements are testable and unambiguous
|
||||
- [x] Success criteria are measurable
|
||||
- [x] Scope is clearly bounded
|
||||
- [x] Dependencies and assumptions identified
|
||||
|
||||
---
|
||||
|
||||
## Execution Status
|
||||
|
||||
- [x] User description parsed
|
||||
- [x] Key concepts extracted
|
||||
- [x] Ambiguities marked
|
||||
- [x] User scenarios defined
|
||||
- [x] Requirements generated
|
||||
- [x] Entities identified
|
||||
- [x] Review checklist passed
|
||||
- [ ] Review checklist passed
|
||||
Reference in New Issue
Block a user