{"id":51846484,"url":"https://github.com/rupertgermann/habit-tracker","last_synced_at":"2026-07-23T12:31:29.271Z","repository":{"id":371853973,"uuid":"1283261066","full_name":"rupertgermann/habit-tracker","owner":"rupertgermann","description":"AI-assisted full-stack habit tracker with React, SQLite persistence, dark mode, journaling, and Playwright regression coverage","archived":false,"fork":false,"pushed_at":"2026-07-17T09:28:22.000Z","size":2553,"stargazers_count":0,"open_issues_count":16,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-17T10:22:52.618Z","etag":null,"topics":["accessibility","ai-assisted-development","better-sqlite3","dark-mode","data-visualization","express","full-stack","habit-tracker","journaling","playwright","productivity","react","responsive-design","sqlite","vite"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rupertgermann.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null},"funding":{"github":null,"patreon":"rupertgermann","open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"lfx_crowdfunding":null,"polar":null,"buy_me_a_coffee":"rupertgermann","thanks_dev":null,"custom":null}},"created_at":"2026-06-28T18:15:40.000Z","updated_at":"2026-07-17T09:29:18.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/rupertgermann/habit-tracker","commit_stats":null,"previous_names":["rupertgermann/habit-tracker"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/rupertgermann/habit-tracker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rupertgermann%2Fhabit-tracker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rupertgermann%2Fhabit-tracker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rupertgermann%2Fhabit-tracker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rupertgermann%2Fhabit-tracker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rupertgermann","download_url":"https://codeload.github.com/rupertgermann/habit-tracker/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rupertgermann%2Fhabit-tracker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35802930,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"online","status_checked_at":"2026-07-23T02:00:06.683Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["accessibility","ai-assisted-development","better-sqlite3","dark-mode","data-visualization","express","full-stack","habit-tracker","journaling","playwright","productivity","react","responsive-design","sqlite","vite"],"created_at":"2026-07-23T12:31:28.569Z","updated_at":"2026-07-23T12:31:29.265Z","avatar_url":"https://github.com/rupertgermann.png","language":"JavaScript","funding_links":["https://patreon.com/rupertgermann","https://buymeacoffee.com/rupertgermann"],"categories":[],"sub_categories":[],"readme":"# Habit Tracker\n\nAn AI-assisted, full-stack habit tracker for building routines, visualizing streaks, and reflecting on progress. The app combines a polished React 19 interface with five switchable visual systems, an Express API, SQLite persistence, database-backed settings, dark mode, and browser regression coverage.\n\n**Repository description:** AI-assisted full-stack habit tracker with five design modes, React, SQLite persistence, journaling, and Playwright coverage.\n\n**Suggested GitHub topics:** `ai-assisted-development`, `react`, `vite`, `express`, `sqlite`, `better-sqlite3`, `playwright`, `habit-tracker`, `productivity`, `journaling`, `design-system`, `dark-mode`, `responsive-design`, `accessibility`, `data-visualization`, `full-stack`\n\n## Screenshots\n\nThe README screenshots use seeded synthetic data generated by `npm run screenshots`.\n\n| Standard | Rhythm Ledger | Orbit |\n|---|---|---|\n| \u003cimg src=\"docs/images/readme-dashboard-light.png\" alt=\"Standard Habit Tracker dashboard with seeded example habits\" width=\"300\"\u003e | \u003cimg src=\"docs/images/readme-dashboard-rhythm-ledger.png\" alt=\"Rhythm Ledger dashboard with a seven-day rhythm rail\" width=\"300\"\u003e | \u003cimg src=\"docs/images/readme-dashboard-orbit.png\" alt=\"Orbit dashboard with orbital completion visualization\" width=\"300\"\u003e |\n\n| Quiet Momentum | Sunday Club | Appearance settings |\n|---|---|---|\n| \u003cimg src=\"docs/images/readme-dashboard-quiet-momentum.png\" alt=\"Quiet Momentum dashboard with calm botanical styling\" width=\"300\"\u003e | \u003cimg src=\"docs/images/readme-dashboard-sunday-club.png\" alt=\"Sunday Club dashboard with a playful punch-card layout\" width=\"300\"\u003e | \u003cimg src=\"docs/images/readme-settings-appearance.png\" alt=\"Appearance settings showing all five design choices\" width=\"300\"\u003e |\n\n| Standard dark mode | Calendar dark mode |\n|---|---|\n| \u003cimg src=\"docs/images/readme-dashboard-dark.png\" alt=\"Standard Habit Tracker dashboard in dark mode\" width=\"300\"\u003e | \u003cimg src=\"docs/images/readme-calendar-dark.png\" alt=\"Habit Tracker calendar heatmap in dark mode\" width=\"300\"\u003e |\n\n## Design Modes\n\nThe Appearance settings apply each visual system as a complete responsive shell: theme tokens, global texture, Dashboard composition, primary navigation, and desktop frame change together. Light and dark mode remain available within every design, and both preferences persist in SQLite.\n\n| Design | Character | Wide-screen navigation |\n|---|---|---|\n| Standard | Friendly green cards and direct progress feedback | Top bar |\n| Rhythm Ledger | Warm field journal with editorial typography and a seven-day rhythm rail | Left record rail |\n| Orbit | Cobalt trajectory controls and orbital Completion signals | Left command rail |\n| Quiet Momentum | Botanical restraint and deliberately low-noise progress | Top bar |\n| Sunday Club | Bright punch cards and playful weekend energy | Right club rail |\n\nBelow the wide breakpoint, every design uses a touch-safe bottom navigation suited to its own visual language.\n\n## Why This Repo\n\n- **Product-quality UI** - five complete design modes, mobile-first navigation, tablet split views, polished motion, dark mode, and readable empty states.\n- **Real persistence** - habits, categories, journal entries, profile details, design/theme preferences, and calendar preference live in SQLite through an Express REST API.\n- **Domain-oriented code** - tracking rules are isolated in `src/domain/`, with project vocabulary documented in `CONTEXT.md`.\n- **Regression coverage** - domain tests cover habit and journal rules; Playwright tests cover persisted flows, all design dashboards across responsive viewports, profile/avatar settings, and dark-mode contrast.\n- **Reproducible public assets** - README screenshots are generated from a temp database, so docs assets do not depend on local personal data.\n\n## Features\n\n- **Dashboard** - design-specific daily overview, Completion rate and weekly rhythm, motivational messaging, quick yes/no check-off, and Count Habit steppers.\n- **Habit management** - create, edit, and delete habits with category, color, frequency, reminders, yes/no tracking, or count tracking with an optional daily goal.\n- **Searchable icon catalog** - Tabler-based habit and category icons grouped by theme, with legacy emoji/string icon fallback for older data.\n- **Categories** - seeded default categories for health, productivity, mindfulness, learning, social, creativity, and other habits.\n- **Calendar view** - per-habit week, month, and year views with heatmap intensity, day details, period navigation, week-start preferences, and dark-mode contrast checks.\n- **Progress \u0026 stats** - weekly bars, monthly trend charts, current and longest streaks, completion rates, and insight cards.\n- **Journal** - dated reflections connected to habits, mood annotations, weekly timeline navigation, and search scoped to the selected week.\n- **Settings \u0026 profile** - editable name/email, image avatar upload/removal, Standard/Rhythm Ledger/Orbit/Quiet Momentum/Sunday Club design selection, dark mode, reminder time, notification permission handling, and Sunday/Monday week-start selection.\n- **Data management** - JSON export, CSV export, canonical version 2 backup, safe restore of version 2 and legacy `1.0.0` files, and clear-all controls backed by the database.\n- **Information pages** - privacy, terms, and support pages reachable from Settings.\n- **Responsive layout** - mobile bottom navigation and wide-screen tablet split views for habit list/detail workflows.\n- **Accessibility** - a skip-to-main link, labeled controls, keyboard focus states, readable dark-mode controls, and Playwright assertions for overflow and contrast-sensitive surfaces.\n\n## Tech Stack\n\n| Area | Library |\n|---|---|\n| UI library | React 19 |\n| Build tool | Vite 8 |\n| Routing | React Router 7 |\n| Styling | styled-components 6 |\n| Animations | Framer Motion 12 |\n| Charts | Recharts 3 |\n| Icons | Tabler Icons React 3 |\n| Dates | date-fns 4 |\n| Celebrations | react-confetti 6 |\n| API server | Express 5 |\n| Database | SQLite through better-sqlite3 |\n| Browser tests | Playwright |\n\n## Getting Started\n\n### Prerequisites\n\n- Node.js 24.x (run `nvm use` to select the version from `.nvmrc`)\n- npm\n\n### Install\n\n```bash\nnpm install\n```\n\n### Run Locally\n\n```bash\nnpm run dev\n```\n\nThe app opens at `http://localhost:3300`. The API listens at `http://127.0.0.1:3301`, and Vite proxies `/api` to that backend.\n\n## Commands\n\n| Command | Description |\n|---|---|\n| `npm run dev` | Start the Express API and Vite client together. Client: `http://localhost:3300`; API: `http://127.0.0.1:3301`. |\n| `npm run dev:client` | Start only the Vite client on port `3300`; use it with a separately running API server. |\n| `npm run server` | Start only the Express API server on `127.0.0.1:3301`. |\n| `npm run dev:e2e` | Start the API and client against `.tmp/e2e/habit-tracker.db` for browser tests. Client: `http://127.0.0.1:3340`; API: `http://127.0.0.1:3341`. |\n| `npm run test` | Run domain, server, and Playwright browser tests. |\n| `npm run test:domain` | Run domain and context tests through Vite SSR. |\n| `npm run test:server` | Run transactional SQLite server tests. |\n| `npm run test:e2e` | Run the Playwright suite with an isolated temp database and runtime reset guard. |\n| `npm run screenshots` | Seed synthetic data in `.tmp/screenshots`, start isolated local servers on `3330/3331`, and capture the five dashboards, Appearance picker, and dark-mode README surfaces into `docs/images/`. |\n| `npm run build` | Build the production bundle to `dist/` with source maps. |\n| `npm run preview` | Serve the production build locally for preview. |\n| `npm run dev:all` | Alias for `npm run dev`. |\n\n### Runtime Options\n\n| Option | Purpose |\n|---|---|\n| `HOST` | API bind host. Defaults to `127.0.0.1`. |\n| `PORT` | API port. Defaults to `3301`; also drives Vite's default `/api` proxy target. |\n| `VITE_API_TARGET` | Explicit Vite proxy target. The e2e and screenshot harnesses set this automatically. |\n| `VITE_OPEN=true` | Open the Vite dev server in the browser on startup. |\n| `HABIT_TRACKER_DB_PATH` | SQLite database path. Defaults to `server/data/habit-tracker.db`. |\n| `HABIT_TRACKER_E2E=true` | Marks a runtime as safe for destructive test resets when the DB path is under `.tmp/e2e/`. |\n| `E2E_CLIENT_PORT` / `E2E_API_PORT` | Override the ports used by `npm run dev:e2e` and Playwright. Defaults: `3340` / `3341`. |\n| `SCREENSHOT_CLIENT_PORT` / `SCREENSHOT_API_PORT` | Override the ports used by `npm run screenshots`. Defaults: `3330` / `3331`. |\n\n## Project Structure\n\n```text\nhabit-tracker/\n├── CONTEXT.md                 # Domain vocabulary for habits, completions, streaks, and journals\n├── design-specifications.md   # Current UI component and screen specifications\n├── docs/\n│   ├── images/                # README screenshots generated from seeded example data\n│   ├── implementation-summary.md\n│   └── prompt.md\n├── scripts/\n│   ├── capture-readme-screenshots.mjs\n│   ├── run-domain-tests.mjs\n│   └── run-e2e-dev.mjs\n├── shared/\n│   └── defaultCategories.json # Seed and legacy-restore defaults shared by server and client\n├── server/\n│   ├── db.js                  # SQLite schema, row helpers, settings, and complete-state restore\n│   ├── index.js               # Express REST API\n│   └── data/                  # Local SQLite database files, ignored by git\n├── src/\n│   ├── adapters/              # Browser-only file selection and download behavior\n│   ├── appDesign/             # Complete App Design registrations and fallback resolution\n│   ├── api/                   # Frontend API client\n│   ├── components/            # Reusable UI components\n│   ├── context/               # Habits, theme, preferences, toast, and navigation contexts\n│   ├── domain/                # Pure tracking rules plus injected write and backup coordinators\n│   ├── screens/               # Route-level screens\n│   └── styles/                # Design registry plus per-design light/dark themes and global styles\n└── tests/\n    ├── context/\n    ├── domain/\n    ├── e2e/\n    └── server/\n```\n\n## Architecture\n\nThe frontend uses React Context for live app state. Pure calculations stay separate from persistence-aware coordinators, whose effects are supplied through injected interfaces:\n\n- `HabitsContext` loads application state and supplies persistence-aware Completion and Journal Entry writers. Both return committed results, serialize same-record writes, and restore exact prior state after persistence failure.\n- `src/domain/habitTracking.js` and `src/domain/journalTimeline.js` contain pure date, Completion, Streak, Calendar Period, and timeline calculations.\n- `src/domain/dashboardHabitTracking.js` composes those shared calculations with the Completion writer, waits for in-flight Completion writes to settle, and returns committed semantic outcomes for all five dashboard presentations. App Designs own wording, layout, motion, and feedback rendering.\n- `src/domain/journalEntryWrites.js` coordinates injected persistence, same-entry ordering, exact rollback, and committed caller results.\n- `src/appDesign/catalog.jsx` is the single registration seam for each design's metadata, previews, light/dark themes, global styles, dashboard, primary navigation, and responsive frame.\n- `ThemeContext` resolves the selected catalog registration, stores design and light/dark preferences in the database, and removes legacy browser-storage theme values.\n- `PreferencesContext` stores week-start preference in the database and feeds calendar, journal, and progress calculations.\n- `ToastContext` owns notifications inside the UI.\n- `NavigationContext` keeps the bottom navigation aligned with the active route.\n- `src/domain/backup.js` coordinates persisted-state reads and restore writes around pure canonical validation and legacy migration, while `src/adapters/browserBackup.js` owns browser file I/O.\n\nThe backend stores each collection item as JSON in SQLite tables. `server/db.js` owns complete restore as one transaction over Habits, Categories, Journal Entries, and settings and returns the authoritative `{ ok, state }` result.\n\n## API\n\n| Method \u0026 Path | Description |\n|---|---|\n| `GET /api/state` | Full app state: habits, categories, journal entries, and settings. |\n| `GET /api/runtime` | Runtime marker used by the e2e reset guard. |\n| `GET /api/settings/:key` / `PUT /api/settings/:key` | Read or persist database-backed settings such as `design`, `theme`, `profile`, and `preferences`. |\n| `POST /api/habits` / `PUT /api/habits/:id` / `DELETE /api/habits/:id` | Create, update, or delete a habit. Deleting a habit also removes its journal entries. |\n| `POST /api/categories` / `PUT /api/categories/:id` / `DELETE /api/categories/:id` | Manage categories. |\n| `POST /api/journal` / `PUT /api/journal/:id` / `DELETE /api/journal/:id` | Manage journal entries. |\n| `POST /api/restore` | Atomically replace all stored app data and return `{ ok, state }` with authoritative committed state. |\n| `DELETE /api/data` | Clear all data and re-seed default categories. |\n\n## Routes\n\n| Path | Screen |\n|---|---|\n| `/` | Dashboard |\n| `/habits` | Habits list or tablet split view |\n| `/calendar` | Calendar heatmap |\n| `/habit/:id` | Habit detail or tablet split view |\n| `/progress` | Progress \u0026 stats |\n| `/journal` | Journal |\n| `/settings` | Settings |\n| `/privacy` | Privacy policy |\n| `/terms` | Terms of service |\n| `/support` | Support |\n| `/add-habit` | Add habit |\n| `/edit-habit/:id` | Edit habit |\n\n## Testing\n\nDomain tests run with `npm run test:domain` and cover Habit tracking, dashboard semantic outcomes, persistence-aware Completion and Journal Entry writes, App Design registrations, canonical backup validation/migration, journal timelines, and database-backed preference normalization. Server tests force complete-restore failures to verify SQLite rollback.\n\nBrowser tests run with `npm run test:e2e`. Playwright starts `npm run dev:e2e`, verifies the API is using `.tmp/e2e/habit-tracker.db`, and only then allows reset/restore operations. The suite covers cross-design Completion success, reload, rollback, and confetti suppression; every App Design's light/dark persistence matrix; committed Journal Entry feedback; canonical and legacy backup/restore including visible failure preservation; persisted habit flows; profile/avatar persistence; calendar contrast; and responsive smoke coverage.\n\n## Documentation\n\n- `CONTEXT.md` - domain vocabulary for the app.\n- `design-specifications.md` - current component, screen, theme, motion, responsive, and accessibility specifications.\n- `docs/implementation-summary.md` - implementation overview with file-level pointers.\n- `docs/prompt.md` - original product/design brief.\n- `docs/agents/` - agent workflow notes for GitHub Issues, triage labels, and domain docs.\n\n## License\n\nHabit Tracker is released under the [MIT License](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frupertgermann%2Fhabit-tracker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frupertgermann%2Fhabit-tracker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frupertgermann%2Fhabit-tracker/lists"}