Skip to content

Conversation

@marcodejongh
Copy link
Owner

This reduces client bundle size by moving large configuration data (~260KB)
to the backend and making it available via GraphQL queries.

Changes:

  • Add board configuration data module to backend (packages/backend/src/data/)

    • product-sizes-data.ts: Product sizes, layouts, sets, image filenames, hole placements
    • led-placements-data.ts: LED position mappings for Bluetooth control
    • board-data.ts: Static board dimensions, angles, and grades
    • types.ts: TypeScript type definitions
    • index.ts: Module exports
  • Add GraphQL types and queries for board configuration

    • ProductSize, Layout, HoldSet, BoardDetails, LedPlacements types
    • boardDetails, layouts, sizesForLayout, setsForLayoutAndSize queries
    • ledPlacements query for Bluetooth LED control
    • boardSelectorOptions query for setup wizard
  • Update Bluetooth components to fetch LED placements via GraphQL

    • use-board-bluetooth.ts: Async fetch with caching
    • send-climb-to-board-button.tsx: Async fetch with caching
  • Add server-side cached GraphQL operations for board config

    • board-config.ts: Server-only cached queries
    • board-config.client.ts: Client-side fetcher for LED placements

This is the first phase of the migration. Server components still use
the bundled data files; future work will update them to use GraphQL.

This reduces client bundle size by moving large configuration data (~260KB)
to the backend and making it available via GraphQL queries.

Changes:
- Add board configuration data module to backend (packages/backend/src/data/)
  - product-sizes-data.ts: Product sizes, layouts, sets, image filenames, hole placements
  - led-placements-data.ts: LED position mappings for Bluetooth control
  - board-data.ts: Static board dimensions, angles, and grades
  - types.ts: TypeScript type definitions
  - index.ts: Module exports

- Add GraphQL types and queries for board configuration
  - ProductSize, Layout, HoldSet, BoardDetails, LedPlacements types
  - boardDetails, layouts, sizesForLayout, setsForLayoutAndSize queries
  - ledPlacements query for Bluetooth LED control
  - boardSelectorOptions query for setup wizard

- Update Bluetooth components to fetch LED placements via GraphQL
  - use-board-bluetooth.ts: Async fetch with caching
  - send-climb-to-board-button.tsx: Async fetch with caching

- Add server-side cached GraphQL operations for board config
  - board-config.ts: Server-only cached queries
  - board-config.client.ts: Client-side fetcher for LED placements

This is the first phase of the migration. Server components still use
the bundled data files; future work will update them to use GraphQL.
@vercel
Copy link

vercel bot commented Dec 30, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
boardsesh Ready Ready Preview, Comment Dec 30, 2025 1:13pm

@claude
Copy link

claude bot commented Dec 30, 2025

Claude Review

  • packages/backend/src/graphql/resolvers/board/queries.ts:125-127 - Empty catch block swallows errors silently in boardDetails query; should at least log the error
  • packages/web/app/components/board-bluetooth-control/send-climb-to-board-button.tsx:119-150 - Duplicated sendClimbToBoard logic exists in both the function and inline in handleClick (lines 184-203); create shared helper function
  • packages/web/app/components/board-bluetooth-control/use-board-bluetooth.ts:18-42 and send-climb-to-board-button.tsx:25-49 - convertToMirroredFramesString function duplicated in both files; extract to shared utility
  • packages/web/app/components/board-bluetooth-control/send-climb-to-board-button.tsx:104-116 and use-board-bluetooth.ts:82-103 - getLedPlacementsCached logic duplicated; should be shared
  • packages/backend/src/data/product-sizes-data.ts - 476 lines of static data; this would balloon client bundle if accidentally imported on client-side (verify tree-shaking works correctly or add build-time checks)
  • Memory concern: LED_PLACEMENTS in led-placements-data.ts contains large nested objects that will remain in memory on backend; consider lazy-loading or streaming for very large datasets

- Extract duplicated convertToMirroredFramesString to bluetooth-utils.ts
- Create shared createLedPlacementsFetcher factory for cached LED fetching
- Update use-board-bluetooth.ts and send-climb-to-board-button.tsx to use shared utilities
- Add error logging to empty catch block in boardDetails resolver
@claude
Copy link

claude bot commented Dec 30, 2025

Claude Review

Issues Found:

  1. Duplicated LED placements fetching logic - send-climb-to-board-button.tsx:72-80 and send-climb-to-board-button.tsx:138-155 contain nearly identical code for fetching LED placements and sending to board. The sendClimbToBoard callback already handles this, but it's duplicated inline in handleClick.

  2. Silent failure on LED placements fetch - send-climb-to-board-button.tsx:143-145 logs error but doesn't notify user when LED placements fetch fails during connection. User sees successful connection but climb won't be sent.

  3. No error handling for GraphQL client - board-config.client.ts:33-36 catches errors but silently returns null. Consider propagating errors so callers can handle them appropriately (e.g., retry logic, user notification).

  4. Potential memory leak in cache - bluetooth-utils.ts:42-67 creates an in-memory cache that never expires or clears. While cache invalidation isn't critical for static data, consider clearing on board config change.

  5. Type duplication between packages - Types in packages/backend/src/data/types.ts duplicate those in packages/shared-schema/src/types.ts. Consider importing from shared-schema to maintain single source of truth.

  6. Missing validation on GraphQL resolver - queries.ts:96 casts setIds to array without validating it's actually an array of integers.

- Deduplicate handleClick to reuse sendClimbToBoard callback
- Add user notification (message.error) when LED placements fetch fails
- Add comprehensive input validation for GraphQL resolvers:
  - LayoutIdSchema for layout_id validation
  - SizeIdSchema for size_id validation
  - SetIdsArraySchema for set_ids array validation
- Import shared types from @boardsesh/shared-schema to reduce duplication
  - BoardName, HoldTuple, HoldRenderData, ImageFileName, ImagesToHolds
@claude
Copy link

claude bot commented Dec 30, 2025

Claude Review

packages/web/app/components/board-bluetooth-control/send-climb-to-board-button.tsx:162-167

  • Race condition: sendClimbToBoard is called in useEffect when isConnected changes to true, but also when currentClimbQueueItem changes. Since handleClick already calls sendClimbToBoard after connection, this will cause duplicate sends when first connecting.

packages/web/app/components/board-bluetooth-control/bluetooth-utils.ts:43-66

  • Memory leak potential: createLedPlacementsFetcher uses closure-based caching that persists for the component's lifetime. The cache is never cleared even when the component unmounts, and the cached data could become stale if board configurations change.

packages/web/app/lib/graphql/operations/board-config.client.ts:38-40

  • Silent error handling: Errors are logged to console but the function returns null, which could mask network issues from users. Consider surfacing errors more explicitly.

packages/backend/src/graphql/resolvers/board/queries.ts:131-134

  • Swallowing errors: boardDetails resolver catches errors and returns null with only a console.error. This makes debugging production issues difficult - consider throwing with a sanitized error message instead.

packages/backend/src/data/product-sizes-data.ts & led-placements-data.ts

  • Data duplication: These files duplicate data that already exists in the web package. While the PR mentions this reduces client bundle size, maintaining duplicate auto-generated files in two packages increases risk of sync issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants