A calorie tracking app for foods, meals, profile settings, and daily summary. Stack: Vue 3, Vite, TypeScript, Vue Router, TanStack Query, Vitest, Storybook.
- Node.js:
^20.19.0or>=22.12.0 - pnpm
pnpm install
pnpm devpnpm dev- local Vite dev serverpnpm build- type-check + production buildpnpm preview- preview production buildpnpm test:unit- unit tests (Vitest)pnpm lint- ESLint (--fix)pnpm format- Prettier forsrc/pnpm storybook- local Storybookpnpm build-storybook- Storybook build
Code is split into layers:
src/domain- domain types and pure client-side calculationssrc/features- feature action contracts used by UI and infrasrc/infra- adapters and implementations (fake API, mappers, storage)src/ui- pages, components, query-hooks, UI kitsrc/ui/router- routing and route wiringsrc/shared- shared pure utilities such asResultsrc/lib- local UI-oriented helpers
domainis pure and does not depend onfeatures/infra/uifeaturesdefine action contracts over domain typesinfraimplements feature actions and maps DTOs to domain modelsui/query-hooksadapt feature actions to TanStack Query- page views define their own
depscontract from the actions they actually use
Import boundaries are enforced in eslint.config.boundaries.ts.
Actions return Result<T, E>:
ok: true-> success resultok: false-> errorinfra-> infrastructure errornot-found-> expected domain case for delete operations
The UI handles expected errors through Result instead of relying on exceptions across layer boundaries.
- Unit tests for
domain,infra, and helpers - Storybook stories for main page-view components
Run:
pnpm test:unit