Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/light-bushes-sniff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@svenvw/fdm-app": patch
---

Migrate Sentry to `@sentry/react-router` (RRv7 integration with improved routing-aware tracing and profiling)
2 changes: 1 addition & 1 deletion .github/workflows/deploy-docs-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10.13.1
version: 10.14.0
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/deploy-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10.13.1
version: 10.14.0
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
- name: Setup pnpm 10
uses: pnpm/action-setup@v4
with:
version: 10.13.1
version: 10.14.0

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ jobs:
- name: Setup pnpm 10
uses: pnpm/action-setup@v4
with:
version: 10.13.1
version: 10.14.0

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
Expand Down Expand Up @@ -146,7 +146,7 @@ jobs:
- name: Setup pnpm 10
uses: pnpm/action-setup@v4
with:
version: 10.13.1
version: 10.14.0

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
Expand Down Expand Up @@ -226,7 +226,7 @@ jobs:
- name: Setup pnpm 10
uses: pnpm/action-setup@v4
with:
version: 10.13.1
version: 10.14.0

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
Expand Down
9 changes: 3 additions & 6 deletions fdm-app/app/components/blocks/sidebar/support.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as Sentry from "@sentry/react"
import * as Sentry from "@sentry/react-router"
import { LifeBuoy, Send } from "lucide-react"
import { useEffect, useState } from "react"
import { NavLink } from "react-router"
Expand Down Expand Up @@ -101,14 +101,11 @@ export function SidebarSupport({
{clientConfig.analytics.sentry ? (
<SidebarMenuItem key="feedback">
<SidebarMenuButton
asChild
size="sm"
onClick={openFeedbackForm}
>
<NavLink to="#">
<Send />
<span>Feedback</span>
</NavLink>
<Send />
<span>Feedback</span>
</SidebarMenuButton>
</SidebarMenuItem>
) : null}
Expand Down
4 changes: 2 additions & 2 deletions fdm-app/app/entry.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* For more information, see https://remix.run/file-conventions/entry.client
*/

import * as Sentry from "@sentry/react"
import * as Sentry from "@sentry/react-router"
import posthog from "posthog-js"
import { PostHogProvider } from "posthog-js/react"
import { StrictMode, startTransition } from "react"
Expand All @@ -18,7 +18,7 @@ if (clientConfig.analytics.sentry) {
dsn: sentryConfig.dsn,
environment: import.meta.env.NODE_ENV,
integrations: [
Sentry.browserTracingIntegration(),
Sentry.reactRouterTracingIntegration(),
Sentry.replayIntegration(),
Sentry.feedbackIntegration({
autoInject: false,
Expand Down
20 changes: 14 additions & 6 deletions fdm-app/app/entry.server.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import { createReadableStreamFromReadable } from "@react-router/node"
* You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
* For more information, see https://remix.run/file-conventions/entry.server
*/
import * as Sentry from "@sentry/node"
import * as Sentry from "@sentry/react-router"
import {
getMetaTagTransformer,
wrapSentryHandleRequest,
} from "@sentry/react-router"
import { isbot } from "isbot"
import { renderToPipeableStream } from "react-dom/server"
import type {
Expand All @@ -18,7 +22,7 @@ import { addSecurityHeaders, getCacheControlHeaders } from "./lib/cache.server"

export const streamTimeout = 5000

export default function handleRequest(
const handleRequest = async function handleRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
Expand All @@ -27,7 +31,7 @@ export default function handleRequest(
// free to delete this parameter in your app if you're not using it!
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_loadContext: AppLoadContext,
) {
): Promise<Response> {
const url = new URL(request.url)
const { hostname } = url

Expand Down Expand Up @@ -78,7 +82,7 @@ function handleBotRequest(
responseStatusCode: number,
responseHeaders: Headers,
reactRouterContext: EntryContext,
) {
): Promise<Response> {
return new Promise((resolve, reject) => {
let shellRendered = false
let currentStatus = responseStatusCode
Expand Down Expand Up @@ -126,7 +130,7 @@ function handleBrowserRequest(
responseStatusCode: number,
responseHeaders: Headers,
reactRouterContext: EntryContext,
) {
): Promise<Response> {
return new Promise((resolve, reject) => {
let shellRendered = false
let currentStatus = responseStatusCode
Expand All @@ -148,7 +152,8 @@ function handleBrowserRequest(
}),
)

pipe(body)
// this enables distributed tracing between client and server
pipe(getMetaTagTransformer(body))
},
onShellError(error: unknown) {
reject(error)
Expand All @@ -169,6 +174,9 @@ function handleBrowserRequest(
})
}

// wrap the default export
export default wrapSentryHandleRequest(handleRequest)

export const handleError: HandleErrorFunction = (error, { request }) => {
// React Router may abort some interrupted requests, report those
if (!request.signal.aborted) {
Expand Down
2 changes: 1 addition & 1 deletion fdm-app/app/root.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as Sentry from "@sentry/react"
import * as Sentry from "@sentry/react-router"
import mapBoxStyle from "mapbox-gl/dist/mapbox-gl.css?url"
import posthog from "posthog-js"
import { useEffect } from "react"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ import {
type ViewState,
type ViewStateChangeEvent,
} from "react-map-gl/mapbox"
import "mapbox-gl/dist/mapbox-gl.css"
import { getFields } from "@svenvw/fdm-core"
import type { FeatureCollection } from "geojson"
import type { MetaFunction } from "react-router"
import { data, type LoaderFunctionArgs, useLoaderData } from "react-router"
import { type LoaderFunctionArgs, useLoaderData } from "react-router"
import { ZOOM_LEVEL_FIELDS } from "~/components/blocks/atlas/atlas"
import { Controls } from "~/components/blocks/atlas/atlas-controls"
import { FieldsPanelHover } from "~/components/blocks/atlas/atlas-panels"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Layer, Map as MapGL } from "react-map-gl/mapbox"
import "mapbox-gl/dist/mapbox-gl.css"
import { getField } from "@svenvw/fdm-core"
import type { FeatureCollection } from "geojson"
import type { MetaFunction } from "react-router"
Expand Down
4 changes: 3 additions & 1 deletion fdm-app/instrument.server.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as Sentry from "@sentry/node"
import * as Sentry from "@sentry/react-router"
import { nodeProfilingIntegration } from "@sentry/profiling-node"

const requiredEnvVars = [
Expand All @@ -18,4 +18,6 @@ Sentry.init({
integrations: [nodeProfilingIntegration()],
tracesSampleRate: Number(process.env.VITE_SENTRY_TRACE_SAMPLE_RATE),
profilesSampleRate: Number(process.env.VITE_SENTRY_PROFILE_SAMPLE_RATE),
environment: process.env.NODE_ENV ?? "development",
release: process.env.npm_package_version,
})
55 changes: 27 additions & 28 deletions fdm-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"typecheck": "react-router typegen && tsc"
},
"dependencies": {
"@hookform/resolvers": "^5.1.1",
"@hookform/resolvers": "^5.2.1",
"@mapbox/geojson-extent": "^1.0.1",
"@mapbox/mapbox-gl-geocoder": "^5.1.0",
"@mjackson/file-storage": "^0.7.0",
Expand All @@ -23,13 +23,12 @@
"@radix-ui/react-icons": "^1.3.2",
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-switch": "^1.2.5",
"@react-email/components": "^0.3.2",
"@react-email/tailwind": "1.0.5",
"@react-router/node": "^7.7.0",
"@react-router/serve": "^7.7.0",
"@sentry/node": "^9.40.0",
"@sentry/profiling-node": "^9.40.0",
"@sentry/react": "^9.40.0",
"@react-email/components": "^0.5.0",
"@react-email/tailwind": "1.2.2",
"@react-router/node": "^7.8.0",
"@react-router/serve": "^7.8.0",
"@sentry/profiling-node": "^10.4.0",
"@sentry/react-router": "^10.4.0",
"@svenvw/fdm-calculator": "workspace:^",
"@svenvw/fdm-core": "workspace:^",
"@svenvw/fdm-data": "workspace:*",
Expand All @@ -45,44 +44,44 @@
"drizzle-orm": "catalog:",
"file-type": "^21.0.0",
"flatgeobuf": "^4.1.1",
"framer-motion": "^12.23.6",
"isbot": "^5.1.28",
"framer-motion": "^12.23.12",
"isbot": "^5.1.29",
"lodash.throttle": "^4.1.1",
"lucide-react": "^0.525.0",
"mapbox-gl": "^3.13.0",
"lucide-react": "^0.539.0",
"mapbox-gl": "^3.14.0",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Mapbox GL 3.14 and proj4 2.19.x — verify worker/css import and ESM import style

  • Ensure client bundles import Mapbox CSS once to avoid styling regressions.
  • In ESM projects, avoid require("proj4"); prefer ESM imports.

Run:

If require("proj4") is found, replace with:

import proj4 from "proj4"

Also applies to: 58-58


🏁 Script executed:

#!/bin/bash
# Verify Mapbox CSS import present
rg -n 'mapbox-gl/dist/mapbox-gl.css' -g '!**/node_modules/**' || echo "Missing Mapbox GL CSS import"

# Flag any CommonJS imports of proj4
rg -n 'require\\(["\\\']proj4["\\\']\\)' -g '!**/node_modules/**' || true

Length of output: 476


🏁 Script executed:

#!/bin/bash
# Re-check CommonJS imports of proj4 with corrected quoting
rg -n "require\\(['\"]proj4['\"]\\)" -g '!**/node_modules/**' || echo "No CommonJS require of proj4 found"

Length of output: 144


Consolidate Mapbox GL CSS import and confirm ESM proj4 usage

  • Confirmed that Mapbox CSS is imported in:
    • fdm-app/app/root.tsx (line 2)
    • fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx (line 2)
    • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (line 8)
    To avoid duplicate styling, remove the CSS imports from the two route files and keep the single import in app/root.tsx.

  • No CommonJS require("proj4") calls were found in the codebase—ESM imports are already in use, so no changes needed for proj4.

Files to update:

  • Remove import "mapbox-gl/dist/mapbox-gl.css" from
    • 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
🤖 Prompt for AI Agents
In fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.atlas.tsx (around
line 2) and fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
(around line 8), remove the duplicate import statement import
"mapbox-gl/dist/mapbox-gl.css" so only the single CSS import in
fdm-app/app/root.tsx remains; simply delete those import lines from the two
route files and ensure no other mapbox CSS imports exist, no changes required
for proj4 as ESM imports are already used.

"next-themes": "^0.4.6",
"postgres": "^3.4.7",
"posthog-js": "^1.257.2",
"posthog-js": "^1.259.0",
"posthog-node": "^5.6.0",
"postmark": "^4.0.5",
"proj4": "^2.19.7",
"proj4": "^2.19.10",
"radix-ui": "^1.4.2",
"react": "^19.1.0",
"react-day-picker": "9.8.0",
"react-dom": "^19.1.0",
"react-hook-form": "^7.60.0",
"react": "^19.1.1",
"react-day-picker": "9.8.1",
"react-dom": "^19.1.1",
"react-hook-form": "^7.62.0",
"react-map-gl": "^8.0.4",
"react-markdown": "^10.1.0",
"react-router": "^7.7.0",
"react-router-dom": "^7.7.0",
"react-router": "^7.8.0",
"react-router-dom": "^7.8.0",
"recharts": "^2.15.4",
"remark-gfm": "^4.0.1",
"remix-hook-form": "7.1.0",
"remix-toast": "^3.1.0",
"remix-utils": "^8.7.0",
"remix-utils": "^8.8.0",
"shpjs": "^6.1.0",
"sonner": "^2.0.6",
"sonner": "^2.0.7",
"tailwind-merge": "^3.3.1",
"tailwindcss-animate": "^1.0.7",
"validator": "^13.15.15",
"vite-node": "^3.2.4",
"zod": "^3.25.76",
"zustand": "^5.0.6"
"zustand": "^5.0.7"
},
"devDependencies": {
"@dotenvx/dotenvx": "catalog:",
"@react-router/dev": "^7.7.0",
"@react-router/fs-routes": "^7.7.0",
"@react-router/dev": "^7.8.0",
"@react-router/fs-routes": "^7.8.0",
"@svenvw/fdm-calculator": "workspace:*",
"@svenvw/fdm-core": "workspace:*",
"@svenvw/fdm-data": "workspace:*",
Expand All @@ -92,8 +91,8 @@
"@types/mapbox-gl": "^3.4.1",
"@types/mapbox__geojson-extent": "^1.0.3",
"@types/mapbox__mapbox-gl-geocoder": "^5.0.0",
"@types/react": "^19.1.8",
"@types/react-dom": "^19.1.6",
"@types/react": "^19.1.10",
"@types/react-dom": "^19.1.7",
"@types/react-map-gl": "^6.1.7",
"@types/validator": "^13.15.2",
"postcss": "^8.5.6",
Expand All @@ -105,5 +104,5 @@
"engines": {
"node": ">=20.0.0"
},
"packageManager": "pnpm@10.13.1"
"packageManager": "pnpm@10.14.0"
}
20 changes: 20 additions & 0 deletions fdm-app/react-router.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,24 @@
import type { Config } from "@react-router/dev/config"
import { sentryOnBuildEnd } from "@sentry/react-router"
export default {
ssr: true,
buildEnd: async ({ viteConfig, reactRouterConfig, buildManifest }) => {
if (
process.env.SENTRY_AUTH_TOKEN !== undefined &&
process.env.NODE_ENV === "production"
) {
try {
await sentryOnBuildEnd({
viteConfig,
reactRouterConfig,
buildManifest,
})
} catch (err) {
console.warn(
"Sentry buildEnd hook failed; continuing without blocking the build.",
err,
)
}
}
},
} satisfies Config
Loading