[2026-01-05] Refactor Codebase After TypeScript Migration
Task Metadata
Date: 2026-01-05
Status: Complete
1. Context
- Goal: Clean up and refactor the codebase following the recent TypeScript migration. This involves identifying and removing any
anytypes, addressing// @ts-ignorecomments if any, consolidating type definitions, and ensuring idiomatic TypeScript usage across the frontend. - Trigger: Completion of the initial TypeScript migration (Task:
2026-01-05_typescript_conversion.md). Now that the files are converted, a dedicated pass is needed to polish the implementation.
2. Approach
- Technical Strategy:
- Structure Reorganization (Feature-Based): Move from a flat
components/structure to afeatures/based architecture (e.g.,features/dashboard/,features/settings/) to better co-locate related logic. - Type Centralization: Create a dedicated
frontend/src/types/directory to house shared domain models (Meal,UserTargets) and remove ad-hoc interfaces scattered across files. - Decompose God Components:
- Dashboard.tsx: Extract logic into custom hooks (
useClipboardMeal,useLayoutPreference) to reduce component size and complexity. - Tracker.tsx: Move the mock API client out of the component file into a test utility.
- Dashboard.tsx: Extract logic into custom hooks (
- Strict Typing: Replace
anyinApiMealServiceanduseMealswith proper Generics and domain types.
- Structure Reorganization (Feature-Based): Move from a flat
- Key Decisions:
- Will adopt a "Feature Folder" pattern:
src/features/<feature_name>/{components, hooks, types}. - Legacy snake_case support in
Mealtype will be isolated to the parser/adapter layer; the rest of the app will strictly use camelCase.
- Will adopt a "Feature Folder" pattern:
- Testing Strategy:
- Must Test:
npm run typecheck(orbun run typecheck) must pass with zero errors.npm run lintmust be clean.- Existing unit/integration tests must pass.
- Skip: No new feature testing; this is a refactor.
- Must Test:
3. Impact Analysis
- Files to Modify:
frontend/src/pages/Dashboard.tsx(Heavy refactor)frontend/src/hooks/useMeals.ts(Type cleanup)frontend/src/services/ApiMealService.ts(Type cleanup)frontend/src/**/*.tsx(Move to new folders)
- Risks:
- Import paths will change significantly; need to ensure
tsconfig.jsonpaths (if any) and all imports are updated correctly. - Moving state logic to hooks requires careful dependency array management to avoid infinite loops.
- Import paths will change significantly; need to ensure
4. Execution Plan
- Step 1: Type Foundation
- Create
frontend/src/types/index.tsand migrateMeal,UserTargets,DaySummary. - Clean up
ApiMealService.tsto use these types instead ofany.
- Create
- Step 2: Logic Extraction
- Create
useClipboardMealhook to handle paste logic fromDashboard.tsx. - Create
useLayoutPreferencehook to handle UI state fromDashboard.tsx. - Move Mock Client from
Tracker.tsxtofrontend/src/utils/mockApi.ts.
- Create
- Step 3: Component Reorganization
- Create
frontend/src/features/dashboard/componentsand moveMealList,DailyTotals, etc. - Update all import paths.
- Create
- Step 4: Cleanup
- Remove legacy snake_case fields from internal types (ensure
mealParserhandles the conversion at the boundary). - Verify build and tests.
- Remove legacy snake_case fields from internal types (ensure
5. Execution Notes
(AI to add details discovered during implementation)
Refactor Tour & Benefits
We moved from a flat, organic structure to a Feature-Based Architecture. Here is why this is better for the project's long-term health:
1. Feature Modules (frontend/src/features/dashboard)
- What Changed: Instead of a giant
components/folder mixed with everything, we now havefeatures/dashboard/components. - Why it's Better:
- Co-location: Related files stay together. When working on the Dashboard, you don't need to hunt through generic lists.
- Scalability: As we add "Tracking", "Social", or "Profile" features, they will have their own sandboxes, preventing the "God Folder" problem.
2. Logic Extraction (Custom Hooks)
- What Changed:
Dashboard.tsxwas over 250 lines. We extracted:useMealStaging: Handles complex clipboard pasting, URL parsing, and pending state.useLayoutPreference: Manages local storage persistence for UI toggles.
- Why it's Better:
- Separation of Concerns: The view layer (
Dashboard.tsx) now just renders. The logic is isolated and testable in hooks. - Reusability: If we ever need to "paste meal" from another page,
useMealStagingis ready to go.
- Separation of Concerns: The view layer (
3. Strict Centralized Types (frontend/src/types)
- What Changed: We created a single source of truth for
Meal,UserTargets, andAmplifyClient. - Why it's Better:
- No More
any:ApiMealServiceis now strictly typed. If the backend schema changes, TypeScript will scream at us at compile time, not at the user at runtime. - Refactoring Confidence: Changing a field name in one place propagates errors everywhere immediately.
- No More
4. Legacy Data Resilience
- Challenge: The DynamoDB table contains older items with
PascalCasekeys (from early AI prompts) andsnake_casekeys. - Solution: While our internal Types are strict
camelCase, we restored "smart fallback" logic inMealItem.tsx(e.g.,meal.calories || meal.Calories). - Safety: We added a specific regression test (
MealItem.test.tsx) that feeds "Legacy Eggs" (old format) to the component to guarantee it never breaks for long-time users.
Stats
- Type Errors: 0 (Clean
tscrun) - Tests: 100% Passing (including new legacy data tests)
- Code Clarity:
Dashboard.tsxis significantly smaller and more declarative.
Architectural Decision Record
- Granularity Strategy: Added ADR 003: Component Granularity to address concerns about file proliferation vs. maintainability. Key takeaway: ~85 lines per file is the "sweet spot" for maintainability.
6. User Approval & Key Learnings
(User to confirm approval and add notes/learnings)
7. Context Memory (AI-Only)
Summary for Future Context
(Auto-generated summary of what was changed, why, and what is next. To be pasted into the prompt of the next session to maintain continuity.)