Skip to content

[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 any types, addressing // @ts-ignore comments 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:
    1. Structure Reorganization (Feature-Based): Move from a flat components/ structure to a features/ based architecture (e.g., features/dashboard/, features/settings/) to better co-locate related logic.
    2. Type Centralization: Create a dedicated frontend/src/types/ directory to house shared domain models (Meal, UserTargets) and remove ad-hoc interfaces scattered across files.
    3. 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.
    4. Strict Typing: Replace any in ApiMealService and useMeals with proper Generics and domain types.
  • Key Decisions:
    • Will adopt a "Feature Folder" pattern: src/features/<feature_name>/{components, hooks, types}.
    • Legacy snake_case support in Meal type will be isolated to the parser/adapter layer; the rest of the app will strictly use camelCase.
  • Testing Strategy:
    • Must Test:
      • npm run typecheck (or bun run typecheck) must pass with zero errors.
      • npm run lint must be clean.
      • Existing unit/integration tests must pass.
    • Skip: No new feature testing; this is a refactor.

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.json paths (if any) and all imports are updated correctly.
    • Moving state logic to hooks requires careful dependency array management to avoid infinite loops.

4. Execution Plan

  • Step 1: Type Foundation
    • Create frontend/src/types/index.ts and migrate Meal, UserTargets, DaySummary.
    • Clean up ApiMealService.ts to use these types instead of any.
  • Step 2: Logic Extraction
    • Create useClipboardMeal hook to handle paste logic from Dashboard.tsx.
    • Create useLayoutPreference hook to handle UI state from Dashboard.tsx.
    • Move Mock Client from Tracker.tsx to frontend/src/utils/mockApi.ts.
  • Step 3: Component Reorganization
    • Create frontend/src/features/dashboard/components and move MealList, DailyTotals, etc.
    • Update all import paths.
  • Step 4: Cleanup
    • Remove legacy snake_case fields from internal types (ensure mealParser handles the conversion at the boundary).
    • Verify build and tests.

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 have features/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.tsx was 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, useMealStaging is ready to go.

3. Strict Centralized Types (frontend/src/types)

  • What Changed: We created a single source of truth for Meal, UserTargets, and AmplifyClient.
  • Why it's Better:
    • No More any: ApiMealService is 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.

4. Legacy Data Resilience

  • Challenge: The DynamoDB table contains older items with PascalCase keys (from early AI prompts) and snake_case keys.
  • Solution: While our internal Types are strict camelCase, we restored "smart fallback" logic in MealItem.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 tsc run)
  • Tests: 100% Passing (including new legacy data tests)
  • Code Clarity: Dashboard.tsx is 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.)