Every GIS tool on the web — ArcGIS, MapLibre, Deck.gl, Leaflet, Mapbox — speaks the same data language. It's called GeoJSON. Not because someone decided to standardize it, but because it's the simplest possible way to describe geographic shapes in a format JavaScript already understands.
If you've ever exported a layer from ArcGIS Online, queried a Feature Layer from code, or opened a shapefile as JSON, you've already been working with GeoJSON. Understanding what's inside it — and why it's structured the way it is — changes how you think about moving data between tools.
The Two Things Every Geographic Feature Has
Every feature on a map has two things: where it is and what it is.
Where it is means coordinates — latitude and longitude. What it is means attributes — a name, a status, a count, a category.
GeoJSON puts these in two fields on every feature: geometry (where) and properties (what). That's the entire data model.
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-81.66, 30.33]
},
"properties": {
"name": "Duval County Shelter",
"capacity": 800,
"status": "OPEN"
}
}
The Three Shapes
Every geographic feature is one of three shapes.
Point — a single location. A shelter. A hospital. A damage assessment address.
{
"type": "Point",
"coordinates": [-81.66, 30.33]
}
LineString — a connected path. A storm track. An evacuation route. A road segment.
{
"type": "LineString",
"coordinates": [
[-80.0, 23.5],
[-80.8, 25.5],
[-81.3, 29.2]
]
}
Each pair in the array is one point along the line. MapLibre draws a line connecting them in sequence. Add more points for a more precise path.
Polygon — a closed shape. A county boundary. A flood zone. A shelter catchment area.
{
"type": "Polygon",
"coordinates": [[
[-81.5, 30.0],
[-81.0, 30.0],
[-81.0, 30.5],
[-81.5, 30.5],
[-81.5, 30.0]
]]
}
The first and last coordinate must match to close the shape. The double brackets [[...]] are intentional — polygons can have holes (think: a county with a lake inside it), so the outer array holds the outer ring, and any additional arrays in that list define holes.
The Coordinate Trap
Coordinates in GeoJSON are always [longitude, latitude] — longitude first.
This is backwards from how most GIS professionals read coordinates. ESRI, Google Maps, and natural language all say "lat/lon." GeoJSON says lon/lat. Every major web GIS library follows the GeoJSON convention.
The mistake is easy and the failure mode is silent: your points render in the wrong place, often in the ocean, with no error message to tell you why.
A quick check: longitude for the continental United States is always a large negative number (roughly -67 to -125). If you see a positive number in the first position of a US coordinate, the values are reversed.
The FeatureCollection
In practice, you never send one feature at a time. You wrap them all in a FeatureCollection:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [-84.39, 33.75] },
"properties": { "name": "Atlanta Civic Center", "capacity": 800 }
},
{
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [-81.66, 30.33] },
"properties": { "name": "Duval County Shelter", "capacity": 600 }
}
]
}
A FeatureCollection is just an array of features with a wrapper that identifies the type. Every tool that reads GeoJSON expects this wrapper. When you call queryFeatures() on an ArcGIS Online Feature Layer, what comes back is a FeatureCollection. When you add a GeoJSON source to MapLibre, you hand it a FeatureCollection. When Deck.gl reads a data file, it's reading a FeatureCollection.
This is what makes GeoJSON the universal handshake between GIS tools. It doesn't matter which tool generated the data or which tool will render it — if it's a FeatureCollection, they can all work with it.
What This Means for Your AGOL Data
Your hosted Feature Layers in ArcGIS Online already speak GeoJSON. The moment you publish a layer, ESRI creates a REST endpoint that can return your data in GeoJSON format. No export required. No file download. Just a request to the right URL with &f=geojson appended, and your layer comes back as a standard FeatureCollection.
From code, queryFeatures() handles this for you:
const result = await featureLayer.queryFeatures({
where: "STATUS = 'OPEN'",
outFields: ['NAME', 'CAPACITY'],
returnGeometry: true
});
// result.features is your FeatureCollection
That result can go directly into MapLibre as a map source, directly into a Deck.gl layer as data, or into any other tool that reads GeoJSON. ESRI's rendering tools become one option among many, not the only path.
Why This Matters Beyond the Technical Details
GeoJSON matters because it's the format where the ESRI world and the open-source web mapping world meet. Understanding it fluently — the three shapes, the FeatureCollection wrapper, the coordinate order — means your AGOL data isn't trapped inside ESRI's toolset.
It also means that when you see a GeoJSON file from any source — a government open data portal, a GitHub repo, an API response — you know exactly what's in it and how to use it. The format is the same everywhere.