Contour Documentation

Welcome to Contour!

Contour is a cloud-based platform for hosting, editing, and collaborating on geospatial data.

Contour Data Model - Opinionated, Managed PostGIS

At its core Contour is a "Feature Store" for geospatial data. The Feature model is based heavily on the GeoJSON spec, so Contour Features map closely to GeoJSON Features in many respects.

A Feature represents a single spatial entity, containing a Geometry and a set of JSON Properties. Each Feature is labeled with an auto-generated unique ID (UUID v4) and optionally with a user-provided string "key" which functions as a stable identifier within the context of its layer.

Features are organized into a hierarchy:

Internally, Contour uses PostGIS to store features, and to process them in order to run spatial queries or generate vector tiles. However Contour does not expose access to the underlying tables directly, so any edits or queries must be done through the provided APIs.

Edits and Updating

Features are created and updated through edits, which are grouped into changesets similarly to the OpenStreetMap Changeset Model. A single Edit represents a before and after snapshot of all of the changes between a previous Feature state and the current one. A changeset represents an associated group of Edits with an owner and a description which get committed atomically.

Changesets can be created via manual edits in the web editor, or via automated file uploads or other bot-like activities. They can be submitted for immediate merging by a collection owner, or buffered in a "pending" state to be reviewed and merged later. This asynchronous change + merge strategy allows for principled management of crowdsourced datasets -- you can mark a collection as "open for contributions" by volunteers, but still maintain control over reviewing and merging the edits they submit.

Creating a Collection

Sorry, your browser doesn't support embedded videos.

Start a new collection by using the link in the navbar, or navigating to

You'll be prompted for a name for your new collection, which must meet a few constraints:

You'll also need to choose a Privacy level:

Viewing a Collection

The main Collection pages at<username>/<collection name> provide an interface for viewing collection data on a map. It includes some basic features like:

Sorry, your browser doesn't support embedded videos.

Collection Settings

Some settings to customize your collection's behavior can be found via the "Settings" link in the collection page header.

Working with Layers

Using the Web Editor

Sorry, your browser doesn't support embedded videos.

Uploading Data

Upload Process

To ensure the integrity of uploaded data, there are a few validation steps involved in the process. First you will select and upload your files. Then the system will convert (if necessary) and validate your Features for issues like size, coordinate scheme, etc. Then, once features are validated, you can assign your upload to the desired Collection + Layer, at which point it will be converted into a new changeset for your review.

  1. Start at
  2. Select your files and upload -- files will be uploaded to cloud storage and Contour will begin processing them in the background.
  3. Files will be converted and validated.
  4. Review your converted files -- you'll be able to see some statistics like geometry and property counts.
  5. If everything looks good, select a target collection and layer from the dropdown.
  6. Your upload will be converted into a new changeset. Once this completes, you can review and merge the new pending changeset.
Sorry, your browser doesn't support embedded videos.

Upserting Features via Uploads

Sometimes when dealing with bulk data ingestion it can useful to re-upload existing rows. Contour supports "matching" GeoJSON Features on upload via 2 mechanisms:

  1. By the Feature's top-level "id". This should be the UUID v4 string assigned by Contour on the original upload.
  2. By the Feature's top-level "key" attribute. This can be an arbitrary string which should be unique within the context of your layer's data. Stable identifiers that correspond to external systems are a good fit for Feature keys, since they allow re-matching for subsequent automated updates.

For example uploading the following GeoJSON feature will first attempt to match to an existing feature with the UUID 67ee125d-e7f0-4170-a1b1-2033074888e5, and then to an existing feature with the key "external_1234". If one of these is found, the upload will update the existing feature rather than creating a new one. This edit will still appear in your changeset as normal, and will record the Feature's previous state in the changelog.

{ "type": "Feature", "properties": {}, // Match by UUID or by string Key "id": "67ee125d-e7f0-4170-a1b1-2033074888e5", "key": "external_1234", "geometry": { "type": "Point", "coordinates": [-119.53125, 33.75] } }

Vector Tile Rendering

Contour provides a Vector Tile endpoint for each hosted layer at the path /api/u/:owner/:collection/layers/:layer/mvt/:z/:x/:y.pbf. For example the 1/1/0 tile for the layer "default" in the collection "example" owned by the user "worace" would be hosted at Tiles are generated lazily and are cached into Google's Cloud CDN for better latency and delivery. New data edits will expire the cache, but the system will attempt to warm it for you in the background when this occurs.

Tiles are generated with PostGIS and are based on the Mapbox Vector Tiles v2 spec.