Skip to content

Migrate from Mapbox GL to MapLibre GL with dual provider support#359

Merged
SvenVw merged 12 commits into
developmentfrom
FDM347
Dec 2, 2025
Merged

Migrate from Mapbox GL to MapLibre GL with dual provider support#359
SvenVw merged 12 commits into
developmentfrom
FDM347

Conversation

@SvenVw
Copy link
Copy Markdown
Collaborator

@SvenVw SvenVw commented Nov 28, 2025

Summary by CodeRabbit

  • New Features

    • Unified map-style provider with built-in fallbacks (MapTiler & OSM).
    • Geocoder supports multiple providers with improved result handling.
  • Changes

    • Mapping stack migrated from Mapbox to MapLibre across the app.
    • Configuration moved from a single token to provider/key-based env vars.
    • Loaders and map components now expose a single mapStyle value for initialization.
  • Documentation

    • README and docs updated for MapLibre/provider-based configuration.

✏️ Tip: You can customize this high-level summary in your review settings.

@SvenVw SvenVw self-assigned this Nov 28, 2025
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Nov 28, 2025

🦋 Changeset detected

Latest commit: 66da6d5

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@svenvw/fdm-app Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Nov 28, 2025

Walkthrough

Replaces Mapbox with MapLibre across the app: imports, types, CSS, dependencies, runtime env and config shapes; adds getMapStyle() with MapTiler/OSM handling; rewrites geocoder and map controls to use MapLibre; updates many route loaders to return a unified mapStyle.

Changes

Cohort / File(s) Summary
Config & Env Types
fdm-app/app/types/config.d.ts, fdm-app/app/types/public-env.d.ts
Replace integrations.mapbox / PUBLIC_MAPBOX_TOKEN with integrations.map (provider: `"maptiler"
Map integration modules
fdm-app/app/integrations/map.ts, fdm-app/app/integrations/mapbox.ts (removed)
Add exported getMapStyle(variant) returning a MapTiler style URL or fallback StyleSpecification; remove Mapbox-specific integration file and its token/style helpers.
Dependencies & Changeset
fdm-app/package.json, .changeset/metal-fans-brush.md
Swap Mapbox packages for MapLibre equivalents (mapbox-glmaplibre-gl, @mapbox/...geocoder@maplibre/...geocoder), update type deps, and add a changeset noting the migration.
App root & styles
fdm-app/app/root.tsx, fdm-app/app/tailwind.css
Replace Mapbox CSS import with MapLibre CSS; expose new map env vars from loader; add MapLibre geocoder UI CSS tweaks.
Atlas controls & geocoder
fdm-app/app/components/blocks/atlas/atlas-controls.tsx, fdm-app/app/components/blocks/atlas/atlas-geocoder.tsx
Replace Mapbox types/imports with MapLibre equivalents; adjust control CSS classes; implement MapLibre geocoder and custom forwardGeocode supporting MapTiler and OSM.
Atlas panels / sources / styles
fdm-app/app/components/blocks/atlas/atlas-panels.tsx, fdm-app/app/components/blocks/atlas/atlas-sources.tsx, fdm-app/app/components/blocks/atlas/atlas-styles.tsx
Switch react-map-gl imports to maplibre variants, update event/typing to MapLibre types, tighten event/feature guards, and add a type cast for style expressions.
Routes / Loaders & Map usage
fdm-app/app/routes/**/atlas*.tsx, fdm-app/app/routes/**/fields*.tsx, fdm-app/app/routes/**/field*.tsx, fdm-app/app/routes/farm.create...
Remove mapboxToken/mapboxStyle from loaders; loaders now return mapStyle via getMapStyle(); client components use react-map-gl/maplibre, pass mapLib={maplibregl}, and use mapStyle; add small runtime guards and stricter geojson typing.
Other edits & docs
fdm-app/README.md, fdm-app/.env.example, docker-compose.yml, various atlas files
Documentation, env examples, and compose updated to new PUBLIC_MAP_PROVIDER/PUBLIC_MAPTILER_API_KEY; various minor typing, guard, and CSS class fixes across atlas components.

Sequence Diagram(s)

sequenceDiagram
    actor Browser
    participant Server
    participant Config
    participant MapService as getMapStyle
    participant External as MapTiler/OSM
    Browser->>Server: Request atlas route (loader)
    Server->>Config: Read PUBLIC_MAP_PROVIDER / maptilerKey
    Server->>MapService: getMapStyle(variant)
    MapService->>External: Fetch style URL or return fallback
    External-->>MapService: style URL or StyleSpecification
    MapService-->>Server: return mapStyle
    Server-->>Browser: loader payload { fields, mapStyle }
    Browser->>MapLibrary: Init MapGL with mapLib=maplibregl and mapStyle
    Browser->>GeocoderControl: forwardGeocode(query)
    GeocoderControl->>External: geocode request (maptiler/osm)
    External-->>GeocoderControl: geocode results
    GeocoderControl-->>Browser: display results as features
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Areas needing extra attention:
    • fdm-app/app/integrations/map.ts — provider branching, MapTiler key handling, fallback style correctness
    • fdm-app/app/components/blocks/atlas/atlas-geocoder.tsx — custom forwardGeocode network/error handling and feature transformation
    • Route loaders and call sites — ensure all callers updated to expect mapStyle instead of mapboxToken/mapboxStyle
    • Dependency/type changes — verify dev deps (@types/maplibre-gl) and CSS imports behave at runtime

Possibly related issues

Possibly related PRs

Suggested reviewers

  • BoraIneviNMI
  • gerardhros

Poem

🐰 MapLibre hops in, Mapbox hops out,
Provider flags flutter and rabbits shout.
Styles fetched, geocoders call with cheer,
Types updated, the atlas shifts gear.
Hooray — open maps across the warren, dear!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: migrating from Mapbox GL to MapLibre GL and adding dual provider support (maptiler and osm), which aligns with the comprehensive changeset across multiple files.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch FDM347

Tip

✨ Issue Enrichment is now available for GitHub issues!

CodeRabbit can now help you manage issues more effectively:

  • Duplicate Detection — Identify similar or duplicate issues
  • Related Issues & PRs — Find relevant issues and PR's from your repository
  • Suggested Assignees — Find the best person to work on the issue
  • Implementation Planning — Generate detailed coding plans for engineers and agents
Disable automatic issue enrichment

To disable automatic issue enrichment, add the following to your .coderabbit.yaml:

issue_enrichment:
  auto_enrich:
    enabled: false

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented Nov 28, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.62%. Comparing base (58209df) to head (66da6d5).
⚠️ Report is 13 commits behind head on development.

Additional details and impacted files
@@             Coverage Diff              @@
##           development     #359   +/-   ##
============================================
  Coverage        87.62%   87.62%           
============================================
  Files               79       79           
  Lines             3959     3959           
  Branches          1145     1145           
============================================
  Hits              3469     3469           
  Misses             490      490           
Flag Coverage Δ
fdm-calculator 87.81% <ø> (ø)
fdm-core 87.08% <ø> (ø)
fdm-data 92.12% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot changed the title @coderabbitai Migrate from Mapbox GL to MapLibre GL with dual provider support Nov 28, 2025
@coderabbitai coderabbitai Bot added branch:development Issue only affecting development, not the main branch (yet) dependencies Pull requests that update a dependency file enhancement New feature or request fdm-app labels Nov 28, 2025
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx (2)

36-42: Update outdated JSDoc to reflect MapLibre migration.

The JSDoc comment still references "Mapbox configuration" and "Mapbox access token" but the implementation now uses MapLibre with getMapStyle. Update the documentation to accurately describe the current behavior.

 /**
- * Loads field data and Mapbox configuration for rendering a farm field on the map.
+ * Loads field data and map configuration for rendering a farm field on the map.
  *
- * This function retrieves a farm field's details using the field ID from the route parameters. It establishes a valid user session and uses it to fetch the corresponding field data. The retrieved field details are formatted into a GeoJSON FeatureCollection, and Mapbox configuration values (access token and style) are provided for map rendering.
+ * This function retrieves a farm field's details using the field ID from the route parameters. It establishes a valid user session and uses it to fetch the corresponding field data. The retrieved field details are formatted into a GeoJSON FeatureCollection, and map style configuration is provided for rendering.
  *
- * @returns An object containing the field's GeoJSON FeatureCollection, Mapbox access token, and Mapbox style.
+ * @returns An object containing the field's GeoJSON FeatureCollection and map style.
  *

95-99: Update JSDoc to reflect MapLibre migration.

The JSDoc still references "Mapbox map" but the implementation now uses MapLibre.

 /**
- * Renders a map view of a farm field.
+ * Renders a MapLibre map view of a farm field.
  *
- * This component uses data retrieved from the loader to display a non-interactive Mapbox map with the field overlaid as a styled layer. It computes the view state and field styles, then conditionally renders the map on the client side with a skeleton fallback.
+ * This component uses data retrieved from the loader to display a non-interactive map with the field overlaid as a styled layer. It computes the view state and field styles, then conditionally renders the map on the client side with a skeleton fallback.
🧹 Nitpick comments (10)
fdm-app/app/components/blocks/atlas/atlas-styles.tsx (1)

23-23: Type cast to any bypasses type safety.

The as any cast circumvents TypeScript's type checking for the expression specification. While this may be necessary if MapLibre's ExpressionSpecification type doesn't accommodate the dynamic array construction, consider verifying whether a more type-safe approach exists.

fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx (1)

91-103: Update JSDoc to reflect MapLibre migration.

The JSDoc still references "Mapbox configuration (token and style)" at line 97, but the implementation now uses MapLibre. Consider updating the documentation to match the current implementation.

fdm-app/app/integrations/map.ts (2)

23-28: Consider using multiple OSM tile servers for improved reliability.

Using only a.tile.openstreetmap.org may cause load issues. OSM provides subdomains a, b, and c for load balancing.

             sources: {
                 "osm": {
                     type: "raster",
-                    tiles: ["https://a.tile.openstreetmap.org/{z}/{x}/{y}.png"],
+                    tiles: [
+                        "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png",
+                        "https://b.tile.openstreetmap.org/{z}/{x}/{y}.png",
+                        "https://c.tile.openstreetmap.org/{z}/{x}/{y}.png",
+                    ],
                     tileSize: 256,
                     attribution: "&copy; OpenStreetMap Contributors",
                 },
             },

14-15: Document the hard-coded MapTiler satellite style ID.

The style ID 019aca7b-e3d9-7dc7-9b70-84318d91dc9a is not self-documenting. Consider adding a comment or extracting it to a named constant for clarity.

+        // MapTiler Satellite Hybrid style
+        const MAPTILER_SATELLITE_STYLE_ID = "019aca7b-e3d9-7dc7-9b70-84318d91dc9a"
         if (variant === "standard") {
             return `https://api.maptiler.com/maps/streets/style.json?key=${maptilerKey}`
         }
