Map Markers
Place points, draw lines, and define polygons on the shared map with real-time sync.
10 min readMarker Types
GroundWave supports three geometry types for map markers. All types are stored in
PostgreSQL using PostGIS GEOGRAPHY columns with SRID 4326, which enables
accurate distance and area calculations in meters without coordinate system conversion.
Point Markers
Single coordinate markers with name, category, description, and optional photo attachments. Ideal for rally points, hazards, medical stations, water sources, shelters, and any discrete location of interest.
Line Markers
Multi-vertex polylines with label and color for routes of march, patrol paths, cordons, phase lines, and linear features.
Polygon Markers
Closed polygon areas with label, color, and fill for objective areas, engagement zones, exclusion zones, grid squares, and any bounded region requiring area representation.
All marker geometry is validated against the GeoJSON specification on the server before being written to the database. Invalid geometry -- self-intersecting polygons, unclosed rings, or out-of-range coordinates -- is rejected with a descriptive error response.
Categories
Point markers belong to one of the predefined categories. Categories drive the visual appearance of markers on the map and give operators an immediate, at-a-glance understanding of what a marker represents without reading its label.
| Category | Intended Use | Default Color |
|---|---|---|
rally_point |
Assembly areas, rendezvous locations | Blue |
water_source |
Rivers, wells, resupply points | Cyan |
hazard |
Obstacles, danger zones, known threats | Red |
shelter |
Structures, safe houses, bivouac sites | Green |
medical |
Aid stations, casualty collection points | Amber |
Additional context beyond the category belongs in the description field. Use it for grid references, access notes, capacity, or any other free-form operational detail.
Creating Markers
Markers can be created through two paths: the interactive map drawing tool in the client UI, or directly via the REST API or Socket.IO for programmatic or external integrations.
Interactive Drawing Tool
The client implements a custom MapLibre drawing state machine that manages the full lifecycle of geometry construction without depending on a third-party drawing library. The interaction model is:
- Point -- select the Point tool, then click anywhere on the map. A create form opens to set name, category, and description. Submitting creates the marker immediately.
- Line -- select the Line tool, click to place the first vertex, click again to add subsequent vertices, and double-click to finish and submit the line.
- Polygon -- select the Polygon tool, click to place vertices around the area, and double-click to close the ring and submit the polygon.
During drawing, a live preview renders the in-progress geometry on the map so operators can see the shape forming before they commit it. The Escape key cancels an in-progress drawing without creating a marker.
API Creation
Markers can also be created directly via REST:
geometry field must be a valid GeoJSON geometry object (Point, LineString, or Polygon). Point markers require name and category.// POST /api/markers -- point marker example
{
"marker_type": "point",
"name": "Alpha Rally Point",
"category": "rally_point",
"description": "Grid 4QFJ 123 456 -- clear LZ to the north",
"geometry": {
"type": "Point",
"coordinates": [-118.243, 34.052]
}
}
// POST /api/markers -- polygon marker example
{
"marker_type": "polygon",
"name": "Objective Alpha",
"marker_properties": {
"color": "#ef4444",
"opacity": 0.35,
"lineWidth": 2
},
"geometry": {
"type": "Polygon",
"coordinates": [[[-118.25, 34.05], [-118.24, 34.05],
[-118.24, 34.06], [-118.25, 34.06],
[-118.25, 34.05]]]
}
}
Markers can also be submitted via Socket.IO for lower-latency creation:
// Socket.IO event: marker:create (client -> server)
{
"marker_type": "point",
"name": "RP Delta",
"category": "rally_point",
"geometry": {
"type": "Point",
"coordinates": [-118.243, 34.052]
}
}
Real-Time Sync
All marker CRUD operations are broadcast to every connected client via Socket.IO immediately after the database write completes. Changes appear on all maps simultaneously without any polling or manual refresh.
| Event | Direction | Payload |
|---|---|---|
marker:created |
Server → All | Full marker object including geometry, properties, generated id, and created_at |
marker:updated |
Server → All | Full updated marker object |
marker:deleted |
Server → All | { id } -- clients remove the feature from their map source |
Markers are included in the offline IndexedDB cache. When the client reconnects after a connectivity gap, the cache is refreshed from the server and any queued marker operations are replayed in order.
Styling
MapLibre renders markers using a data-driven style stack that provides visual differentiation across marker types and states:
- Polygon fill -- semi-transparent filled area using the marker's
colorandopacityproperties. - Polygon outline -- solid border using the marker's
colorandlineWidthproperties. - Line stroke -- rendered for LineString geometry using
colorandlineWidth. - Point circle -- rendered for Point geometry as a circle whose color is determined by the marker's
category. - Label -- the marker
namerendered as a text symbol above the feature centroid.
Color, opacity, and line width are stored in the marker's marker_properties
JSON column and applied at render time. Users can adjust these values through the marker
edit panel in the slide-out UI. Changes persist to the database and broadcast to all clients
via marker:updated.
Photo Attachments
Point markers support photo attachments through the existing file upload system. Any image file
uploaded to POST /api/files can be associated with a marker by including the
marker's identifier in the upload metadata.
Photos are displayed in the marker detail view within the slide-out panel. Clicking a thumbnail opens the full-resolution image using an authenticated download URL. Multiple photos per marker are supported; they are displayed in a scrollable gallery ordered by upload timestamp.
Photo uploads follow the same MIME allowlist and size limits as the File Sharing system. Only authenticated operators and admins can attach photos; observers can view them.
Filtering
The GET /api/markers endpoint supports multiple independent filtering
mechanisms that can be combined in a single request.
marker_type, category, bbox=west,south,east,north, lat + lng + radius
Type Filter
Filter markers by geometry type to retrieve only points, lines, or polygons:
GET /api/markers?marker_type=point
Category Filter
Pass a comma-separated list of categories to restrict results to specific point marker types:
GET /api/markers?category=hazard,medical
Bounding Box Filter
Pass a bbox query parameter as four comma-separated decimal values in
minLon,minLat,maxLon,maxLat order (GeoJSON convention):
GET /api/markers?bbox=-118.5,33.9,-118.1,34.2
The server translates the bbox into a PostGIS ST_MakeEnvelope call and
filters using the spatial index on the geometry column, making
this query efficient even with large datasets.
Radius Filter
Supply a center point and a radius in meters to fetch all markers within a given distance:
GET /api/markers?lat=34.052&lng=-118.243&radius=5000
Internally this executes a PostGIS ST_DWithin call against the
GEOGRAPHY column. Because the column type is GEOGRAPHY
rather than GEOMETRY, the radius unit is always meters regardless of the
underlying coordinate system.
Category Visibility Filtering
The marker panel includes a visibility toggle row for each category. Toggling a category off applies a MapLibre filter expression that hides all markers of that type without removing them from the data source. This is a client-side display preference and does not affect what other users see.
Permissions
Marker access follows GroundWave's role-based access control model. Permission levels are enforced on both the REST API and Socket.IO event handlers.
| Action | Observer | Operator | Admin |
|---|---|---|---|
| View markers | ✓ | ✓ | ✓ |
| Create markers | — | ✓ | ✓ |
| Edit own markers | — | ✓ | ✓ |
| Delete own markers | — | ✓ | ✓ |
| Edit any marker | — | — | ✓ |
| Delete any marker | — | — | ✓ |
Observers can view all markers on the map and in the marker panel but cannot create, modify, or delete any marker. This is appropriate for personnel who need situational awareness without permission to alter the shared map picture.
When authentication is disabled (AUTH_REQUIRED=false), all connected
users have full create, edit, and delete access to markers regardless of role.
Enable authentication for any deployment requiring access control.
Markers can be exported as a GeoJSON FeatureCollection from the admin Data
Export tab and re-imported via POST /api/import/markers, enabling
faithful round-trip transfer of marker data between GroundWave deployments.