From 36b1b99c151b90cab10486f0af4166c669b4fa99 Mon Sep 17 00:00:00 2001
From: Sven Verweij <37927107+SvenVw@users.noreply.github.com>
Date: Mon, 22 Dec 2025 14:07:09 +0100
Subject: [PATCH 1/6] fix: TypeError when `updatePanel` attempts to access
`map.getLayer(layer)` before the map is fully initialized
---
.changeset/silly-shoes-shake.md | 5 +++++
fdm-app/app/components/blocks/atlas/atlas-panels.tsx | 2 +-
2 files changed, 6 insertions(+), 1 deletion(-)
create mode 100644 .changeset/silly-shoes-shake.md
diff --git a/.changeset/silly-shoes-shake.md b/.changeset/silly-shoes-shake.md
new file mode 100644
index 000000000..9db570076
--- /dev/null
+++ b/.changeset/silly-shoes-shake.md
@@ -0,0 +1,5 @@
+---
+"@svenvw/fdm-app": patch
+---
+
+Fix TypeError when `updatePanel` attempts to access `map.getLayer(layer)` before the map is fully initialized
diff --git a/fdm-app/app/components/blocks/atlas/atlas-panels.tsx b/fdm-app/app/components/blocks/atlas/atlas-panels.tsx
index 6fc8d6155..f73d34ef2 100644
--- a/fdm-app/app/components/blocks/atlas/atlas-panels.tsx
+++ b/fdm-app/app/components/blocks/atlas/atlas-panels.tsx
@@ -39,7 +39,7 @@ export function FieldsPanelHover({
// Set message about zoom level
const zoom = map.getZoom()
if (zoom && zoom > zoomLevelFields) {
- if (!map.getLayer(layer)) return
+ if (!map.getStyle() || !map.getLayer(layer)) return
const features = map.queryRenderedFeatures(evt.point, {
layers: [layer],
From 067c0de49c95f5da5d35c879f3e70c39bca44330 Mon Sep 17 00:00:00 2001
From: Sven Verweij <37927107+SvenVw@users.noreply.github.com>
Date: Mon, 22 Dec 2025 14:44:50 +0100
Subject: [PATCH 2/6] fix: AggregateError in Elevation Atlas by implementing
chunked concurrency for sampling requests to avoid exceeding HTTP/1.1
connection limits.
---
.changeset/yummy-wombats-live.md | 5 +
...m.$b_id_farm.$calendar.atlas.elevation.tsx | 118 ++++++++----------
2 files changed, 56 insertions(+), 67 deletions(-)
create mode 100644 .changeset/yummy-wombats-live.md
diff --git a/.changeset/yummy-wombats-live.md b/.changeset/yummy-wombats-live.md
new file mode 100644
index 000000000..a3ee54d5e
--- /dev/null
+++ b/.changeset/yummy-wombats-live.md
@@ -0,0 +1,5 @@
+---
+"@svenvw/fdm-app": patch
+---
+
+Fix AggregateError in Elevation Atlas by implementing chunked concurrency for sampling requests to avoid exceeding HTTP/1.1 connection limits
diff --git a/fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx b/fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
index 2d9ffd17f..80316b1a5 100644
--- a/fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
+++ b/fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
@@ -87,7 +87,6 @@ interface ActiveTile {
id: string
url: string
cogUrl: string | null
- cogUrlHillshade: string | null
}
// Meta
@@ -318,7 +317,7 @@ export default function FarmAtlasElevationBlock() {
const ring = (f.geometry as any).coordinates[0]
return polygonIntersectsPolygon(rdCoords, ring)
})
- .slice(0, 24)
+ .slice(0, 12)
// Calculate global min/max for the viewport by sampling
const samplePoints: { lng: number; lat: number }[] = []
@@ -334,49 +333,60 @@ export default function FarmAtlasElevationBlock() {
let min = 1000
let max = -1000
- // Gather values for samples
- const values = await Promise.all(
- samplePoints.map(async (p) => {
- try {
- const rdP = proj4("EPSG:28992").forward([
- p.lng,
- p.lat,
- ]) as [number, number]
- // Find which tile contains this point
- const feature = visibleFeatures.find((f) => {
- if (!f.geometry || f.geometry.type !== "Polygon")
- return false
- const ring = (f.geometry as any).coordinates[0]
- return isPointInPolygon(rdP, ring)
- })
- if (feature?.properties) {
- const url =
- feature.properties.url ||
- feature.properties.href ||
- feature.properties.download_url
- if (url) {
- // Requesting location value
- const vals = await locationValues(url, {
- longitude: p.lng,
- latitude: p.lat,
- })
+ // Gather values for samples with concurrency limit
+ const results: (number | null)[] = []
+ const chunkSize = 4
+ for (let i = 0; i < samplePoints.length; i += chunkSize) {
+ const chunk = samplePoints.slice(i, i + chunkSize)
+ const chunkResults = await Promise.all(
+ chunk.map(async (p) => {
+ try {
+ const rdP = proj4("EPSG:28992").forward([
+ p.lng,
+ p.lat,
+ ]) as [number, number]
+ // Find which tile contains this point
+ const feature = visibleFeatures.find((f) => {
if (
- vals &&
- vals.length > 0 &&
- !Number.isNaN(vals[0]) &&
- vals[0] > -100 &&
- vals[0] < 1000
- ) {
- return vals[0]
+ !f.geometry ||
+ f.geometry.type !== "Polygon"
+ )
+ return false
+ const ring = (f.geometry as any).coordinates[0]
+ return isPointInPolygon(rdP, ring)
+ })
+ if (feature?.properties) {
+ const url =
+ feature.properties.url ||
+ feature.properties.href ||
+ feature.properties.download_url
+ if (url) {
+ // Requesting location value
+ const vals = await locationValues(url, {
+ longitude: p.lng,
+ latitude: p.lat,
+ })
+ if (
+ vals &&
+ vals.length > 0 &&
+ !Number.isNaN(vals[0]) &&
+ vals[0] > -100 &&
+ vals[0] < 1000
+ ) {
+ return vals[0]
+ }
}
}
+ } catch {
+ // Ignore errors for individual points
}
- } catch {
- // Ignore errors for individual points
- }
- return null
- }),
- )
+ return null
+ }),
+ )
+ results.push(...chunkResults)
+ }
+
+ const values = results
if (updateId.current !== currentId) return
@@ -421,7 +431,6 @@ export default function FarmAtlasElevationBlock() {
id,
url,
cogUrl: `cog://${url}${colorParam}`,
- cogUrlHillshade: `cog://${url}#dem`,
})
}
@@ -601,31 +610,6 @@ export default function FarmAtlasElevationBlock() {
}
/>
-
-
-
))}
From 1274a327040bcba456670ca439864d72539ac0a8 Mon Sep 17 00:00:00 2001
From: Sven Verweij <37927107+SvenVw@users.noreply.github.com>
Date: Mon, 22 Dec 2025 15:21:24 +0100
Subject: [PATCH 3/6] refactor: Optimize Elevation Atlas stability and
performance: implement chunked sampling concurrency, server-side AHN index
caching, geometry simplification and WMS layer zoom constraints
---
.changeset/witty-foxes-lose.md | 5 +++
fdm-app/app/integrations/ahn-cache.server.ts | 34 +++++++++++++++++++
fdm-app/app/routes/atlas.ahn-index.tsx | 11 ++++++
...m.$b_id_farm.$calendar.atlas.elevation.tsx | 15 +++++---
..._id_farm.$calendar.atlas.fields._index.tsx | 6 +++-
.../farm.$b_id_farm.$calendar.atlas.soil.tsx | 6 +++-
...farm.create.$b_id_farm.$calendar.atlas.tsx | 6 +++-
7 files changed, 75 insertions(+), 8 deletions(-)
create mode 100644 .changeset/witty-foxes-lose.md
create mode 100644 fdm-app/app/integrations/ahn-cache.server.ts
create mode 100644 fdm-app/app/routes/atlas.ahn-index.tsx
diff --git a/.changeset/witty-foxes-lose.md b/.changeset/witty-foxes-lose.md
new file mode 100644
index 000000000..bec69dfbf
--- /dev/null
+++ b/.changeset/witty-foxes-lose.md
@@ -0,0 +1,5 @@
+---
+"@svenvw/fdm-app": patch
+---
+
+Optimize Elevation Atlas stability and performance: implement chunked sampling concurrency, server-side AHN index caching, geometry simplification and WMS layer zoom constraints
diff --git a/fdm-app/app/integrations/ahn-cache.server.ts b/fdm-app/app/integrations/ahn-cache.server.ts
new file mode 100644
index 000000000..f95174617
--- /dev/null
+++ b/fdm-app/app/integrations/ahn-cache.server.ts
@@ -0,0 +1,34 @@
+import type { FeatureCollection } from "geojson"
+
+let cache: { data: FeatureCollection; expires: number } | null = null
+const CACHE_TTL = 24 * 60 * 60 * 1000 // 24 hours in milliseconds
+
+export async function getAhnIndex(): Promise {
+ const now = Date.now()
+
+ if (cache && cache.expires > now) {
+ return cache.data
+ }
+
+ try {
+ console.log("Fetching AHN index from PDOK...")
+ const response = await fetch(
+ "https://service.pdok.nl/rws/ahn/atom/downloads/dtm_05m/kaartbladindex.json",
+ )
+
+ if (!response.ok) {
+ throw new Error(`Failed to fetch AHN index: ${response.statusText}`)
+ }
+
+ const data = (await response.json()) as FeatureCollection
+ cache = {
+ data,
+ expires: now + CACHE_TTL,
+ }
+ return data
+ } catch (error) {
+ console.error("Error fetching AHN index, serving stale cache if available", error)
+ if (cache) return cache.data
+ throw error
+ }
+}
diff --git a/fdm-app/app/routes/atlas.ahn-index.tsx b/fdm-app/app/routes/atlas.ahn-index.tsx
new file mode 100644
index 000000000..dc044c2df
--- /dev/null
+++ b/fdm-app/app/routes/atlas.ahn-index.tsx
@@ -0,0 +1,11 @@
+import { type LoaderFunctionArgs, data } from "react-router"
+import { getAhnIndex } from "@/app/integrations/ahn-cache.server"
+
+export async function loader() {
+ const ahnIndex = await getAhnIndex()
+ return data(ahnIndex, {
+ headers: {
+ "Cache-Control": "public, max-age=86400, s-maxage=86400",
+ },
+ })
+}
diff --git a/fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx b/fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
index 80316b1a5..f3d67c295 100644
--- a/fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
+++ b/fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
@@ -4,6 +4,7 @@ import {
proj4,
} from "@geomatico/maplibre-cog-protocol"
import { getFields } from "@svenvw/fdm-core"
+import { simplify } from "@turf/turf"
import type { FeatureCollection } from "geojson"
import throttle from "lodash.throttle"
import maplibregl from "maplibre-gl"
@@ -130,7 +131,10 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
b_lu_name: field.b_lu_name,
b_id_source: field.b_id_source,
},
- geometry: field.b_geometry,
+ geometry: simplify(field.b_geometry as any, {
+ tolerance: 0.00001,
+ highQuality: true,
+ }),
}
return feature
})
@@ -239,9 +243,9 @@ export default function FarmAtlasElevationBlock() {
}
}
- const response = await fetch(
- "https://service.pdok.nl/rws/ahn/atom/downloads/dtm_05m/kaartbladindex.json",
- )
+ // Fetch from our server-side cache
+ const response = await fetch("/resources/ahn-index")
+
if (!response.ok) throw new Error("Failed to fetch COG index")
const data = (await response.json()) as FeatureCollection
setIndexData(data)
@@ -566,7 +570,7 @@ export default function FarmAtlasElevationBlock() {
{/* WMS Overview Layer (Zoom < 13) */}
- {showElevation && (
+ {showElevation && viewState.zoom < 13 && (
Date: Mon, 22 Dec 2025 15:43:17 +0100
Subject: [PATCH 4/6] refactor: improve type
---
.../app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx | 4 ++--
.../routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx | 4 ++--
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx | 3 ++-
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx | 3 ++-
4 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx b/fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
index f3d67c295..d7609ed7d 100644
--- a/fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
+++ b/fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
@@ -5,7 +5,7 @@ import {
} from "@geomatico/maplibre-cog-protocol"
import { getFields } from "@svenvw/fdm-core"
import { simplify } from "@turf/turf"
-import type { FeatureCollection } from "geojson"
+import type { FeatureCollection, Geometry } from "geojson"
import throttle from "lodash.throttle"
import maplibregl from "maplibre-gl"
import {
@@ -131,7 +131,7 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
b_lu_name: field.b_lu_name,
b_id_source: field.b_id_source,
},
- geometry: simplify(field.b_geometry as any, {
+ geometry: simplify(field.b_geometry as Geometry, {
tolerance: 0.00001,
highQuality: true,
}),
diff --git a/fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx b/fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
index e806cb55e..101d46098 100644
--- a/fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
+++ b/fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
@@ -1,6 +1,6 @@
import { getFields } from "@svenvw/fdm-core"
import { simplify } from "@turf/turf"
-import type { FeatureCollection } from "geojson"
+import type { FeatureCollection, Geometry } from "geojson"
import maplibregl from "maplibre-gl"
import { useCallback, useEffect, useRef, useState } from "react"
import {
@@ -84,7 +84,7 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
b_lu_name: field.b_lu_name,
b_id_source: field.b_id_source,
},
- geometry: simplify(field.b_geometry as any, {
+ geometry: simplify(field.b_geometry as Geometry, {
tolerance: 0.00001,
highQuality: true,
}),
diff --git a/fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx b/fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
index 70ee8300d..de49aaec2 100644
--- a/fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
+++ b/fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
@@ -1,5 +1,6 @@
import { getFields } from "@svenvw/fdm-core"
import { simplify } from "@turf/turf"
+import { Geometry } from "geojson"
import {
data,
type LoaderFunctionArgs,
@@ -68,7 +69,7 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
b_name: field.b_name,
b_area: Math.round(field.b_area * 10) / 10,
},
- geometry: simplify(field.b_geometry as any, {
+ geometry: simplify(field.b_geometry as Geometry, {
tolerance: 0.00001,
highQuality: true,
}),
diff --git a/fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx b/fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
index 8890134d7..075f8f753 100644
--- a/fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
+++ b/fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
@@ -12,6 +12,7 @@ import type {
Feature,
FeatureCollection,
GeoJsonProperties,
+ Geometry,
Polygon,
} from "geojson"
import maplibregl from "maplibre-gl"
@@ -149,7 +150,7 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
b_lu_name: cultivation,
b_id_source: field.b_id_source,
},
- geometry: simplify(field.b_geometry as any, {
+ geometry: simplify(field.b_geometry as Geometry, {
tolerance: 0.00001,
highQuality: true,
}),
From 14350dfd5e14db09fcfa478411d11586800c7145 Mon Sep 17 00:00:00 2001
From: Sven Verweij <37927107+SvenVw@users.noreply.github.com>
Date: Mon, 22 Dec 2025 15:47:55 +0100
Subject: [PATCH 5/6] nitpicks
---
fdm-app/app/integrations/ahn-cache.server.ts | 9 ++++++++-
fdm-app/app/routes/atlas.ahn-index.tsx | 2 +-
.../farm.$b_id_farm.$calendar.atlas.elevation.tsx | 10 +++++++---
3 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/fdm-app/app/integrations/ahn-cache.server.ts b/fdm-app/app/integrations/ahn-cache.server.ts
index f95174617..e665b34fb 100644
--- a/fdm-app/app/integrations/ahn-cache.server.ts
+++ b/fdm-app/app/integrations/ahn-cache.server.ts
@@ -14,6 +14,7 @@ export async function getAhnIndex(): Promise {
console.log("Fetching AHN index from PDOK...")
const response = await fetch(
"https://service.pdok.nl/rws/ahn/atom/downloads/dtm_05m/kaartbladindex.json",
+ { signal: AbortSignal.timeout(30000) }, // 30 second timeout
)
if (!response.ok) {
@@ -21,13 +22,19 @@ export async function getAhnIndex(): Promise {
}
const data = (await response.json()) as FeatureCollection
+ if (!data.features || !Array.isArray(data.features)) {
+ throw new Error("Invalid AHN index format")
+ }
cache = {
data,
expires: now + CACHE_TTL,
}
return data
} catch (error) {
- console.error("Error fetching AHN index, serving stale cache if available", error)
+ console.error(
+ "Error fetching AHN index, serving stale cache if available",
+ error,
+ )
if (cache) return cache.data
throw error
}
diff --git a/fdm-app/app/routes/atlas.ahn-index.tsx b/fdm-app/app/routes/atlas.ahn-index.tsx
index dc044c2df..4ea54b58a 100644
--- a/fdm-app/app/routes/atlas.ahn-index.tsx
+++ b/fdm-app/app/routes/atlas.ahn-index.tsx
@@ -1,4 +1,4 @@
-import { type LoaderFunctionArgs, data } from "react-router"
+import { data } from "react-router"
import { getAhnIndex } from "@/app/integrations/ahn-cache.server"
export async function loader() {
diff --git a/fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx b/fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
index d7609ed7d..bd0d7a3ad 100644
--- a/fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
+++ b/fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
@@ -272,6 +272,10 @@ export default function FarmAtlasElevationBlock() {
const updateId = useRef(0)
// Function to update visible tiles
+ const activeTilesLengthRef = useRef(activeTiles.length)
+ useEffect(() => {
+ activeTilesLengthRef.current = activeTiles.length
+ }, [activeTiles])
const updateVisibleTiles = useCallback(async () => {
if (!mapRef.current || !indexData) return
@@ -280,7 +284,7 @@ export default function FarmAtlasElevationBlock() {
// If zoomed out, clear active tiles to save resources (WMS will take over)
if (zoom < 13) {
- if (activeTiles.length > 0) {
+ if (activeTilesLengthRef.current > 0) {
setActiveTiles([])
}
return
@@ -313,7 +317,7 @@ export default function FarmAtlasElevationBlock() {
] as [number, number][]
// Find intersecting tiles
- // Optimization: limit to e.g. 24 tiles to avoid overload
+ // Optimization: limit to 12 tiles to avoid overload
const visibleFeatures = indexData.features
.filter((f) => {
if (!f.geometry || f.geometry.type !== "Polygon")
@@ -451,7 +455,7 @@ export default function FarmAtlasElevationBlock() {
}
clearTimeout(slowTimer)
}
- }, [indexData, activeTiles])
+ }, [indexData])
// Throttle updates
const updateRef = useRef(updateVisibleTiles)
From c7b7d49003a7e20a5db50cfde357c38a3b38016b Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
Date: Mon, 22 Dec 2025 14:56:21 +0000
Subject: [PATCH 6/6] chore: bump version of packages for release
---
.changeset/silly-shoes-shake.md | 5 -----
.changeset/witty-foxes-lose.md | 5 -----
.changeset/yummy-wombats-live.md | 5 -----
fdm-app/CHANGELOG.md | 8 ++++++++
fdm-app/package.json | 2 +-
5 files changed, 9 insertions(+), 16 deletions(-)
delete mode 100644 .changeset/silly-shoes-shake.md
delete mode 100644 .changeset/witty-foxes-lose.md
delete mode 100644 .changeset/yummy-wombats-live.md
diff --git a/.changeset/silly-shoes-shake.md b/.changeset/silly-shoes-shake.md
deleted file mode 100644
index 9db570076..000000000
--- a/.changeset/silly-shoes-shake.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@svenvw/fdm-app": patch
----
-
-Fix TypeError when `updatePanel` attempts to access `map.getLayer(layer)` before the map is fully initialized
diff --git a/.changeset/witty-foxes-lose.md b/.changeset/witty-foxes-lose.md
deleted file mode 100644
index bec69dfbf..000000000
--- a/.changeset/witty-foxes-lose.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@svenvw/fdm-app": patch
----
-
-Optimize Elevation Atlas stability and performance: implement chunked sampling concurrency, server-side AHN index caching, geometry simplification and WMS layer zoom constraints
diff --git a/.changeset/yummy-wombats-live.md b/.changeset/yummy-wombats-live.md
deleted file mode 100644
index a3ee54d5e..000000000
--- a/.changeset/yummy-wombats-live.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@svenvw/fdm-app": patch
----
-
-Fix AggregateError in Elevation Atlas by implementing chunked concurrency for sampling requests to avoid exceeding HTTP/1.1 connection limits
diff --git a/fdm-app/CHANGELOG.md b/fdm-app/CHANGELOG.md
index 26d07dfe5..9dc444af5 100644
--- a/fdm-app/CHANGELOG.md
+++ b/fdm-app/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog fdm-app
+## 0.26.1
+
+### Patch Changes
+
+- 36b1b99: Fix TypeError when `updatePanel` attempts to access `map.getLayer(layer)` before the map is fully initialized
+- 1274a32: Optimize Elevation Atlas stability and performance: implement chunked sampling concurrency, server-side AHN index caching, geometry simplification and WMS layer zoom constraints
+- 067c0de: Fix AggregateError in Elevation Atlas by implementing chunked concurrency for sampling requests to avoid exceeding HTTP/1.1 connection limits
+
## 0.26.0
### Minor Changes
diff --git a/fdm-app/package.json b/fdm-app/package.json
index 9609c80e0..0f4c448c5 100644
--- a/fdm-app/package.json
+++ b/fdm-app/package.json
@@ -1,6 +1,6 @@
{
"name": "@svenvw/fdm-app",
- "version": "0.26.0",
+ "version": "0.26.1",
"private": true,
"sideEffects": false,
"type": "module",