geojson-postgis

SKILL.md

PostGIS Geometry Rows → GeoJSON FeatureCollection

Use this skill when your data already has a PostGIS geometry column (typically geom) and you need to serve it to a web map as GeoJSON.

This is the canonical pattern:

  • output WGS84 (EPSG:4326) for clients
  • return a FeatureCollection
  • keep properties as “all columns minus geom” (or explicitly selected fields)

When to use

  • You have a table with geom (geometry) and other columns
  • You are building or updating an API endpoint that returns map layers
  • You want consistent GeoJSON structure and coordinate system

Core rules

  • Serve geometry in EPSG:4326 for web clients
  • GeoJSON output should be a FeatureCollection
  • Properties should not include raw geom (remove it or select explicitly)

Canonical SQL pattern (FeatureCollection)

SELECT jsonb_build_object(
  'type', 'FeatureCollection',
  'features', COALESCE(jsonb_agg(
    jsonb_build_object(
      'type', 'Feature',
      'geometry', ST_AsGeoJSON(ST_Transform(t.geom, 4326))::jsonb,
      'properties', (to_jsonb(t) - 'geom')
    )
  ), '[]'::jsonb)
) AS geojson
FROM my_table t
WHERE t.geom IS NOT NULL;

Notes

  • COALESCE(..., '[]') ensures empty results return "features": [] (not null)
  • ST_Transform(..., 4326) ensures map-safe coordinates
  • to_jsonb(t) - 'geom' keeps properties clean

Selecting only certain properties (recommended for payload size)

If a table has many columns, explicitly build properties:

SELECT jsonb_build_object(
  'type', 'FeatureCollection',
  'features', COALESCE(jsonb_agg(
    jsonb_build_object(
      'type', 'Feature',
      'geometry', ST_AsGeoJSON(ST_Transform(t.geom, 4326))::jsonb,
      'properties', jsonb_build_object(
        'id', t.id,
        'name', t.name,
        'status', t.status
      )
    )
  ), '[]'::jsonb)
) AS geojson
FROM my_table t
WHERE t.geom IS NOT NULL;

Returning one feature by id

Use this pattern for a single geometry row:

SELECT jsonb_build_object(
  'type', 'Feature',
  'geometry', ST_AsGeoJSON(ST_Transform(t.geom, 4326))::jsonb,
  'properties', (to_jsonb(t) - 'geom')
) AS feature
FROM my_table t
WHERE t.id = $1
  AND t.geom IS NOT NULL;

Guardrails for map endpoints

  • Always require filtering (bbox, ids, or a sensible limit) for large tables
  • Consider enforcing a maximum feature count
  • Prefer explicit properties for large payloads
  • If you frequently serve this layer, consider simplifying geometry upstream (separate skill)

Common mistakes

  • Serving geometry in a projected SRID (client renders nonsense)
  • Returning raw geom in properties
  • Forgetting COALESCE and returning "features": null
  • Returning too many features (browser crash / huge payload)
Weekly Installs
12
GitHub Stars
1
First Seen
Feb 9, 2026
Installed on
codex11
gemini-cli10
github-copilot10
amp10
kimi-cli10
opencode10