# Next.js WebSocket live tracking with Google Maps

> Published 2026-10-26T00:42:09.718Z on https://youblog.app/p/next-js-websocket-live-tracking-with-google-maps/
> Source video: https://www.youtube.com/watch?v=eBkM0NUGj4g

Most of the live tracking tutorial is not the map code. It is the filtering. Next.js WebSocket live tracking only behaves once each message is checked against the ride you are looking at and the drawing is kept out of the socket handler.

## How does Next.js WebSocket live tracking work on a Google Maps page?

Next.js WebSocket live tracking works by holding one Socket.IO connection open on the ride detail page, filtering every incoming coordinate against that page's ride ID, and appending matching points to React state that a Google Maps polyline redraws. The car marker follows the newest point; the tracked line shows the path already driven.

The pattern comes from a Gustavo Dev Doido tutorial published on 2023-12-27, the 42nd lesson in a Portuguese-language build of a driver tracking app using [Next.js](https://nextjs.org/) and Google Maps. The approach separates three concerns: server-side data fetching for the planned route, a socket subscription for live coordinates, and a drawing layer that maps state to overlays.

That separation matters because the page loads with history already in the database. If the map relied only on socket messages, a reader opening a ride mid-trip would see nothing until the next coordinate arrived.

## Which Google Maps overlays show a planned route against the driven path?

Two overlays do the work: a dark polyline for the route the trip was supposed to follow and a white polyline for the road actually covered. The video sets the driven line to the colour value fff and makes the per-point markers invisible so only the car icon and the white trail read clearly.

The distinction is visible in the demo. The darker road sits underneath, the white line traces the same road while the driver stays on route, and any deviation shows as the white line leaving the planned road. That is the simplest available signal for a detour, without a separate corridor comparison.

This is presentation, not routing. The Google Maps overlay only draws coordinates it receives. The page does not recalculate a route on the client; see the [Google Maps JavaScript API documentation](https://developers.google.com/maps/documentation/javascript) for what polylines and markers can carry.

## Why does a ride ID filter stop the map drawing another driver's trip?

A ride ID filter prevents cross-talk when several rides share one route. Without it, a socket message from a second ride on the same road passes the check, appends a point to the wrong map, and the car appears to jump. The fix is a strict comparison against the ride driver ID held by the page.

The tutorial hits this bug live. Two rides are started on the same route, and the detail page for one of them starts receiving points from the other. The comparison in the handler was looking at a ride identifier that matched both, so a different identifier from the socket payload had to be compared instead.

The system is deliberately one-to-many: one route can be taken by many drivers, so messages for other rides are expected on the same connection. Filtering is not an edge case, it is the normal path.

Handle this before styling anything. A correct polyline attached to the wrong ride is worse than a missing one.

## What is the data flow from server render to socket message?

The ride detail page fetches the ride driver record on the server, hands it to the client component as a prop, and the client opens the socket subscription using the identifier inside that record. Every incoming payload is validated, compared, and only then appended to the points array that drives the map overlays.

The sequence below follows the lesson's order, with the two drawing passes kept separate because they run at different times.

1. On the server, read the ride driver record for the page's ride ID and pass it into the map component.

2. On the client, initialise the map once the map container ref is set, then subscribe to the socket message event.

3. In the handler, check that the payload is a valid object with a ride ID, and that the ride ID matches the page's ride driver record. Return early if either check fails.

4. Append a location object to the points array with the coordinates from the payload.

5. On the first map render, draw the stored points as consecutive segments so history appears immediately.

6. On each change to the points array, draw only the new segment and move the car marker to the latest coordinate.

The two drawing functions exist because one runs once with stored history and one runs continuously with live data. The video's author says this directly: one effect loops with for...of at load, the other loops through updates as messages arrive.

## How do you draw the driven path segment by segment?

Segment by segment, each stored point becomes the start of a short polyline and the next point becomes its end, with the car marker pinned to the newest point. The video builds each step's line with a unique key derived from the coordinates so the map does not confuse two segments at the same place.

A single polyline containing every point would be simpler, but the tutorial creates a line per hop. The cost is more overlay objects on long trips; the benefit is a straightforward mapping from points array index to screen geometry while debugging.

Two details prevent flicker. Debounce redraws with a stored timeout ID so frequent coordinates do not thrash the map, and convert latitude and longitude to numbers before handing them to the overlay, since stored values can arrive as strings.

When a websocket route is redrawn on every message without that debounce, the map visibly jumps between zoom levels. Watch for it during testing and cap the redraw rate.

## Where do the points come from and how are they stored?

Points arrive from the driver side and land in the ride driver record, and the client only reads them. In the lesson the driver is simulated, the ride driver record is created with an empty points array, and the coordinates are streamed over the socket as the simulation walks the route.

The video also describes a backend path the client never sees: socket messages feed a topic that a consumer drains into the database, so persistence does not run inside the websocket handler. The client only needs the ride driver ID and the stored points, which is why the page can render a full trip from server-side data before any live message arrives.

The lesson series is built inside a course called Crazystack TypeScript, and the accompanying materials are published at [crazystack.com.br](https://crazystack.com.br). Treat the series as a teaching build rather than a production reference; the author says at the end that the system still needs to mature.

## What broke during the live test, and what does it teach?

The live test broke in three visible ways: the car drew a route from the wrong ride, the first render missed points that arrived before the page finished loading, and the redraw loop had an off-by-one check that skipped the final segment. Each failure points at a check, not at the mapping library.

The wrong-ride bug was a comparison against an identifier shared by two rides. The missing-history bug came from loading a ride that had already finished; the page rendered before live messages started, so the stored points had to be drawn in a separate pass. The segment bug sat in a comparison between the current index and the array length, where the boundary condition excluded the last point.

The lesson ends with the white trail visible over the darker route, the car moving, and the detour signal readable. The author notes that the demo prioritised speed of construction over polish.

## FAQ

- **Is this a production-ready tracking architecture?** No. The video is a teaching build from a lesson series, and the author says the system still needs to mature. The page-level filtering and the redraw debounce are the parts most worth reusing.

- **Which Socket.IO version does the video use?** The December 2023 video does not state a version. Check the [Socket.IO documentation](https://socket.io/docs/v4/) for the client and server versions you are actually installing, because event names and connection options have changed across majors.

- **Do I need server-side rendering to show the driven path?** No, but it helps. Fetching the ride driver record on the server means the planned route and stored history render on first paint instead of after a client request.

- **Why compare two identifiers instead of one?** One route can be shared by many drivers, so the ride identifier alone does not identify a live driver. The socket payload has to carry an identifier unique to the driver's ride.

- **How often should the map redraw?** Less often than messages arrive. The video stores a timeout ID per redraw to avoid refreshing the map on every coordinate; a test on a slower network will show whether a longer interval is needed.

- **Can the same approach detect route deviations automatically?** Not on its own. The visual comparison between the white driven line and the dark planned route is manual; tolerance checks would need a separate calculation against the planned geometry.

## Turning a long build session into a readable article

The lesson above is mostly small decisions: a filter comparison, a debounce, an off-by-one. Those decisions are exactly what a written article can preserve, and what a recording loses to pacing and re-recording.

If you have a tutorial, an interview or an explanation sitting in a video, you can paste the YouTube link into Skala blog, let it transcribe the audio, and edit the result into an article. The [Skala Blog](https://skalablog.com) workflow starts from the video you already made.

[Source video](https://www.youtube.com/watch?v=eBkM0NUGj4g)
