City 3D STAC
A command-line tool for generating STAC (SpatioTemporal Asset Catalog) metadata from CityJSON datasets.
Overview
STAC is the widely-adopted metadata standard for geospatial data, but it lacks native support for 3D city models. This tool bridges that gap by automatically generating STAC Items and Collections from various CityJSON and CityGML format files by traversing directories and extracting comprehensive metadata.
Supported Formats
- CityJSON (
.json) - Standard CityJSON files - CityJSONTextSequences (
.jsonl) - Line-delimited CityJSON features - CityGML (
.gml,.xml) - 3D City Models standard XML format (v2.0, v3.0) - FlatCityBuf (
.fcb) - Binary columnar format for CityJSON - CityParquet (
.parquet) - Planned future support
Features
- Generate STAC Items from individual files
- Generate STAC Collections by traversing directories
- Custom STAC extension for 3D city model metadata
- Support for multiple CityJSON formats and CityGML
- Extract rich metadata including:
- 3D bounding boxes
- Coordinate reference systems
- Levels of Detail (LOD)
- City object types and counts
- Semantic attribute schemas
- Coordinate transforms
Repository Scope
This repository contains the cityjson-stac CLI tool and its supporting Rust library code.
Public dataset registry content such as collection config instances, contribution guidelines, and publication workflows should live in a separate consumer repository. That consumer repository can vendor this tool as a git submodule and invoke the CLI from CI to validate and publish STAC catalogs.
See docs/external-registry.md for a recommended layout.
Installation
From source
The binary will be available at ./target/release/city3dstac.
With Cargo install
Quick Start
Generate STAC Item from a single file
With custom metadata:
Generate STAC Collection from a directory
The command will:
- Scan the directory for supported files (
.json,.jsonl,.fcb) - Generate a STAC Item for each file
- Aggregate metadata into a STAC Collection
- Create the output structure:
stac_catalog/ ├── collection.json └── items/ ├── building1_item.json ├── building2_item.json └── ...
CLI Reference
Global Options
| Option | Description |
|---|---|
-v, --verbose |
Enable verbose logging output |
-h, --help |
Print help information |
-V, --version |
Print version information |
Commands
item - Generate STAC Item from single file
Generate a STAC Item from a single CityJSON file.
Arguments:
| Argument | Description |
|---|---|
<FILE> |
Input file path |
Options:
| Option | Description |
|---|---|
-o, --output <PATH> |
Output file path (default: <input>.item.json) |
--id <ID> |
Custom STAC Item ID (default: file stem) |
--title <TITLE> |
Item title |
-d, --description <DESC> |
Item description |
-c, --collection <ID> |
Parent collection ID (adds collection link) |
--base-url <URL> |
Base URL for asset hrefs (makes them absolute URLs) |
--pretty |
Pretty-print JSON output (default: true) |
Examples:
# Basic usage (output: building.item.json)
# With custom output path
# With metadata
# With absolute URL for assets (useful for Object Storage)
collection - Generate STAC Collection from directory
Scan a directory for CityJSON files and generate a STAC Collection with Items.
Arguments:
| Argument | Description |
|---|---|
<DIRECTORY> |
Directory to scan |
Options:
| Option | Description |
|---|---|
-o, --output <PATH> |
Output directory (default: ./stac_output) |
-C, --config <FILE> |
Configuration file (YAML or TOML) |
--id <ID> |
Collection ID (default: directory name) |
--title <TITLE> |
Collection title |
-d, --description <DESC> |
Collection description |
-l, --license <LICENSE> |
Data license (default: proprietary) |
-r, --recursive |
Scan subdirectories recursively (default: true) |
--max-depth <N> |
Maximum directory depth |
--skip-errors |
Skip files with errors (default: true) |
--base-url <URL> |
Base URL for asset hrefs (makes them absolute URLs) |
--pretty |
Pretty-print JSON output (default: true) |
Output Structure:
stac_output/
├── collection.json
└── items/
├── building1_item.json
├── building2_item.json
└── ...
Examples:
# Basic usage
# With metadata and custom output
# With absolute URLs for assets
# Non-recursive with depth limit
# With verbose logging
catalog - Generate STAC Catalog from multiple directories
Generate a STAC Catalog by aggregating multiple directories (collections).
Arguments:
| Argument | Description |
|---|---|
<DIRS>... |
Input directories to include as collections |
Options:
| Option | Description |
|---|---|
-o, --output <PATH> |
Output directory (default: ./catalog) |
-C, --config <FILE> |
Configuration file (YAML or TOML) |
--id <ID> |
Catalog ID (default: output dir name) |
--title <TITLE> |
Catalog title |
-d, --description <DESC> |
Catalog description |
-l, --license <LICENSE> |
License for sub-collections (default: proprietary) |
--base-url <URL> |
Base URL for catalog child links |
--pretty |
Pretty-print JSON output (default: true) |
Examples:
# Basic usage
# With metadata
# Using a configuration file (YAML or TOML)
update-collection / aggregate - Generate STAC Collection from existing items
Generate a STAC Collection by aggregating metadata from existing STAC Item files. This is useful for Object Storage workflows where STAC Items are generated individually and then need to be combined into a collection.
Arguments:
| Argument | Description |
|---|---|
<ITEMS>... |
STAC Item JSON files to aggregate |
Options:
| Option | Description |
|---|---|
-o, --output <PATH> |
Output file path (default: ./collection.json) |
--id <ID> |
Collection ID (default: output file stem) |
--title <TITLE> |
Collection title |
-d, --description <DESC> |
Collection description |
-l, --license <LICENSE> |
Data license (default: proprietary) |
--items-base-url <URL> |
Base URL for item links (makes them absolute URLs) |
--skip-errors |
Skip items with parsing errors (default: true) |
--pretty |
Pretty-print JSON output (default: true) |
Aggregated Metadata:
The command aggregates the following 3D City Models extension properties from all items:
| Property | Aggregation Method |
|---|---|
city3d:version |
Unique list of all versions |
city3d:lods |
Merged, sorted list of all LODs |
city3d:co_types |
Merged, sorted list of all object types |
city3d:city_objects |
Statistics: min, max, total |
city3d:semantic_surfaces |
Array of unique observed values |
city3d:textures |
Array of unique observed values |
city3d:materials |
Array of unique observed values |
proj:code |
Unique list of all projection codes |
bbox (spatial) |
Merged bounding box of all items |
Examples:
# Aggregate items with relative links
# Using glob pattern
# Using the alias
# With collection metadata
# With absolute URLs for item links (useful for Object Storage)
Object Storage Workflow Example:
# Step 1: Generate STAC Items individually (can be parallelized)
# Step 2: Aggregate all items into a collection
Filename Collision Handling
When processing a collection with files that have the same stem but different extensions (e.g., delft.city.json and delft.city.jsonl), item IDs and filenames get format-specific suffixes:
| Format | Suffix | Example |
|---|---|---|
CityJSON (.json) |
_cj |
delft.city_cj |
CityJSONSeq (.jsonl) |
_cjseq |
delft.city_cjseq |
FlatCityBuf (.fcb) |
_fcb |
delft.city_fcb |
Documentation
- AGENTS.md / CLAUDE.md - Project overview and coding guidelines for AI agents
- DESIGN_DOC.md - Detailed technical architecture and implementation
- STAC_EXTENSION.md - CityJSON STAC extension specification
- Detailed JSON schema of the STAC extension can be found in
stac-cityjson-extension/json-schema/schema.json.
- Detailed JSON schema of the STAC extension can be found in
Project Status
✅ Core Implementation Complete - The tool is functional with:
- CityJSON format support (
.jsonfiles) - CityJSON Sequences support (
.jsonlfiles) - CityGML support (
.gml,.xmlfiles) - FlatCityBuf support (
.fcbfiles) - STAC Item and Collection generation
- Full CLI with
item,collection,catalog, andupdate-collectioncommands - TOML and YAML configuration support
- 135+ unit and integration tests passing
- Custom CityJSON STAC extension
Contributing
Contributions are welcome! Please see the design documents for implementation details and architectural decisions.
License
This project is licensed under the MIT License - see the LICENSE file for details.