Fix Maps Loading and Worker Configuration

Download the React DevTools for a better development experience: https://react.dev/link/react-devtools 1jtx_next_dist_0xxh72tjnquy-..js:720:28 [HMR] connected 1jtx_next_dist_0xxh72tjnquy-..js:720:28 Loading Worker from “http://localhost:3000/walk” was blocked because of a disallowed MIME type (“text/html”). walk Error: Worker failed to load. Check that the worker URL is correct. actors dispatcher.ts:39 1jtx_next_dist_0xxh72tjnquy-..js:996:32 Error: Worker failed to load. Check that the worker URL is correct. actors dispatcher.ts:39 1jtx_next_dist_0xxh72tjnquy-..js:996:32
[Fast Refresh] rebuilding 1jtx_next_dist_0xxh72tjnquy-..js:720:28 [Fast Refresh] done in 103ms 1jtx_next_dist_0xxh72tjnquy-..js:720:28 The resource at “http://localhost:3000/_next/static/media/a85fe84266768609-s.p.0h6ig86gwutp4.woff2” preloaded with link preload was not used within a few seconds. Make sure all attributes of the preload tag are set correctly. walk The resource at “http://localhost:3000/_next/static/media/70bc3e132a0a741e-s.p.3t6q91iet4nsy.woff2” preloaded with link preload was not used within a few seconds. Make sure all attributes of the preload tag are set correctly. walk The resource at “http://localhost:3000/_next/static/media/b67966e0b83b2cd0-s.p.0fuf3937kiol3.woff2” preloaded with link preload was not used within a few seconds. Make sure all attributes of the preload tag are set correctly. walk The resource at “http://localhost:3000/_next/static/media/c47649aa31f9e140-s.p.3lxpqujs87tck.woff2” preloaded with link preload was not used within a few seconds. Make sure all attributes of the preload tag are set correctly. walk Security Error: Content at http://localhost:3000/ may not load or link to file:///.
i have configured the required keys , but the maps dont load https://openrouteservice.org/dev/#/api-docs for reference
Root Cause
The map failure was caused by two separate aspects:
-
MapLibre GL Worker Resolution (
dispatcher.ts:39): MapLibre GL v6 uses an isolated web worker (maplibre-gl-worker.mjs) for vector tile processing. When dynamically imported in Next.js (via Turbopack/Webpack),import.meta.urldoes not resolve to the worker script location on the filesystem. MapLibre fell back to instantiatingnew Worker("")relative to the current route URL (http://localhost:3000/walk). Next.js answered that worker request with the HTML page document (text/html), causing the browser error: -
Keys & OpenRouteService:
- The map itself renders vector tiles from OpenFreeMap (
https://tiles.openfreemap.org/styles/liberty), which requires no API key. - Your OpenRouteService key in
.env.localis for the pedestrian walking loop generator (/api/route). We verified that your key is valid and working (tested live viaPOST /api/routewhich successfully returned a 2.6 km pedestrian loop withfallback: false). - We updated
app/api/route/route.tsso it accepts bothORS_API_KEYandOPENROUTESERVICE_API_KEY.
- The map itself renders vector tiles from OpenFreeMap (
What Was Fixed
- Copied the Standalone MapLibre Worker:
Placed
public/maplibre-gl-worker.mjsinto the staticpublic/directory so Next.js serves it directly asapplication/javascript. - Explicit Worker URL Configuration:
Configured
maplibregl.setWorkerUrl('/maplibre-gl-worker.mjs')upon module load in: - Dual Env Support for OpenRouteService:
Updated
app/api/route/route.tsto checkprocess.env.ORS_API_KEY || process.env.OPENROUTESERVICE_API_KEY.
Verification
- Verified
http://localhost:3000/maplibre-gl-worker.mjsreturnsHTTP 200 OK(Content-Type: application/javascript). - Tested
POST /api/routewith coordinates[-73.968, 40.785]; OpenRouteService successfully responded with full pedestrian coordinates andfallback: false. - Ran full evaluation suite:
pnpm test:eval(30/30 passed) andpnpm exec tsc --noEmit(clean type-check).
Page Feedback: /walk
Viewport: 1892×1012
1. <WalkPage> <WalkControls> button [Hold button to finalize and save your walk session]
Location: .absolute > .pointer-events-auto > .relative > .relative React: <WalkPage> <WalkControls> Feedback: button doesnt work
Download the React DevTools for a better development experience: https://react.dev/link/react-devtools 1jtx_next_dist_0xxh72tjnquy-..js:720:28 [HMR] connected 1jtx_next_dist_0xxh72tjnquy-..js:720:28 layers[highway-shield-non-us].filter[1]: Expected value to be of type number, but found null instead. Falling back to false. maplibre-gl-worker.mjs:5:114672 layers[highway-shield-us-interstate].filter[1]: Expected value to be of type number, but found null instead. Falling back to false. maplibre-gl-worker.mjs:5:114672 layers[road_shield_us].filter[1]: Expected value to be of type number, but found null instead. Falling back to false. maplibre-gl-worker.mjs:5:114672 Image "bollard" could not be loaded. Please make sure you have added the image before it is needed with map.addImage(), resolved it with map.setMissingStyleImageResolver(), or included it in a "sprite" property in your style. 1jtx_next_dist_0xxh72tjnquy-..js:720:28 Image "sports_centre" could not be loaded. Please make sure you have added the image before it is needed with map.addImage(), resolved it with map.setMissingStyleImageResolver(), or included it in a "sprite" property in your style. 1jtx_next_dist_0xxh72tjnquy-..js:720:28 Image "gate" could not be loaded. Please make sure you have added the image before it is needed with map.addImage(), resolved it with map.setMissingStyleImageResolver(), or included it in a "sprite" property in your style. 1jtx_next_dist_0xxh72tjnquy-..js:720:28 Image "atm" could not be loaded. Please make sure you have added the image before it is needed with map.addImage(), resolved it with map.setMissingStyleImageResolver(), or included it in a "sprite" property in your style. 1jtx_next_dist_0xxh72tjnquy-..js:720:28 Image "swimming_pool" could not be loaded. Please make sure you have added the image before it is needed with map.addImage(), resolved it with map.setMissingStyleImageResolver(), or included it in a "sprite" property in your style. 1jtx_next_dist_0xxh72tjnquy-..js:720:28 Image "office" could not be loaded. Please make sure you have added the image before it is needed with map.addImage(), resolved it with map.setMissingStyleImageResolver(), or included it in a "sprite" property in your style. 1jtx_next_dist_0xxh72tjnquy-..js:720:28 Image "gymnastics" could not be loaded. Please make sure you have added the image before it is needed with map.addImage(), resolved it with map.setMissingStyleImageResolver(), or included it in a "sprite" property in your style. 1jtx_next_dist_0xxh72tjnquy-._.js:720:28
Why the Button Didn't Respond
In components/walk/walk-controls.tsx:
- Missing Click Handler (
onClick): The button only listened to mouse-down/up and touch events and enforced a continuous 1.5-second hold (HOLD_DURATION_MS = 1500). When clicked or tapped normally on desktop (like in your 1892×1012 viewport), mouse-up cancelled the timer after ~100ms. Because there was noonClickhandler, the action was simply dropped, giving the appearance of a dead/broken button. - Fragile Mouse-Leave Cancellation:
Any slight cursor movement during mouse-down fired
onMouseLeave, which instantly aborted the hold timer. - No Visible Feedback: There was no text or tooltip explaining that the button required a long-press.
What Was Fixed
- Dual Support for Click and Hold (
components/walk/walk-controls.tsx):- Click / Tap: Instantly triggers the end-walk flow.
- Hold (1.0s): Animates the circular progress ring with haptic feedback and automatically finalizes the walk upon completion.
- 2-Tap Confirmation Safety (per D-13):
- For short walks under 1 minute: clicking immediately opens
WalkDiscardDialog("Discard Walk" or "Save Anyway"). - For active walks: clicking opens a new
WalkEndDialog("End & Save Walk" or "Continue Walking"), guarding against accidental taps without blocking desktop users. - A deliberate hold bypasses the confirmation dialog and finalizes immediately.
- For short walks under 1 minute: clicking immediately opens
- Pointer Capture:
Switched to pointer events with
setPointerCapture, ensuring slight mouse movement or touch jitter does not prematurely cancel a hold. - Visual Guidance:
- Added hover/idle hint:
"Hold to finish, or click to confirm" - Added active hold label:
"Ending walk..."with a smooth SVG progress indicator.
- Added hover/idle hint:
okay gps works , A. On loop route, A.1. on larger kms , loops are bigger, but some have too many turns, if code allows it, I would prefer the least turns for a loop. A.2. the route automatically updates, wasting api calls, only show 1 route, and add 2 buttons, to refresh (new route) and previous (cycle between all generated routes) A. 3. Allow user to maybe add custom stops on the map , or start / finish locations (default is current system) A. 4. Dark/light mode in map if possible
All 4 requested improvements have been implemented and verified:
A.1. Least Turns for Loop Routes
- OpenRouteService Minimum Vertices: In
app/api/route/route.ts, updatedoptions.round_trip.pointsfrom5to3(the minimum supported). Fewer guide vertices forces OpenRouteService to calculate triangular, direct walking perimeters rather than convoluted, zigzagging loops through side alleys. - Smoothed Synthetic Fallback: In
lib/route.ts, reduced synthetic geometric oscillations to gentle single-harmonic curves, eliminating noisy artificial turns.
A.2. Controlled Generation (No Auto-Updates) + Cycle & Refresh
- Eliminated GPS Auto-Updates: In
components/route/route-preview-sheet.tsx, decoupled route fetching from live GPS position ticks. The route now generates once when you switch to Loop Route or change distance, and stays steady without consuming API calls on GPS jitter. New RouteRefresh Button: Generates a new alternative loop using a randomized seed while preserving the least-turns constraint.Previous/NextHistory Cycling: Keeps an in-memory history of all generated routes for that session. You can cycle between them (Route 1 of 3,Route 2 of 3, etc.) instantly with zero extra API requests.
A.3. Custom Stops & Endpoints
- Interactive Waypoint Customization: Added an expandable Custom Stops & Waypoints panel in
components/route/route-preview-sheet.tsx. - Map Click Placement: Tapping "Tap Map to Add Stop" switches the map cursor to
crosshairand shows an interactive placement banner. Tapping anywhere on the map places a numbered amber stop pin (1,2,3...). - Route Through Stops: When stops exist, the routing engine routes through your sequence
[Start → Stop 1 → Stop 2 → ... → Finish]. - Remove & Clear: Tapping any stop pin on the map or its removal button in the sheet deletes the stop and updates the route.
A.4. Dark & Light Mode on the Map
- Dynamic Vector Tile Styles:
- Light mode:
https://tiles.openfreemap.org/styles/libertywith moss-green route and trail overlays. - Dark mode:
https://tiles.openfreemap.org/styles/darkwith luminous mint/emerald overlays (#34d399/#22c55e).
- Light mode:
- Live Theme Synchronization: Added document class mutation observer and
themechangelistener incomponents/map/walk-map.tsx. Toggling the sun/moon button dynamically callsmap.setStyle()and seamlessly re-applies the route line and markers.
some caveates
- map text doesnt show in dark mode, nothing beside path and roads shows in dark mode (icons etc), check and update
- some time route calculation shows route length larger than set (eg : set 1 , calculated 4.3) 3.## Page Feedback: /walk Viewport: 1892×1012
1. <WalkPage> <ThemeToggle> <Moon> button icon
Location: .absolute > .rounded-full > .inline-flex > svg React: <WalkPage> <ThemeToggle> <Moon> Feedback: nested in a div, redundant , remove the circular container
All three reported caveats have been resolved and verified:
1. Map Text and Icons in Dark Mode
- Root Cause: OpenFreeMap's default
darkstyle was based on Carto Dark Matter, which omitted all POI layers (parks, transit, amenities) and rendered street names in low-contrast dark charcoal (#504e4e) on a black canvas with zero icons. - Fix:
- Created a dedicated dark-adapted style
public/styles/dark-liberty.jsonthat preserves all 111 layers from Liberty (every POI, transit icon, trail, and park). - Styled street names, labels, and POIs with high-contrast text (
#ffffff,#e2e8f0,#86efac,#7dd3fc) and deep halos (#0a1120), ensuring street names and points of interest are crisp and legible in dark mode. - Added a
styleimagemissinghandler incomponents/map/walk-map.tsxto gracefully resolve missing sprite icons without console error spam.
- Created a dedicated dark-adapted style
2. Route Length Mismatch (Set 1 km, Calculated 4.3 km)
- Root Cause: When
points: 3was requested in areas with road barriers or highway overpasses, OpenRouteService's pedestrian router would occasionally detour kilometers around pedestrian-inaccessible intersections. - Fix:
- In
app/api/route/route.ts, added multi-candidate seed evaluation and strict distance tolerance bounds (≤ 35%). - If a seed yields a massive detour (e.g., 4.3 km for a 1 km request), alternative seeds are checked.
- If local road geometry cannot accommodate a low-turn walking loop within tolerance, the API falls back to a calibrated pedestrian loop matching the exact target distance (~1.0 km).
- In
lib/route.ts, added seed-driven rotation togenerateSyntheticLoopso cycling or requesting "New Route" provides distinct compass headings.
- In
3. Removed Redundant Outer Wrapper around ThemeToggle
- Fix: In
app/walk/page.tsx, removed the outer circular container<div className="rounded-full bg-background/80 ...">and applied the button styling directly to<ThemeToggle />, eliminating the double border/circle while matching the top-left back button.
Building rendering in dark mode has been updated to be sleek and dark-mode friendly:
What Changed
- 3D Building Extrusions (
building-3d): Replaced the bright off-white fill (hsl(35, 8%, 85%)/#dad7d4) with a dark slate tone (#222c3f,opacity: 0.85). - 2D Building Footprints (
building): Replaced the light outline and bright fill with a matching charcoal-slate fill (#1c2333) and subtle edge borders (#273248).
The buildings now blend naturally with the surrounding dark roads and greenery without glaring white blocks, while preserving full architectural visibility and street-level spatial clarity.