-        return `https://api.maptiler.com/maps/019aca7b-e3d9-7dc7-9b70-84318d91dc9a/style.json?key=${maptilerKey}`
+        return `https://api.maptiler.com/maps/${MAPTILER_SATELLITE_STYLE_ID}/style.json?key=${maptilerKey}`
fdm-app/app/components/blocks/atlas/atlas-geocoder.tsx (2)

54-54: Consider making the geocoder language configurable.

The accept-language=nl is hardcoded. If the app supports internationalization, consider deriving this from user locale or app configuration.


37-38: Consider adding types for geocoder config and features.

Using any for config and features reduces type safety. Consider defining proper interfaces for the geocoder API configuration and feature structures.

+interface GeocoderConfig {
+    query: string
+    limit?: number
+}
+
+interface GeocoderFeature {
+    id: string | number
+    type: "Feature"
+    geometry: { type: "Point"; coordinates: [number, number] }
+    properties: Record<string, unknown>
+    place_name: string
+    place_type: string[]
+    text: string
+    center: [number, number]
+    bbox?: [number, number, number, number]
+}
+
         const geocoderApi = {
-            forwardGeocode: async (config: any) => {
-                const features: any[] = []
+            forwardGeocode: async (config: GeocoderConfig) => {
+                const features: GeocoderFeature[] = []
fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx (1)

70-81: Update JSDoc to reflect MapLibre migration.

The JSDoc at lines 73, 77, and 81 still references "Mapbox token" and "Mapbox style". Update to reflect the current MapLibre implementation.

 /**
  * Retrieves farm details and map configurations for rendering the farm map.
  *
- * This loader function extracts the farm ID from route parameters, validates its presence, and uses the current session to fetch the corresponding farm details. It then retrieves the Mapbox token and style configuration, and returns these along with the farm's display name and a URL for available fields. Any errors encountered during processing are transformed using {@link handleLoaderError}.
+ * This loader function extracts the farm ID from route parameters, validates its presence, and uses the current session to fetch the corresponding farm details. It then retrieves the map style configuration, and returns these along with the farm's display name and a URL for available fields. Any errors encountered during processing are transformed using {@link handleLoaderError}.
  *
  * @throws {Response} When the farm ID is missing, the specified farm is not found, or another error occurs during data retrieval.
  *
- * @returns An object containing the farm name, Mapbox token, Mapbox style, and the URL for available fields.
+ * @returns An object containing the farm name, map style, and the URL for available fields.
  */
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx (1)

74-82: Update JSDoc to reflect MapLibre migration.

The JSDoc references "Mapbox token and style configuration" and "Mapbox token, Mapbox style" but the implementation now uses MapLibre with a unified mapStyle.

fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (1)

37-50: Update JSDoc to reflect MapLibre migration.

Multiple JSDoc blocks reference "Mapbox" (lines 38, 43, 47-48, 108). Update to reflect the current MapLibre implementation.

 /**
- * Loads and processes farm field data along with Mapbox configuration for rendering the farm atlas.
+ * Loads and processes farm field data along with map configuration for rendering the farm atlas.
  *
  * This loader function extracts the farm ID from the route parameters and validates its presence,
  * retrieves the current user session, and fetches fields associated with the specified farm.
  * It converts these fields into a GeoJSON FeatureCollection—rounding the field area values for precision—
- * and obtains the Mapbox access token and style configuration for map rendering.
+ * and obtains the map style configuration for rendering.
  *
  * @returns An object containing:
  *  - savedFields: A GeoJSON FeatureCollection of the farm fields.
- *  - mapboxToken: The Mapbox access token.
- *  - mapboxStyle: The Mapbox style configuration.
+ *  - mapStyle: The map style configuration.

Also applies to: 108-109

fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx (1)

113-118: Consider proper typing instead of as any cast.

The as any cast bypasses type safety. The bounds check is a good defensive guard, but consider defining a proper type for the view state that includes the optional bounds and fitBoundsOptions properties.

+interface ViewStateWithBounds {
+    bounds?: [[number, number], [number, number]]
+    fitBoundsOptions?: { padding?: number; duration?: number }
+    // ... other viewState properties
+}
+
 useEffect(() => {
-    const vs = viewState as any
-    if (vs.bounds) {
-        mapRef.current?.fitBounds(vs.bounds, vs.fitBoundsOptions)
+    const vs = viewState as ViewStateWithBounds
+    if (vs.bounds) {
+        mapRef.current?.fitBounds(vs.bounds, vs.fitBoundsOptions)
     }
 }, [viewState])

Alternatively, update getViewState to return a properly typed object that includes these properties.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 88758e0 and 7c40a9b.

⛔ Files ignored due to path filters (4)
  • fdm-app/app/lib/cache.server.ts is excluded by !fdm-app/app/lib/**
  • fdm-app/app/lib/config.server.ts is excluded by !fdm-app/app/lib/**
  • fdm-app/app/lib/config.ts is excluded by !fdm-app/app/lib/**
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (20)
  • .changeset/metal-fans-brush.md (1 hunks)
  • fdm-app/app/components/blocks/atlas/atlas-controls.tsx (4 hunks)
  • fdm-app/app/components/blocks/atlas/atlas-geocoder.tsx (3 hunks)
  • fdm-app/app/components/blocks/atlas/atlas-panels.tsx (1 hunks)
  • fdm-app/app/components/blocks/atlas/atlas-sources.tsx (6 hunks)
  • fdm-app/app/components/blocks/atlas/atlas-styles.tsx (2 hunks)
  • fdm-app/app/integrations/map.ts (1 hunks)
  • fdm-app/app/integrations/mapbox.ts (0 hunks)
  • fdm-app/app/root.tsx (3 hunks)
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx (0 hunks)
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (5 hunks)
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx (0 hunks)
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx (6 hunks)
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx (5 hunks)
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx (4 hunks)
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx (5 hunks)
  • fdm-app/app/tailwind.css (1 hunks)
  • fdm-app/app/types/config.d.ts (2 hunks)
  • fdm-app/app/types/public-env.d.ts (1 hunks)
  • fdm-app/package.json (3 hunks)
💤 Files with no reviewable changes (3)
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
  • fdm-app/app/integrations/mapbox.ts
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
🧰 Additional context used
🧠 Learnings (26)
📓 Common learnings
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2025-06-10T13:10:03.154Z
Learning: When facing prop name inconsistencies with react-map-gl (like mapboxAccessToken vs mapboxApiAccessToken), using different import statements can resolve the issue more elegantly than changing prop names across multiple files.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: Map configuration in the application should be modularized using the `useMapConfig` hook and `MapControls` component to maintain consistency across all MapGL instances.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2024-11-25T14:42:26.660Z
Learning: In `fdm-app/app/components/blocks/field-map.tsx`, explicit cleanup of Mapbox GL resources is not necessary, as `react-map-gl` handles it automatically upon component unmount, and `MapRef` does not have a `remove` method.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: MapGL implementations should use the shared `useMapConfig` hook for configuration and `getLayerStyle` utility for consistent styling. The hook supports both interactive and non-interactive maps, handling bounds calculation and view state management.
📚 Learning: 2025-02-19T10:50:50.200Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 82
File: fdm-app/app/entry.client.tsx:13-13
Timestamp: 2025-02-19T10:50:50.200Z
Learning: Sentry DSN being public in client-side code is not a security concern as per Sentry documentation, but it can be made configurable using Vite's environment variables system with the `VITE_` prefix.

Applied to files:

  • fdm-app/app/types/public-env.d.ts
  • fdm-app/app/root.tsx
📚 Learning: 2025-06-10T13:10:03.154Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2025-06-10T13:10:03.154Z
Learning: When facing prop name inconsistencies with react-map-gl (like mapboxAccessToken vs mapboxApiAccessToken), using different import statements can resolve the issue more elegantly than changing prop names across multiple files.

Applied to files:

  • fdm-app/app/root.tsx
  • fdm-app/app/components/blocks/atlas/atlas-panels.tsx
  • fdm-app/app/components/blocks/atlas/atlas-styles.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
  • fdm-app/package.json
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/components/blocks/atlas/atlas-sources.tsx
  • fdm-app/app/components/blocks/atlas/atlas-controls.tsx
  • fdm-app/app/components/blocks/atlas/atlas-geocoder.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
📚 Learning: 2024-11-25T14:42:26.660Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2024-11-25T14:42:26.660Z
Learning: In `fdm-app/app/components/blocks/field-map.tsx`, explicit cleanup of Mapbox GL resources is not necessary, as `react-map-gl` handles it automatically upon component unmount, and `MapRef` does not have a `remove` method.

Applied to files:

  • fdm-app/app/root.tsx
  • fdm-app/app/components/blocks/atlas/atlas-panels.tsx
  • fdm-app/app/tailwind.css
  • fdm-app/app/components/blocks/atlas/atlas-styles.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
  • fdm-app/package.json
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/components/blocks/atlas/atlas-sources.tsx
  • fdm-app/app/components/blocks/atlas/atlas-controls.tsx
  • .changeset/metal-fans-brush.md
  • fdm-app/app/components/blocks/atlas/atlas-geocoder.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
📚 Learning: 2025-06-10T12:20:38.360Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:68-68
Timestamp: 2025-06-10T12:20:38.360Z
Learning: In react-map-gl v8.0.4, the correct prop name for the Mapbox access token in the MapGL component is `mapboxApiAccessToken`, not `mapboxAccessToken` as verified by checking the MapboxProps interface.

Applied to files:

  • fdm-app/app/root.tsx
  • fdm-app/app/components/blocks/atlas/atlas-panels.tsx
  • fdm-app/app/components/blocks/atlas/atlas-styles.tsx
  • fdm-app/app/types/config.d.ts
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/components/blocks/atlas/atlas-controls.tsx
  • fdm-app/app/components/blocks/atlas/atlas-geocoder.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
📚 Learning: 2025-06-10T12:20:38.360Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:68-68
Timestamp: 2025-06-10T12:20:38.360Z
Learning: When using MapGL component from react-map-gl, the correct prop name for the Mapbox access token is `mapboxApiAccessToken` as verified by checking the MapboxProps interface. This should be consistent across all usages of the MapGL component.

Applied to files:

  • fdm-app/app/root.tsx
  • fdm-app/app/components/blocks/atlas/atlas-panels.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/components/blocks/atlas/atlas-controls.tsx
  • fdm-app/app/components/blocks/atlas/atlas-geocoder.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
📚 Learning: 2025-01-31T16:06:33.810Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: Map configuration in the application should be modularized using the `useMapConfig` hook and `MapControls` component to maintain consistency across all MapGL instances.

Applied to files:

  • fdm-app/app/root.tsx
  • fdm-app/app/components/blocks/atlas/atlas-panels.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/components/blocks/atlas/atlas-sources.tsx
  • fdm-app/app/components/blocks/atlas/atlas-controls.tsx
  • fdm-app/app/components/blocks/atlas/atlas-geocoder.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
📚 Learning: 2024-12-16T10:56:07.561Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 16
File: fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx:1-1
Timestamp: 2024-12-16T10:56:07.561Z
Learning: The project uses `react-router` v7, and the `data` function is exported and used for error handling in loaders and actions.

Applied to files:

  • fdm-app/app/root.tsx
  • fdm-app/app/components/blocks/atlas/atlas-sources.tsx
📚 Learning: 2025-07-24T08:29:44.044Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 198
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.balance.nitrogen.$b_id.tsx:146-148
Timestamp: 2025-07-24T08:29:44.044Z
Learning: In React Router v7, the defer() function has been removed. Instead, loaders can return promises directly in the response object, and components use Suspense and Await to handle them without needing defer().

Applied to files:

  • fdm-app/app/root.tsx
📚 Learning: 2025-01-31T14:29:37.599Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas.d.tsx:8-8
Timestamp: 2025-01-31T14:29:37.599Z
Learning: In the Atlas component's MapFieldsProps interface, mapStyle is intentionally restricted to "mapbox://styles/mapbox/satellite-streets-v12" as it's currently the only supported style option.

Applied to files:

  • fdm-app/app/root.tsx
  • fdm-app/app/components/blocks/atlas/atlas-panels.tsx
  • fdm-app/app/integrations/map.ts
  • fdm-app/app/components/blocks/atlas/atlas-styles.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/components/blocks/atlas/atlas-sources.tsx
  • fdm-app/app/components/blocks/atlas/atlas-controls.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
📚 Learning: 2025-01-31T15:06:35.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas-sources.tsx:21-66
Timestamp: 2025-01-31T15:06:35.764Z
Learning: In react-map-gl components, when querying rendered features via map.queryRenderedFeatures(), the effect's dependency array must include any props that affect the map's rendered state (like source data) to ensure features are queried against the current map state.

Applied to files:

  • fdm-app/app/root.tsx
  • fdm-app/app/components/blocks/atlas/atlas-panels.tsx
  • fdm-app/app/components/blocks/atlas/atlas-styles.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/components/blocks/atlas/atlas-sources.tsx
  • fdm-app/app/components/blocks/atlas/atlas-controls.tsx
  • fdm-app/app/components/blocks/atlas/atlas-geocoder.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
📚 Learning: 2025-05-09T14:53:44.578Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/combobox.tsx:34-37
Timestamp: 2025-05-09T14:53:44.578Z
Learning: In the context of this React Router v7 project, it's important to follow the pattern of importing only the types (like UseFormReturn) from "react-hook-form" while importing the Form component from "react-router" to avoid naming conflicts.

Applied to files:

  • fdm-app/app/root.tsx
  • fdm-app/app/components/blocks/atlas/atlas-sources.tsx
📚 Learning: 2025-01-31T15:41:43.741Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas-panels.tsx:28-28
Timestamp: 2025-01-31T15:41:43.741Z
Learning: When handling different map event types in react-map-gl v7.1.8, use MapLayerMouseEvent for mouse events (which have the point property) and ViewStateChangeEvent for view state changes. Use a type guard like 'point' in evt to safely access event-specific properties.

Applied to files:

  • fdm-app/app/components/blocks/atlas/atlas-panels.tsx
  • fdm-app/app/components/blocks/atlas/atlas-styles.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/components/blocks/atlas/atlas-sources.tsx
  • fdm-app/app/components/blocks/atlas/atlas-controls.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
📚 Learning: 2025-01-31T16:06:33.810Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: MapGL implementations should use the shared `useMapConfig` hook for configuration and `getLayerStyle` utility for consistent styling. The hook supports both interactive and non-interactive maps, handling bounds calculation and view state management.

Applied to files:

  • fdm-app/app/integrations/map.ts
  • fdm-app/app/components/blocks/atlas/atlas-styles.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/components/blocks/atlas/atlas-sources.tsx
  • fdm-app/app/components/blocks/atlas/atlas-controls.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
📚 Learning: 2024-11-25T12:42:32.783Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/vite.config.ts:5-9
Timestamp: 2024-11-25T12:42:32.783Z
Learning: In the `fdm-app` project, SvenVw is preparing for migration to Remix v3 and may include type declarations or configurations for v3 features in advance, such as in `vite.config.ts`.

Applied to files:

  • fdm-app/app/types/config.d.ts
📚 Learning: 2025-01-09T16:03:37.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes/farm/_b_id_farm/layout.tsx:46-95
Timestamp: 2025-01-09T16:03:37.764Z
Learning: A shared layout component `FarmLayoutBase` has been created in `components/custom/farm-layout-base.tsx` to maintain consistency across farm-related pages. The component handles farm selection dropdown, breadcrumb navigation, and provides a common layout structure.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
📚 Learning: 2025-01-09T16:03:37.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes/farm/_b_id_farm/layout.tsx:46-95
Timestamp: 2025-01-09T16:03:37.764Z
Learning: The `FarmLayout` component in `components/custom/farm-layout.tsx` provides a reusable layout structure for farm-related pages, with support for farm selection dropdown, customizable breadcrumb titles, and flexible content rendering through either children or Outlet components.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
📚 Learning: 2025-09-23T12:29:34.184Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 274
File: fdm-app/app/routes/farm.$b_id_farm._index.tsx:160-163
Timestamp: 2025-09-23T12:29:34.184Z
Learning: In the FDM application, the fertilizer application route intentionally uses `${calendar}/field/fertilizer` instead of the originally planned `/farm/{farmId}/add/fertilizer` structure. This design decision prioritizes starting from the field list view to provide better field selection workflow before applying fertilizer, rather than direct dashboard-to-action navigation.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
📚 Learning: 2025-01-09T16:03:37.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes/farm/_b_id_farm/layout.tsx:46-95
Timestamp: 2025-01-09T16:03:37.764Z
Learning: A comprehensive farm layout system has been created in `components/custom/farm-layouts/` with `BaseFarmLayout` and `FarmSidebarLayout` components. The system supports both simple and sidebar-based layouts while maintaining consistent header and farm selection functionality across all farm routes.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
📚 Learning: 2025-06-02T10:31:27.097Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 151
File: fdm-app/app/routes/signin._index.tsx:101-101
Timestamp: 2025-06-02T10:31:27.097Z
Learning: In fdm-app/app/routes/signin._index.tsx, the redirect destinations are intentionally inconsistent by design: the component defaults new sign-ins to "/welcome" (line 101) while the loader redirects authenticated users to "/farm" (line 80) and the action uses "/farm" as fallback (line 434). This creates appropriate user flows where new users complete their profile via the welcome page, while existing authenticated users bypass it and go directly to the main application.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
📚 Learning: 2025-01-09T16:03:37.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes/farm/_b_id_farm/layout.tsx:46-95
Timestamp: 2025-01-09T16:03:37.764Z
Learning: The farm layout system has been reorganized into separate components (`FarmHeader`, `ContentLayout`, `PaginationLayout`) to support different navigation patterns (sidebar, pagination) while maintaining consistent styling. Each layout component is designed to be used independently or combined as needed.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
📚 Learning: 2025-08-11T12:24:32.200Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 233
File: fdm-app/app/components/blocks/atlas-fields/cultivation-history.tsx:53-53
Timestamp: 2025-08-11T12:24:32.200Z
Learning: In `fdm-app/app/components/blocks/atlas-fields/cultivation-history.tsx`, the NMI API for cultivations guarantees that each year will be unique in the cultivation history data, so using `cultivation.year` as a React list key is safe and won't cause duplicate key warnings.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/components/blocks/atlas/atlas-sources.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
📚 Learning: 2025-09-26T08:34:50.413Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 279
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.norms.tsx:277-283
Timestamp: 2025-09-26T08:34:50.413Z
Learning: In the fdm project, fdm-core and fdm-app are updated together as part of a monorepo structure, which eliminates legacy data concerns when new fields like b_isproductive are introduced. Both packages are synchronized, so there's no need for defensive coding against undefined values for newly introduced database fields.

Applied to files:

  • fdm-app/package.json
📚 Learning: 2025-05-09T14:58:10.465Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/combobox.tsx:34-37
Timestamp: 2025-05-09T14:58:10.465Z
Learning: When updating React components that use both react-hook-form and React Router v7, it's important to only import types (like UseFormReturn, FieldValues) from react-hook-form to avoid naming conflicts with React Router's Form component. Use `import type { ... } from 'react-hook-form'` syntax to ensure only types are imported.

Applied to files:

  • fdm-app/app/components/blocks/atlas/atlas-sources.tsx
📚 Learning: 2025-01-31T15:05:14.310Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.fields.$b_id.tsx:601-610
Timestamp: 2025-01-31T15:05:14.310Z
Learning: The `updateField` function in fdm-core has optional parameters after `fdm` and `b_id`. The TypeScript definitions might show 8 required parameters due to a potential version mismatch.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
📚 Learning: 2025-01-31T15:34:20.850Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.fields.$b_id.tsx:601-610
Timestamp: 2025-01-31T15:34:20.850Z
Learning: The `updateField` function in fdm-core has optional parameters that don't need to be passed as undefined. Only `fdm` and `b_id` are required.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
🧬 Code graph analysis (5)
fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx (1)
fdm-app/app/integrations/map.ts (1)
  • getMapStyle (4-65)
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx (1)
fdm-app/app/integrations/map.ts (1)
  • getMapStyle (4-65)
fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx (1)
fdm-app/app/integrations/map.ts (1)
  • getMapStyle (4-65)
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx (1)
fdm-app/app/integrations/map.ts (1)
  • getMapStyle (4-65)
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (1)
fdm-app/app/integrations/map.ts (1)
  • getMapStyle (4-65)
⏰ Context from checks skipped due to timeout of 300000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: core (24)
🔇 Additional comments (22)
.changeset/metal-fans-brush.md (1)

1-5: LGTM!

The changeset file is correctly formatted and appropriately documents the patch version bump for the Mapbox to MapLibre migration. The description clearly communicates the intent of the changes.

fdm-app/app/components/blocks/atlas/atlas-sources.tsx (1)

60-60: LGTM: Type safety and null checks improved.

The explicit MapLayerMouseEvent typing and property guards enhance type safety and prevent potential runtime errors during the MapLibre migration. The null checks for setFieldsData and property guards for feature comparisons are defensive coding best practices.

Also applies to: 80-81, 117-130

fdm-app/package.json (1)

21-21: Let me also check the maplibre-gl version:
<function_calls>

maplibre-gl latest stable version npm registry 2025

</function_calls>

And let me retrieve the actual package.json content to see the versions currently specified:
<function_calls>


#!/bin/bash

Find all package.json files and show maplibre-related dependencies

find . -name "package.json" -path "/fdm-app/" -type f -exec grep -l "maplibre" {} ;


</function_calls>

fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx (3)

15-16: LGTM on MapLibre import migration.

The imports are correctly updated to use react-map-gl/maplibre and maplibre-gl for the MapLibre integration.


197-198: LGTM on loader data shape update.

The loader correctly returns mapStyle from the centralized getMapStyle utility, aligning with the migration pattern across the codebase.

Also applies to: 211-211


385-386: LGTM on MapGL props update.

The MapGL component correctly receives mapStyle and mapLib={maplibregl}, consistent with the MapLibre migration pattern. Based on learnings, using different import statements (react-map-gl/maplibre) resolves prop name inconsistencies elegantly.

fdm-app/app/components/blocks/atlas/atlas-geocoder.tsx (2)

153-156: LGTM on MapLibre integration.

The onAdd method correctly accepts MapLibreMap type and the as any cast for the geocoder's internal onAdd is an acceptable workaround for library type mismatches.


36-48: The MapTiler response format is already correct and requires no transformation.

Based on web search verification:

  • MapTiler API natively returns a GeoJSON FeatureCollection with type: "FeatureCollection" and a features array—the exact format that MapLibre GL geocoder expects.
  • OSM/Nominatim returns a plain JSON array, which is why the code wraps it as { features } to match the FeatureCollection format.

Returning MapTiler's response directly (line 48: return data) is correct. The apparent "inconsistency" with the OSM branch is intentional and necessary because the two APIs return different base structures. No additional transformation of the MapTiler response is needed.

fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx (3)

18-19: LGTM on MapLibre imports.

Imports correctly updated for MapLibre migration.

Also applies to: 49-49


171-172: LGTM on loader and MapGL integration.

The loader correctly returns mapStyle and the MapGL component properly uses mapStyle and mapLib={maplibregl}.

Also applies to: 182-182, 300-301


351-356: Type cast workaround for Layer layout prop.

The as any cast is a reasonable workaround when merging layout into the style object. This pattern is consistent across the codebase.

fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx (2)

22-23: LGTM on MapLibre imports.

Imports correctly updated for MapLibre migration.

Also applies to: 53-53


161-162: LGTM on loader and MapGL integration.

The migration is correctly implemented with getMapStyle("satellite") in the loader and proper MapGL props.

Also applies to: 170-170, 262-263

fdm-app/app/components/blocks/atlas/atlas-controls.tsx (2)

2-2: LGTM on MapLibre type and import updates.

Types correctly updated from Mapbox to MapLibre.

Also applies to: 10-10


57-57: LGTM on MapLibre CSS class and type updates.

CSS classes correctly migrated from mapboxgl-* to maplibregl-*, and _map property type updated to MapLibreMap.

Also applies to: 73-73, 82-82, 85-85

fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (3)

9-10: LGTM on MapLibre imports.

Imports correctly updated for MapLibre migration.

Also applies to: 19-19


94-95: LGTM on loader and MapGL integration.

The migration is correctly implemented, consistent with the broader MapLibre migration pattern across the codebase.

Also applies to: 101-101, 164-165


190-192: Type cast workaround for Layer layout prop.

The as any cast is consistent with the pattern used in other files for merging layout into the style object.

fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx (4)

4-5: LGTM! Clean migration to MapLibre imports.

Using react-map-gl/maplibre is the correct approach for MapLibre integration, which elegantly handles prop name differences compared to the Mapbox variant. Based on learnings, this import pattern resolves prop inconsistencies more cleanly than changing prop names across multiple files.


66-67: Good use of as const for type narrowing.

Using "Feature" as const ensures the type is narrowed to the literal "Feature" rather than string, which is correct for GeoJSON typing.


140-145: Verify interactiveLayerIds usage with interactive={false}.

The map is set to interactive={false} but interactiveLayerIds is still specified. While this may be intentional (perhaps for future use or consistency with other map instances), consider removing interactiveLayerIds if the map will never be interactive, as it's unnecessary.


174-184: Action function validates but returns nothing.

The action validates the presence of b_id but doesn't perform any action or return a value. If this is intentional (e.g., a placeholder for future functionality), consider adding a comment. Otherwise, verify if this action should be removed or if it's missing implementation.

Comment thread fdm-app/app/integrations/map.ts
@SvenVw SvenVw linked an issue Nov 28, 2025 that may be closed by this pull request
6 tasks
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
fdm-app/app/integrations/map.ts (1)

10-13: Consider extracting MapTiler style IDs as named constants.

The satellite style uses a hardcoded UUID (019aca7b-e3d9-7dc7-9b70-84318d91dc9a) which appears to be a custom MapTiler style. Consider extracting this to a named constant with a brief comment explaining what this style represents, improving maintainability.

+// MapTiler style identifiers
+const MAPTILER_STREETS_STYLE = "streets"
+const MAPTILER_SATELLITE_STYLE = "019aca7b-e3d9-7dc7-9b70-84318d91dc9a" // Custom satellite hybrid style
+
 export function getMapStyle(variant: "satellite" | "standard"): string | StyleSpecification {
     const { provider, maptilerKey } = clientConfig.integrations.map

     if (provider === "maptiler") {
         if (maptilerKey) {
             // MapTiler styles
             if (variant === "standard") {
-                return `https://api.maptiler.com/maps/streets/style.json?key=${maptilerKey}`
+                return `https://api.maptiler.com/maps/${MAPTILER_STREETS_STYLE}/style.json?key=${maptilerKey}`
             }
-            return `https://api.maptiler.com/maps/019aca7b-e3d9-7dc7-9b70-84318d91dc9a/style.json?key=${maptilerKey}`
+            return `https://api.maptiler.com/maps/${MAPTILER_SATELLITE_STYLE}/style.json?key=${maptilerKey}`
         }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7c40a9b and ad6966b.

📒 Files selected for processing (1)
  • fdm-app/app/integrations/map.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: MapGL implementations should use the shared `useMapConfig` hook for configuration and `getLayerStyle` utility for consistent styling. The hook supports both interactive and non-interactive maps, handling bounds calculation and view state management.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: Map configuration in the application should be modularized using the `useMapConfig` hook and `MapControls` component to maintain consistency across all MapGL instances.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2025-06-10T13:10:03.154Z
Learning: When facing prop name inconsistencies with react-map-gl (like mapboxAccessToken vs mapboxApiAccessToken), using different import statements can resolve the issue more elegantly than changing prop names across multiple files.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas.d.tsx:8-8
Timestamp: 2025-01-31T14:29:37.599Z
Learning: In the Atlas component's MapFieldsProps interface, mapStyle is intentionally restricted to "mapbox://styles/mapbox/satellite-streets-v12" as it's currently the only supported style option.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2024-11-25T14:42:26.660Z
Learning: In `fdm-app/app/components/blocks/field-map.tsx`, explicit cleanup of Mapbox GL resources is not necessary, as `react-map-gl` handles it automatically upon component unmount, and `MapRef` does not have a `remove` method.
📚 Learning: 2025-01-31T14:29:37.599Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas.d.tsx:8-8
Timestamp: 2025-01-31T14:29:37.599Z
Learning: In the Atlas component's MapFieldsProps interface, mapStyle is intentionally restricted to "mapbox://styles/mapbox/satellite-streets-v12" as it's currently the only supported style option.

Applied to files:

  • fdm-app/app/integrations/map.ts
📚 Learning: 2025-01-31T16:06:33.810Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: MapGL implementations should use the shared `useMapConfig` hook for configuration and `getLayerStyle` utility for consistent styling. The hook supports both interactive and non-interactive maps, handling bounds calculation and view state management.

Applied to files:

  • fdm-app/app/integrations/map.ts
📚 Learning: 2025-06-10T12:20:38.360Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:68-68
Timestamp: 2025-06-10T12:20:38.360Z
Learning: When using MapGL component from react-map-gl, the correct prop name for the Mapbox access token is `mapboxApiAccessToken` as verified by checking the MapboxProps interface. This should be consistent across all usages of the MapGL component.

Applied to files:

  • fdm-app/app/integrations/map.ts
🔇 Additional comments (1)
fdm-app/app/integrations/map.ts (1)

21-44: Well-structured fallback with proper attribution.

The fallback styles are correctly implemented with required attributions for OSM and Esri. The inline StyleSpecification objects are valid and type-safe.

One consideration: OpenStreetMap's tile usage policy requires that heavy usage (production apps) use a commercial provider or self-hosted tiles. Since this is a fallback path (when MapTiler key is missing), this should be acceptable for development/emergency use, but ensure production deployments have a valid MapTiler key configured.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (1)

190-192: Type assertion to any bypasses type checking.

The as any cast works around a type mismatch when merging fieldsAvailableStyle with the layout property. While functional, this suppresses potential type errors.

Consider defining a proper type or using a more specific assertion if the Layer component's props type is available:

-<Layer
-    {...({ ...fieldsAvailableStyle, layout: layerLayout } as any)}
-/>
+<Layer
+    {...fieldsAvailableStyle}
+    layout={layerLayout}
+/>

If the above doesn't compile due to type constraints, the current approach is acceptable as a pragmatic workaround for the library migration.

fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx (1)

114-117: Type assertion to any masks potential type mismatch.

The cast viewState as any to access bounds and fitBoundsOptions suggests that getViewState returns a type that doesn't expose these properties, even though the implementation may include them.

Consider updating the return type of getViewState in atlas-viewstate.ts to properly expose bounds and fitBoundsOptions, which would eliminate the need for this cast and improve type safety:

-const vs = viewState as any
-if (vs.bounds) {
-    mapRef.current?.fitBounds(vs.bounds, vs.fitBoundsOptions)
-}
+if ('bounds' in viewState && viewState.bounds) {
+    mapRef.current?.fitBounds(
+        viewState.bounds as LngLatBoundsLike,
+        viewState.fitBoundsOptions
+    )
+}

Alternatively, update getViewState's return type to include bounds?: LngLatBoundsLike and fitBoundsOptions?: FitBoundsOptions.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ad6966b and c421252.

📒 Files selected for processing (6)
  • fdm-app/app/integrations/map.ts (1 hunks)
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (6 hunks)
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx (7 hunks)
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx (6 hunks)
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx (5 hunks)
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • fdm-app/app/integrations/map.ts
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx
🧰 Additional context used
🧠 Learnings (19)
📓 Common learnings
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: Map configuration in the application should be modularized using the `useMapConfig` hook and `MapControls` component to maintain consistency across all MapGL instances.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: MapGL implementations should use the shared `useMapConfig` hook for configuration and `getLayerStyle` utility for consistent styling. The hook supports both interactive and non-interactive maps, handling bounds calculation and view state management.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2024-11-25T14:42:26.660Z
Learning: In `fdm-app/app/components/blocks/field-map.tsx`, explicit cleanup of Mapbox GL resources is not necessary, as `react-map-gl` handles it automatically upon component unmount, and `MapRef` does not have a `remove` method.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2025-06-10T13:10:03.154Z
Learning: When facing prop name inconsistencies with react-map-gl (like mapboxAccessToken vs mapboxApiAccessToken), using different import statements can resolve the issue more elegantly than changing prop names across multiple files.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas.d.tsx:8-8
Timestamp: 2025-01-31T14:29:37.599Z
Learning: In the Atlas component's MapFieldsProps interface, mapStyle is intentionally restricted to "mapbox://styles/mapbox/satellite-streets-v12" as it's currently the only supported style option.
📚 Learning: 2025-01-09T16:03:37.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes/farm/_b_id_farm/layout.tsx:46-95
Timestamp: 2025-01-09T16:03:37.764Z
Learning: A shared layout component `FarmLayoutBase` has been created in `components/custom/farm-layout-base.tsx` to maintain consistency across farm-related pages. The component handles farm selection dropdown, breadcrumb navigation, and provides a common layout structure.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2024-11-25T14:42:26.660Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2024-11-25T14:42:26.660Z
Learning: In `fdm-app/app/components/blocks/field-map.tsx`, explicit cleanup of Mapbox GL resources is not necessary, as `react-map-gl` handles it automatically upon component unmount, and `MapRef` does not have a `remove` method.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-06-10T13:10:03.154Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2025-06-10T13:10:03.154Z
Learning: When facing prop name inconsistencies with react-map-gl (like mapboxAccessToken vs mapboxApiAccessToken), using different import statements can resolve the issue more elegantly than changing prop names across multiple files.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-01-09T16:03:37.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes/farm/_b_id_farm/layout.tsx:46-95
Timestamp: 2025-01-09T16:03:37.764Z
Learning: The `FarmLayout` component in `components/custom/farm-layout.tsx` provides a reusable layout structure for farm-related pages, with support for farm selection dropdown, customizable breadcrumb titles, and flexible content rendering through either children or Outlet components.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-06-02T10:31:27.097Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 151
File: fdm-app/app/routes/signin._index.tsx:101-101
Timestamp: 2025-06-02T10:31:27.097Z
Learning: In fdm-app/app/routes/signin._index.tsx, the redirect destinations are intentionally inconsistent by design: the component defaults new sign-ins to "/welcome" (line 101) while the loader redirects authenticated users to "/farm" (line 80) and the action uses "/farm" as fallback (line 434). This creates appropriate user flows where new users complete their profile via the welcome page, while existing authenticated users bypass it and go directly to the main application.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
📚 Learning: 2025-01-09T16:03:37.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes/farm/_b_id_farm/layout.tsx:46-95
Timestamp: 2025-01-09T16:03:37.764Z
Learning: A comprehensive farm layout system has been created in `components/custom/farm-layouts/` with `BaseFarmLayout` and `FarmSidebarLayout` components. The system supports both simple and sidebar-based layouts while maintaining consistent header and farm selection functionality across all farm routes.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
📚 Learning: 2025-08-11T12:24:32.200Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 233
File: fdm-app/app/components/blocks/atlas-fields/cultivation-history.tsx:53-53
Timestamp: 2025-08-11T12:24:32.200Z
Learning: In `fdm-app/app/components/blocks/atlas-fields/cultivation-history.tsx`, the NMI API for cultivations guarantees that each year will be unique in the cultivation history data, so using `cultivation.year` as a React list key is safe and won't cause duplicate key warnings.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
📚 Learning: 2025-09-23T12:29:34.184Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 274
File: fdm-app/app/routes/farm.$b_id_farm._index.tsx:160-163
Timestamp: 2025-09-23T12:29:34.184Z
Learning: In the FDM application, the fertilizer application route intentionally uses `${calendar}/field/fertilizer` instead of the originally planned `/farm/{farmId}/add/fertilizer` structure. This design decision prioritizes starting from the field list view to provide better field selection workflow before applying fertilizer, rather than direct dashboard-to-action navigation.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
📚 Learning: 2025-01-31T14:29:37.599Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas.d.tsx:8-8
Timestamp: 2025-01-31T14:29:37.599Z
Learning: In the Atlas component's MapFieldsProps interface, mapStyle is intentionally restricted to "mapbox://styles/mapbox/satellite-streets-v12" as it's currently the only supported style option.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-01-31T15:06:35.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas-sources.tsx:21-66
Timestamp: 2025-01-31T15:06:35.764Z
Learning: In react-map-gl components, when querying rendered features via map.queryRenderedFeatures(), the effect's dependency array must include any props that affect the map's rendered state (like source data) to ensure features are queried against the current map state.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-01-31T15:41:43.741Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas-panels.tsx:28-28
Timestamp: 2025-01-31T15:41:43.741Z
Learning: When handling different map event types in react-map-gl v7.1.8, use MapLayerMouseEvent for mouse events (which have the point property) and ViewStateChangeEvent for view state changes. Use a type guard like 'point' in evt to safely access event-specific properties.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-01-31T16:06:33.810Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: MapGL implementations should use the shared `useMapConfig` hook for configuration and `getLayerStyle` utility for consistent styling. The hook supports both interactive and non-interactive maps, handling bounds calculation and view state management.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-01-31T16:06:33.810Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: Map configuration in the application should be modularized using the `useMapConfig` hook and `MapControls` component to maintain consistency across all MapGL instances.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-06-10T12:20:38.360Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:68-68
Timestamp: 2025-06-10T12:20:38.360Z
Learning: When using MapGL component from react-map-gl, the correct prop name for the Mapbox access token is `mapboxApiAccessToken` as verified by checking the MapboxProps interface. This should be consistent across all usages of the MapGL component.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-06-10T12:20:38.360Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:68-68
Timestamp: 2025-06-10T12:20:38.360Z
Learning: In react-map-gl v8.0.4, the correct prop name for the Mapbox access token in the MapGL component is `mapboxApiAccessToken`, not `mapboxAccessToken` as verified by checking the MapboxProps interface.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-01-31T15:05:14.310Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.fields.$b_id.tsx:601-610
Timestamp: 2025-01-31T15:05:14.310Z
Learning: The `updateField` function in fdm-core has optional parameters after `fdm` and `b_id`. The TypeScript definitions might show 8 required parameters due to a potential version mismatch.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
📚 Learning: 2025-01-31T15:34:20.850Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.fields.$b_id.tsx:601-610
Timestamp: 2025-01-31T15:34:20.850Z
Learning: The `updateField` function in fdm-core has optional parameters that don't need to be passed as undefined. Only `fdm` and `b_id` are required.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx
📚 Learning: 2025-01-09T16:03:37.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes/farm/_b_id_farm/layout.tsx:46-95
Timestamp: 2025-01-09T16:03:37.764Z
Learning: The farm layout system has been reorganized into separate components (`FarmHeader`, `ContentLayout`, `PaginationLayout`) to support different navigation patterns (sidebar, pagination) while maintaining consistent styling. Each layout component is designed to be used independently or combined as needed.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
🧬 Code graph analysis (4)
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx (1)
fdm-app/app/integrations/map.ts (1)
  • getMapStyle (4-23)
fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx (1)
fdm-app/app/integrations/map.ts (1)
  • getMapStyle (4-23)
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (1)
fdm-app/app/integrations/map.ts (1)
  • getMapStyle (4-23)
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx (1)
fdm-app/app/integrations/map.ts (1)
  • getMapStyle (4-23)
🔇 Additional comments (13)
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.$b_id._index.tsx (3)

15-16: LGTM!

The import migration from react-map-gl/mapbox to react-map-gl/maplibre and addition of maplibregl import is correctly implemented for the MapLibre integration.


197-198: LGTM!

The loader correctly uses getMapStyle("satellite") and returns the unified mapStyle property, aligning with the new MapLibre-based configuration pattern.

Also applies to: 211-211


385-386: LGTM!

The MapGL component correctly receives mapStyle from loader data and mapLib={maplibregl} as required by the MapLibre integration.

fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (2)

9-10: LGTM!

The import migration to react-map-gl/maplibre, maplibregl, and getMapStyle is correctly implemented.

Also applies to: 19-19


94-95: LGTM!

The loader correctly uses getMapStyle("satellite") and returns the unified mapStyle property.

Also applies to: 101-101

fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx (4)

22-23: LGTM!

The import migration to react-map-gl/maplibre, maplibregl, and getMapStyle is correctly implemented.

Also applies to: 53-53


161-162: LGTM!

The loader correctly uses getMapStyle("satellite") and returns the unified mapStyle property, consistent with the migration pattern across other routes.

Also applies to: 170-170


262-263: LGTM!

The MapGL component correctly receives mapStyle from loader data and mapLib={maplibregl}.


311-316: Consistent use of type assertion for Layer props.

Same as any pattern as in farm.$b_id_farm.$calendar.atlas.fields._index.tsx. This is acceptable as a pragmatic workaround during the library migration.

Also applies to: 326-331

fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx (4)

4-5: LGTM!

The import migration to react-map-gl/maplibre, maplibregl, and getMapStyle is correctly implemented.

Also applies to: 19-19


67-67: LGTM!

Using "Feature" as const for the type property improves type narrowing and ensures TypeScript infers the literal type correctly.


82-83: LGTM!

The loader correctly uses getMapStyle("satellite") and returns the unified mapStyle property.

Also applies to: 88-88


142-143: LGTM!

The MapGL component correctly receives mapStyle from loader data and mapLib={maplibregl}.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx (1)

7-7: Remove unused import.

useLoaderData is imported but never used in the component (the component only renders a placeholder message).

-    useLoaderData,
♻️ Duplicate comments (1)
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (1)

37-48: Align loader JSDoc with actual return shape and behavior

The implementation now only fetches a style (no token) and returns it as mapStyle, but the JSDoc still mentions an “access token” and lists MapStyle (capital M):

  • Line 43: “obtains the Maplibre access token and style configuration” is stale.
  • Line 47: Bullet label MapStyle doesn’t match the returned key mapStyle.

Suggested update:

- * and obtains the Maplibre access token and style configuration for map rendering.
+ * and obtains the MapLibre style configuration for map rendering.
 ...
  * @returns An object containing:
  *  - savedFields: A GeoJSON FeatureCollection of the farm fields.
- *  - MapStyle: The Maplibre style configuration.
+ *  - mapStyle: The MapLibre style configuration.

This keeps the docs consistent with the loader’s current return object.

Also applies to: 93-101

🧹 Nitpick comments (5)
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx (1)

77-79: Loader data is fetched but never consumed.

The loader returns field data, but the component (lines 90-107) renders only a placeholder message and doesn't use useLoaderData(). If this route is intentionally a work-in-progress placeholder, consider removing the field-fetching logic until the elevation feature is implemented to avoid unnecessary database queries.

If the elevation feature isn't ready, simplify the loader:

 export async function loader({ request, params }: LoaderFunctionArgs) {
     try {
-        // Get the farm id
         const b_id_farm = params.b_id_farm
         if (!b_id_farm) {
             throw data("Farm ID is required", {
                 status: 400,
                 statusText: "Farm ID is required",
             })
         }
-
-        // Get the session
-        const session = await getSession(request)
-
-        // Get timeframe from calendar store
-        const timeframe = getTimeframe(params)
-
-        // Get the fields of the farm
-        const fields = await getFields(
-            fdm,
-            session.principal_id,
-            b_id_farm,
-            timeframe,
-        )
-        const features = fields.map((field) => {
-            const feature = {
-                type: "Feature",
-                properties: {
-                    b_id: field.b_id,
-                    b_name: field.b_name,
-                    b_area: Math.round(field.b_area * 10) / 10,
-                },
-                geometry: field.b_geometry,
-            }
-            return feature
-        })
-
-        const featureCollection = {
-            type: "FeatureCollection",
-            features: features,
-        }
-
-        // Return user information from loader
-        return {
-            fields: featureCollection,
-        }
+        
+        return {}
     } catch (error) {
         throw handleLoaderError(error)
     }
 }
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx (1)

82-84: Loader data is fetched but never consumed.

The loader returns field data, but the component (lines 96-113) renders only a placeholder message and doesn't use useLoaderData(). If this route is intentionally a work-in-progress placeholder, consider removing the field-fetching logic until the soil feature is implemented to avoid unnecessary database queries.

If the soil feature isn't ready, simplify the loader:

 export async function loader({ request, params }: LoaderFunctionArgs) {
     try {
-        // Get the farm id
         const b_id_farm = params.b_id_farm
         if (!b_id_farm) {
             throw data("Farm ID is required", {
                 status: 400,
                 statusText: "Farm ID is required",
             })
         }
-
-        // Get the session
-        const session = await getSession(request)
-
-        // Get timeframe from calendar store
-        const timeframe = getTimeframe(params)
-
-        // Get the fields of the farm
-        const fields = await getFields(
-            fdm,
-            session.principal_id,
-            b_id_farm,
-            timeframe,
-        )
-        const features = fields.map((field) => {
-            const feature = {
-                type: "Feature",
-                properties: {
-                    b_id: field.b_id,
-                    b_name: field.b_name,
-                    b_area: Math.round(field.b_area * 10) / 10,
-                },
-                geometry: field.b_geometry,
-            }
-            return feature
-        })
-
-        const featureCollection = {
-            type: "FeatureCollection",
-            features: features,
-        }
-
-        // Return user information from loader
-        return {
-            fields: featureCollection,
-        }
+        
+        return {}
     } catch (error) {
         throw handleLoaderError(error)
     }
 }
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (2)

4-11: MapLibre integration looks correct; you can probably drop the explicit mapLib wiring

Using Map/Layer/types from react-map-gl/maplibre plus mapStyle={loaderData.mapStyle} matches the MapLibre wrapper API, and getMapStyle("satellite") keeps the loader/view contract clean.

Given the docs, when importing from react-map-gl/maplibre, mapLib already defaults to import('maplibre-gl'), so you likely don't need:

import maplibregl from "maplibre-gl"

<MapGL
  ...
  mapLib={maplibregl}
/>

Dropping the static import and mapLib prop would simplify this file and may also reduce bundle size / avoid potential SSR issues with eagerly importing maplibre-gl.

Also applies to: 19-19, 159-165


189-191: Avoid as any on Layer props; prefer a typed layer style object

The new pattern

<Layer
  {...({ ...fieldsAvailableStyle, layout: layerLayout } as any)}
/>

works but throws away type safety and makes it easier to accidentally pass an invalid style.

If possible, prefer a typed style object and drop the as any, e.g.:

// Example sketch — exact type depends on what getFieldsStyle returns
import type { FillLayer } from "react-map-gl/maplibre"

const fieldsAvailableLayer: FillLayer = {
  ...fieldsAvailableStyle,
  layout: layerLayout,
}

and then:

<Layer {...fieldsAvailableLayer} />

or, if the previous API still compiles with MapLibre types, simply revert to:

<Layer {...fieldsAvailableStyle} layout={layerLayout} />

Either approach preserves type checking without changing runtime behavior.

fdm-app/app/components/blocks/atlas/atlas-panels.tsx (1)

4-8: Align hover handler event typing with MapLibre’s event model and guard on point.

MapLibreZoomEvent is the type used for boxzoom* events in MapLibre, while your listener is wired to "zoom" and "load" (which use generic MapLibreEvent and do not expose a point property). At the same time, updatePanel assumes evt.point exists for all calls. This was already a bit shaky with Mapbox and remains so after the migration; given you’re touching the event types here, it’s a good moment to tighten this up by relying on mouse events only and guarding the point access.

Consider simplifying the signature to mouse events and adding a runtime guard before calling queryRenderedFeatures:

-import type { MapLibreZoomEvent } from "maplibre-gl"
@@
-import type { MapLayerMouseEvent as MapMouseEvent } from "react-map-gl/maplibre"
-import { useMap } from "react-map-gl/maplibre"
+import type { MapLayerMouseEvent as MapMouseEvent } from "react-map-gl/maplibre"
+import { useMap } from "react-map-gl/maplibre"
@@
-        function updatePanel(evt: MapMouseEvent | MapLibreZoomEvent) {
+        function updatePanel(evt: MapMouseEvent) {
             if (map) {
                 // Set message about zoom level
                 const zoom = map.getZoom()
                 if (zoom && zoom > zoomLevelFields) {
-                    const features = map.queryRenderedFeatures(evt.point, {
+                    // Ignore non-mouse events (e.g. zoom/load) that do not carry a screen point
+                    if (!evt.point) {
+                        return
+                    }
+
+                    const features = map.queryRenderedFeatures(evt.point, {
@@
-                        const featuresExclude = map.queryRenderedFeatures(
-                            evt.point,
-                            {
+                        const featuresExclude = map.queryRenderedFeatures(
+                            evt.point,
+                            {

This keeps the MapLibre migration clean, avoids depending on zoom/load events having a point, and matches the earlier guidance to gate access to mouse-only properties via a guard. Based on learnings and MapLibre docs, this should be safer going forward.

Also applies to: 37-59

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c421252 and 68ae27b.

⛔ Files ignored due to path filters (1)
  • fdm-app/app/lib/cache.server.ts is excluded by !fdm-app/app/lib/**
📒 Files selected for processing (10)
  • docker-compose.yml (1 hunks)
  • fdm-app/.env.example (1 hunks)
  • fdm-app/README.md (1 hunks)
  • fdm-app/app/components/blocks/atlas/atlas-panels.tsx (2 hunks)
  • fdm-app/app/root.tsx (4 hunks)
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx (1 hunks)
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (6 hunks)
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx (1 hunks)
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.tsx (1 hunks)
  • fdm-docs/docs/fdm-app/01-introduction-to-fdm-app.md (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • fdm-docs/docs/fdm-app/01-introduction-to-fdm-app.md
  • fdm-app/README.md
🧰 Additional context used
🧠 Learnings (31)
📓 Common learnings
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: Map configuration in the application should be modularized using the `useMapConfig` hook and `MapControls` component to maintain consistency across all MapGL instances.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: MapGL implementations should use the shared `useMapConfig` hook for configuration and `getLayerStyle` utility for consistent styling. The hook supports both interactive and non-interactive maps, handling bounds calculation and view state management.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2024-11-25T14:42:26.660Z
Learning: In `fdm-app/app/components/blocks/field-map.tsx`, explicit cleanup of Mapbox GL resources is not necessary, as `react-map-gl` handles it automatically upon component unmount, and `MapRef` does not have a `remove` method.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2025-06-10T13:10:03.154Z
Learning: When facing prop name inconsistencies with react-map-gl (like mapboxAccessToken vs mapboxApiAccessToken), using different import statements can resolve the issue more elegantly than changing prop names across multiple files.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas.d.tsx:8-8
Timestamp: 2025-01-31T14:29:37.599Z
Learning: In the Atlas component's MapFieldsProps interface, mapStyle is intentionally restricted to "mapbox://styles/mapbox/satellite-streets-v12" as it's currently the only supported style option.
📚 Learning: 2025-01-09T16:03:37.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes/farm/_b_id_farm/layout.tsx:46-95
Timestamp: 2025-01-09T16:03:37.764Z
Learning: A shared layout component `FarmLayoutBase` has been created in `components/custom/farm-layout-base.tsx` to maintain consistency across farm-related pages. The component handles farm selection dropdown, breadcrumb navigation, and provides a common layout structure.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.tsx
📚 Learning: 2024-11-25T14:42:26.660Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2024-11-25T14:42:26.660Z
Learning: In `fdm-app/app/components/blocks/field-map.tsx`, explicit cleanup of Mapbox GL resources is not necessary, as `react-map-gl` handles it automatically upon component unmount, and `MapRef` does not have a `remove` method.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/components/blocks/atlas/atlas-panels.tsx
  • fdm-app/app/root.tsx
📚 Learning: 2025-06-02T10:31:27.097Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 151
File: fdm-app/app/routes/signin._index.tsx:101-101
Timestamp: 2025-06-02T10:31:27.097Z
Learning: In fdm-app/app/routes/signin._index.tsx, the redirect destinations are intentionally inconsistent by design: the component defaults new sign-ins to "/welcome" (line 101) while the loader redirects authenticated users to "/farm" (line 80) and the action uses "/farm" as fallback (line 434). This creates appropriate user flows where new users complete their profile via the welcome page, while existing authenticated users bypass it and go directly to the main application.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
📚 Learning: 2025-09-23T12:29:34.184Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 274
File: fdm-app/app/routes/farm.$b_id_farm._index.tsx:160-163
Timestamp: 2025-09-23T12:29:34.184Z
Learning: In the FDM application, the fertilizer application route intentionally uses `${calendar}/field/fertilizer` instead of the originally planned `/farm/{farmId}/add/fertilizer` structure. This design decision prioritizes starting from the field list view to provide better field selection workflow before applying fertilizer, rather than direct dashboard-to-action navigation.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.tsx
📚 Learning: 2025-01-09T16:03:37.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes/farm/_b_id_farm/layout.tsx:46-95
Timestamp: 2025-01-09T16:03:37.764Z
Learning: The `FarmLayout` component in `components/custom/farm-layout.tsx` provides a reusable layout structure for farm-related pages, with support for farm selection dropdown, customizable breadcrumb titles, and flexible content rendering through either children or Outlet components.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
📚 Learning: 2025-09-23T12:37:58.711Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 274
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.field._index.tsx:113-148
Timestamp: 2025-09-23T12:37:58.711Z
Learning: In the FDM application, the current field data fetching implementation using Promise.all with individual API calls (getCultivations, getFertilizerApplications, getCurrentSoilData) performs acceptably even with farms containing 90+ fields. No performance issues have been observed in practice with this approach.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.tsx
📚 Learning: 2025-04-29T11:28:44.181Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 132
File: fdm-app/app/routes/farm.create.$b_id_farm.$calendar.access.tsx:54-68
Timestamp: 2025-04-29T11:28:44.181Z
Learning: In React Router v7, the `json()` function has been replaced with `data()` for creating responses in loaders and actions.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
📚 Learning: 2025-04-04T14:27:39.518Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 116
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.field.new.tsx:111-154
Timestamp: 2025-04-04T14:27:39.518Z
Learning: In the FDM application, cultivation retrieval logic should be centralized in utility functions rather than duplicated across loader and action functions to improve maintainability and ensure consistent behavior.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.tsx
📚 Learning: 2025-04-29T11:28:44.181Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 132
File: fdm-app/app/routes/farm.create.$b_id_farm.$calendar.access.tsx:54-68
Timestamp: 2025-04-29T11:28:44.181Z
Learning: In React Router v7, the `json()` function has been deprecated and removed. Instead, either return plain JavaScript objects directly from loaders/actions, or use the `data()` function for responses with custom status codes and headers.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
📚 Learning: 2024-12-16T10:56:07.561Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 16
File: fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx:1-1
Timestamp: 2024-12-16T10:56:07.561Z
Learning: The project uses `react-router` v7, and the `data` function is exported and used for error handling in loaders and actions.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/root.tsx
📚 Learning: 2025-04-18T13:49:17.029Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-app/app/components/custom/farm/farm-title.tsx:3-3
Timestamp: 2025-04-18T13:49:17.029Z
Learning: In the fdm project, NavLink and other routing components can be imported from either "react-router" or "react-router-dom" as react-router-dom is included in react-router.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
📚 Learning: 2025-07-24T08:29:44.044Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 198
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.balance.nitrogen.$b_id.tsx:146-148
Timestamp: 2025-07-24T08:29:44.044Z
Learning: In React Router v7, the defer() function has been removed. Instead, loaders can return promises directly in the response object, and components use Suspense and Await to handle them without needing defer().

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/root.tsx
📚 Learning: 2025-05-09T14:53:44.578Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/combobox.tsx:34-37
Timestamp: 2025-05-09T14:53:44.578Z
Learning: In the context of this React Router v7 project, it's important to follow the pattern of importing only the types (like UseFormReturn) from "react-hook-form" while importing the Form component from "react-router" to avoid naming conflicts.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/root.tsx
📚 Learning: 2025-01-09T16:07:36.741Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes.ts:81-81
Timestamp: 2025-01-09T16:07:36.741Z
Learning: The route pattern "api/auth/:" in React Router is required for better-auth's handler to function correctly. The auth.handler() method in the route's loader and action functions expects this exact pattern to handle various authentication endpoints including OAuth callbacks, session management, and rate limiting.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
📚 Learning: 2025-07-24T08:29:44.044Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 198
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.balance.nitrogen.$b_id.tsx:146-148
Timestamp: 2025-07-24T08:29:44.044Z
Learning: React Router v7 supports Suspense patterns by returning promises directly from loaders. The pattern is: return { data: somePromise } from loader, then use <Suspense><Await resolve={loaderData.data}>{resolvedData => ...}</Await></Suspense> in components.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
📚 Learning: 2025-05-09T14:41:43.484Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/fertilizer-applications/form.tsx:6-6
Timestamp: 2025-05-09T14:41:43.484Z
Learning: The project uses React Router v7 which exports a Form component directly from the "react-router" package, making importing from "remix-run/react" unnecessary.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
📚 Learning: 2025-01-14T16:06:24.294Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 45
File: fdm-app/app/routes/farm.$b_id_farm._index.tsx:1-1
Timestamp: 2025-01-14T16:06:24.294Z
Learning: In the fdm-app codebase, the `redirect` function should be imported from `react-router`, not `react-router-dom`.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
📚 Learning: 2025-06-10T13:10:03.154Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2025-06-10T13:10:03.154Z
Learning: When facing prop name inconsistencies with react-map-gl (like mapboxAccessToken vs mapboxApiAccessToken), using different import statements can resolve the issue more elegantly than changing prop names across multiple files.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/components/blocks/atlas/atlas-panels.tsx
  • fdm-app/app/root.tsx
📚 Learning: 2025-01-31T14:29:37.599Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas.d.tsx:8-8
Timestamp: 2025-01-31T14:29:37.599Z
Learning: In the Atlas component's MapFieldsProps interface, mapStyle is intentionally restricted to "mapbox://styles/mapbox/satellite-streets-v12" as it's currently the only supported style option.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/root.tsx
📚 Learning: 2025-06-10T12:20:38.360Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:68-68
Timestamp: 2025-06-10T12:20:38.360Z
Learning: In react-map-gl v8.0.4, the correct prop name for the Mapbox access token in the MapGL component is `mapboxApiAccessToken`, not `mapboxAccessToken` as verified by checking the MapboxProps interface.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/components/blocks/atlas/atlas-panels.tsx
  • fdm-app/app/root.tsx
📚 Learning: 2025-06-10T12:20:38.360Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:68-68
Timestamp: 2025-06-10T12:20:38.360Z
Learning: When using MapGL component from react-map-gl, the correct prop name for the Mapbox access token is `mapboxApiAccessToken` as verified by checking the MapboxProps interface. This should be consistent across all usages of the MapGL component.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/root.tsx
📚 Learning: 2025-01-31T16:06:33.810Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: Map configuration in the application should be modularized using the `useMapConfig` hook and `MapControls` component to maintain consistency across all MapGL instances.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/components/blocks/atlas/atlas-panels.tsx
  • fdm-app/app/root.tsx
📚 Learning: 2025-01-31T16:06:33.810Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: MapGL implementations should use the shared `useMapConfig` hook for configuration and `getLayerStyle` utility for consistent styling. The hook supports both interactive and non-interactive maps, handling bounds calculation and view state management.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/components/blocks/atlas/atlas-panels.tsx
📚 Learning: 2025-01-31T15:41:43.741Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas-panels.tsx:28-28
Timestamp: 2025-01-31T15:41:43.741Z
Learning: When handling different map event types in react-map-gl v7.1.8, use MapLayerMouseEvent for mouse events (which have the point property) and ViewStateChangeEvent for view state changes. Use a type guard like 'point' in evt to safely access event-specific properties.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/components/blocks/atlas/atlas-panels.tsx
📚 Learning: 2025-01-31T15:06:35.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas-sources.tsx:21-66
Timestamp: 2025-01-31T15:06:35.764Z
Learning: In react-map-gl components, when querying rendered features via map.queryRenderedFeatures(), the effect's dependency array must include any props that affect the map's rendered state (like source data) to ensure features are queried against the current map state.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/components/blocks/atlas/atlas-panels.tsx
  • fdm-app/app/root.tsx
📚 Learning: 2025-08-11T12:24:32.200Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 233
File: fdm-app/app/components/blocks/atlas-fields/cultivation-history.tsx:53-53
Timestamp: 2025-08-11T12:24:32.200Z
Learning: In `fdm-app/app/components/blocks/atlas-fields/cultivation-history.tsx`, the NMI API for cultivations guarantees that each year will be unique in the cultivation history data, so using `cultivation.year` as a React list key is safe and won't cause duplicate key warnings.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.tsx
📚 Learning: 2025-01-31T15:05:14.310Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.fields.$b_id.tsx:601-610
Timestamp: 2025-01-31T15:05:14.310Z
Learning: The `updateField` function in fdm-core has optional parameters after `fdm` and `b_id`. The TypeScript definitions might show 8 required parameters due to a potential version mismatch.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.tsx
📚 Learning: 2025-01-31T15:34:20.850Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.fields.$b_id.tsx:601-610
Timestamp: 2025-01-31T15:34:20.850Z
Learning: The `updateField` function in fdm-core has optional parameters that don't need to be passed as undefined. Only `fdm` and `b_id` are required.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.tsx
📚 Learning: 2025-08-11T11:55:26.053Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 233
File: fdm-app/app/integrations/nmi.ts:54-0
Timestamp: 2025-08-11T11:55:26.053Z
Learning: The NMI API Estimates endpoint (`https://api.nmi-agro.nl/estimates`) always returns the fields `b_gwl_ghg`, `b_gwl_glg`, and `cultivations` according to its specification. These fields should be kept as required (not optional) in the TypeScript return type and Zod validation schema in `fdm-app/app/integrations/nmi.ts`.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.tsx
📚 Learning: 2025-02-19T10:50:50.200Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 82
File: fdm-app/app/entry.client.tsx:13-13
Timestamp: 2025-02-19T10:50:50.200Z
Learning: Sentry DSN being public in client-side code is not a security concern as per Sentry documentation, but it can be made configurable using Vite's environment variables system with the `VITE_` prefix.

Applied to files:

  • fdm-app/app/root.tsx
🧬 Code graph analysis (1)
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (1)
fdm-app/app/integrations/map.ts (1)
  • getMapStyle (4-23)
🪛 ast-grep (0.40.0)
fdm-app/app/root.tsx

[warning] 130-130: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- https://cwe.mitre.org/data/definitions/79.html

(react-unsafe-html-injection)

🔇 Additional comments (6)
fdm-app/.env.example (1)

74-81: LGTM! Excellent documentation.

The environment variable documentation is clear and comprehensive. The conditional requirement for PUBLIC_MAPTILER_API_KEY (only when PUBLIC_MAP_PROVIDER is "maptiler") is well-explained, and the default value of "osm" is sensible.

fdm-app/app/root.tsx (3)

2-2: LGTM! Clean CSS migration.

The import and link update from Mapbox GL to MapLibre GL CSS is correct and consistent with the library migration.

Also applies to: 30-30


53-54: LGTM! Runtime environment propagation updated correctly.

The replacement of PUBLIC_MAPBOX_TOKEN with PUBLIC_MAP_PROVIDER and PUBLIC_MAPTILER_API_KEY correctly propagates the new configuration to the client runtime.


130-134: LGTM! Safe global polyfill.

The comment update to "Maplibre" is appropriate. The static analysis warning about dangerouslySetInnerHTML can be safely ignored here—this is a standard, safe pattern for polyfilling global in browser environments with a hardcoded static string.

docker-compose.yml (1)

16-17: ```shell
#!/bin/bash

Check config.d.ts and find where clientConfig is instantiated

echo "=== fdm-app/app/types/config.d.ts ==="
cat -n fdm-app/app/types/config.d.ts

echo -e "\n=== Search for clientConfig instantiation/assignment ==="
rg -n 'clientConfig\s*=|const clientConfig|export.*clientConfig' --type=ts --type=js -C3

echo -e "\n=== Check entry.client.tsx ==="
head -80 fdm-app/app/entry.client.tsx | cat -n

echo -e "\n=== Check store directory ==="
ls -la fdm-app/app/store/


</function_calls>

#!/bin/bash
# Continue searching for clientConfig definition

echo "=== fdm-app/app/types/config.d.ts ==="
cat -n fdm-app/app/types/config.d.ts

echo -e "\n=== Search for clientConfig assignment ==="
rg -n 'clientConfig' --type=ts --type=js | head -40

echo -e "\n=== Look for ~ alias in vite config ==="
cat fdm-app/vite.config.ts | head -50
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (1)

108-112: Updated component-level description matches MapLibre usage

The doc comment now correctly describes this as a MapLibre-backed map consuming preloaded field data and controls. No further changes needed here.

Comment thread fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx Outdated
Comment thread fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx Outdated
Comment thread fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.tsx
@SvenVw SvenVw requested a review from BoraIneviNMI December 1, 2025 08:45
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx (1)

33-82: Consider simplifying or deferring the loader implementation.

The loader fetches and transforms field data, but the component only renders a placeholder message indicating the elevation map isn't available yet. Since the loader data isn't currently consumed, you might consider either:

  • Simplifying the loader to just validate the farm ID until the feature is implemented
  • Keeping the current implementation if you plan to complete the elevation map feature soon
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 68ae27b and e9eb10e.

📒 Files selected for processing (3)
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx (1 hunks)
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx (1 hunks)
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.fields.tsx
🧰 Additional context used
🧠 Learnings (18)
📓 Common learnings
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: Map configuration in the application should be modularized using the `useMapConfig` hook and `MapControls` component to maintain consistency across all MapGL instances.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: MapGL implementations should use the shared `useMapConfig` hook for configuration and `getLayerStyle` utility for consistent styling. The hook supports both interactive and non-interactive maps, handling bounds calculation and view state management.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2024-11-25T14:42:26.660Z
Learning: In `fdm-app/app/components/blocks/field-map.tsx`, explicit cleanup of Mapbox GL resources is not necessary, as `react-map-gl` handles it automatically upon component unmount, and `MapRef` does not have a `remove` method.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2025-06-10T13:10:03.154Z
Learning: When facing prop name inconsistencies with react-map-gl (like mapboxAccessToken vs mapboxApiAccessToken), using different import statements can resolve the issue more elegantly than changing prop names across multiple files.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas.d.tsx:8-8
Timestamp: 2025-01-31T14:29:37.599Z
Learning: In the Atlas component's MapFieldsProps interface, mapStyle is intentionally restricted to "mapbox://styles/mapbox/satellite-streets-v12" as it's currently the only supported style option.
📚 Learning: 2024-11-25T14:42:26.660Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2024-11-25T14:42:26.660Z
Learning: In `fdm-app/app/components/blocks/field-map.tsx`, explicit cleanup of Mapbox GL resources is not necessary, as `react-map-gl` handles it automatically upon component unmount, and `MapRef` does not have a `remove` method.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
📚 Learning: 2025-01-09T16:03:37.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes/farm/_b_id_farm/layout.tsx:46-95
Timestamp: 2025-01-09T16:03:37.764Z
Learning: A shared layout component `FarmLayoutBase` has been created in `components/custom/farm-layout-base.tsx` to maintain consistency across farm-related pages. The component handles farm selection dropdown, breadcrumb navigation, and provides a common layout structure.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
📚 Learning: 2025-08-11T12:24:32.200Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 233
File: fdm-app/app/components/blocks/atlas-fields/cultivation-history.tsx:53-53
Timestamp: 2025-08-11T12:24:32.200Z
Learning: In `fdm-app/app/components/blocks/atlas-fields/cultivation-history.tsx`, the NMI API for cultivations guarantees that each year will be unique in the cultivation history data, so using `cultivation.year` as a React list key is safe and won't cause duplicate key warnings.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
📚 Learning: 2025-01-09T16:03:37.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes/farm/_b_id_farm/layout.tsx:46-95
Timestamp: 2025-01-09T16:03:37.764Z
Learning: The `FarmLayout` component in `components/custom/farm-layout.tsx` provides a reusable layout structure for farm-related pages, with support for farm selection dropdown, customizable breadcrumb titles, and flexible content rendering through either children or Outlet components.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
📚 Learning: 2025-09-23T12:37:58.711Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 274
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.field._index.tsx:113-148
Timestamp: 2025-09-23T12:37:58.711Z
Learning: In the FDM application, the current field data fetching implementation using Promise.all with individual API calls (getCultivations, getFertilizerApplications, getCurrentSoilData) performs acceptably even with farms containing 90+ fields. No performance issues have been observed in practice with this approach.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
📚 Learning: 2025-06-02T10:31:27.097Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 151
File: fdm-app/app/routes/signin._index.tsx:101-101
Timestamp: 2025-06-02T10:31:27.097Z
Learning: In fdm-app/app/routes/signin._index.tsx, the redirect destinations are intentionally inconsistent by design: the component defaults new sign-ins to "/welcome" (line 101) while the loader redirects authenticated users to "/farm" (line 80) and the action uses "/farm" as fallback (line 434). This creates appropriate user flows where new users complete their profile via the welcome page, while existing authenticated users bypass it and go directly to the main application.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
📚 Learning: 2025-06-10T13:10:03.154Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2025-06-10T13:10:03.154Z
Learning: When facing prop name inconsistencies with react-map-gl (like mapboxAccessToken vs mapboxApiAccessToken), using different import statements can resolve the issue more elegantly than changing prop names across multiple files.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
📚 Learning: 2024-12-16T10:56:07.561Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 16
File: fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx:1-1
Timestamp: 2024-12-16T10:56:07.561Z
Learning: The project uses `react-router` v7, and the `data` function is exported and used for error handling in loaders and actions.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
📚 Learning: 2025-04-29T11:28:44.181Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 132
File: fdm-app/app/routes/farm.create.$b_id_farm.$calendar.access.tsx:54-68
Timestamp: 2025-04-29T11:28:44.181Z
Learning: In React Router v7, the `json()` function has been replaced with `data()` for creating responses in loaders and actions.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
📚 Learning: 2025-04-29T11:28:44.181Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 132
File: fdm-app/app/routes/farm.create.$b_id_farm.$calendar.access.tsx:54-68
Timestamp: 2025-04-29T11:28:44.181Z
Learning: In React Router v7, the `json()` function has been deprecated and removed. Instead, either return plain JavaScript objects directly from loaders/actions, or use the `data()` function for responses with custom status codes and headers.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
📚 Learning: 2025-01-09T16:07:36.741Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes.ts:81-81
Timestamp: 2025-01-09T16:07:36.741Z
Learning: The route pattern "api/auth/:" in React Router is required for better-auth's handler to function correctly. The auth.handler() method in the route's loader and action functions expects this exact pattern to handle various authentication endpoints including OAuth callbacks, session management, and rate limiting.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
📚 Learning: 2025-07-24T08:29:44.044Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 198
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.balance.nitrogen.$b_id.tsx:146-148
Timestamp: 2025-07-24T08:29:44.044Z
Learning: In React Router v7, the defer() function has been removed. Instead, loaders can return promises directly in the response object, and components use Suspense and Await to handle them without needing defer().

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
📚 Learning: 2025-05-09T14:53:44.578Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/combobox.tsx:34-37
Timestamp: 2025-05-09T14:53:44.578Z
Learning: In the context of this React Router v7 project, it's important to follow the pattern of importing only the types (like UseFormReturn) from "react-hook-form" while importing the Form component from "react-router" to avoid naming conflicts.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
📚 Learning: 2025-05-09T14:41:43.484Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/fertilizer-applications/form.tsx:6-6
Timestamp: 2025-05-09T14:41:43.484Z
Learning: The project uses React Router v7 which exports a Form component directly from the "react-router" package, making importing from "remix-run/react" unnecessary.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
📚 Learning: 2025-04-18T13:49:17.029Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-app/app/components/custom/farm/farm-title.tsx:3-3
Timestamp: 2025-04-18T13:49:17.029Z
Learning: In the fdm project, NavLink and other routing components can be imported from either "react-router" or "react-router-dom" as react-router-dom is included in react-router.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
📚 Learning: 2025-07-24T08:29:44.044Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 198
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.balance.nitrogen.$b_id.tsx:146-148
Timestamp: 2025-07-24T08:29:44.044Z
Learning: React Router v7 supports Suspense patterns by returning promises directly from loaders. The pattern is: return { data: somePromise } from loader, then use <Suspense><Await resolve={loaderData.data}>{resolvedData => ...}</Await></Suspense> in components.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
📚 Learning: 2025-01-14T16:06:24.294Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 45
File: fdm-app/app/routes/farm.$b_id_farm._index.tsx:1-1
Timestamp: 2025-01-14T16:06:24.294Z
Learning: In the fdm-app codebase, the `redirect` function should be imported from `react-router`, not `react-router-dom`.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
🔇 Additional comments (3)
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx (2)

27-32: JSDoc now accurately reflects the loader's return value.

The documentation has been correctly updated to remove references to map style configuration, addressing the previous review feedback. The description now accurately states that only the GeoJSON FeatureCollection of farm fields is returned.


89-106: LGTM!

The placeholder component appropriately communicates that the elevation map feature is under development and provides clear navigation to an alternative view.

fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx (1)

27-37: Docblock now matches loader behavior

The updated JSDoc correctly describes that the loader only builds and returns a GeoJSON FeatureCollection (via the fields property) and no longer mentions a map style configuration, resolving the earlier discrepancy between docs and implementation.

Copy link
Copy Markdown
Collaborator

@BoraIneviNMI BoraIneviNMI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. These changes should ensure the independence from the business practices of the dependency authors.

@SvenVw SvenVw merged commit 6f06632 into development Dec 2, 2025
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

branch:development Issue only affecting development, not the main branch (yet) dependencies Pull requests that update a dependency file enhancement New feature or request fdm-app fdm-docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migrate fdm-app maps from Mapbox to MapLibre

2 participants