Architecture¶
nyc-geo-toolkit is a small data-first package. Its job is to ship canonical
NYC boundary assets and expose a stable top-level API for loading, normalizing,
converting, and subsetting them.
Design goals¶
- keep the public surface small and explicit
- ship packaged GeoJSON data with no runtime network dependency
- keep pandas, geopandas, and shapely behind optional extras
- support downstream NYC packages without embedding consumer-specific adapters in the toolkit
Runtime flow¶
flowchart LR
packagedData["Packaged boundary GeoJSON"] --> resources["load_boundary_payload()"]
resources --> parsing["boundary_collection_from_geojson()"]
parsing --> models["BoundaryCollection"]
models --> conversion["boundaries_to_geojson() / boundaries_to_dataframe()"]
models --> clipping["clip_boundaries_to_bbox()"]
models --> loading["load_nyc_boundaries()"]
loading --> geodataframe["load_nyc_boundaries_geodataframe()"]
The loaders always return typed BoundaryCollection objects first. Optional
helpers then project those typed models into GeoJSON, pandas, GeoPandas, or
clipped geometry outputs.
Public contract¶
The stable import surface is the top-level nyc_geo_toolkit namespace. The
package-level __all__ in src/nyc_geo_toolkit/__init__.py is the contract
that downstream packages should rely on.
Underscore-prefixed modules such as _loaders.py, _normalize.py, and
_resources.py keep the implementation organized, but they are not public
compatibility promises.
Ecosystem pattern¶
nyc311 is the first consumer of this package, and nyc-mesh and
subway-access follow the same pattern: depend on the shared toolkit surface,
then add project-specific helpers in the consumer repo.
flowchart TB
toolkit["nyc-geo-toolkit"] --> publicApi["Stable top-level API"]
toolkit --> contractTests["Consumer contract tests"]
publicApi --> nyc311["nyc311"]
publicApi --> nycMesh["nyc-mesh"]
publicApi --> subwayAccess["subway-access"]
contractTests -.-> nyc311
contractTests -.-> nycMesh
contractTests -.-> subwayAccess
That design keeps responsibilities clear:
nyc-geo-toolkitowns packaged boundary data, normalization rules, typed models, and the stable public contract- consumer packages own their own compatibility shims and domain-specific logic
- if a consumer needs a reusable primitive, promote that primitive into the toolkit and document it there instead of adding a consumer-specific adapter directory in the toolkit
Internal module map¶
For contributors, the internal layout is intentionally simple:
nyc_geo_toolkit.__init__for the stable public namespacenyc_geo_toolkit._catalogfor layer metadatanyc_geo_toolkit._modelsfor typed boundary modelsnyc_geo_toolkit._normalizefor layer and value normalizationnyc_geo_toolkit._resourcesfor packaged data accessnyc_geo_toolkit._geojsonfor parsing GeoJSON into typed modelsnyc_geo_toolkit._loadersfor boundary loading and optional GeoDataFrame helpersnyc_geo_toolkit._conversionsfor GeoJSON and DataFrame conversion helpersnyc_geo_toolkit._opsfor generic clipping operationsnyc_geo_toolkit._basemapfor optional contextily / Web Mercator map helpers