Site
Surveyor
Open Surveyor /site-analysis
Turns a point on the map into a measured site (terrain, water, climate, soils, hazards, surroundings) from public US datasets, with a Rhino-ready export kit and optional AI readings.
At a glance
- What it is: A GIS desk study with two entry modes (any Place, or an EPA Superfund site) and a study-area span from 1,000 ft to 5 mi. One keyless request fires eleven parallel fetches against public datasets. Your browser then computes slope, aspect, contours, direct-sun hours and D8 drainage from a USGS 3DEP elevation grid, whose spacing depends on the span. Up to five AI passes, all optional and requiring sign-in, write sourced background, a contamination brief and a design synthesis.
- Professional equivalent: ArcGIS Pro (Spatial Analyst, Hydrology) or QGIS with GDAL, GRASS or WhiteboxTools for the terrain. Ladybug, Climate Consultant and ASHRAE design data for the climate. A consultant's pre-design site report, which bundles a boundary/topographic survey, a FEMA FIRMette or elevation certificate, geotechnical borings, a wetland delineation and an ASTM E1527 Phase I ESA. For the AI passes: a human researcher.
- Fidelity: Same engine · Screening estimate · Standard method · Classroom proxy · · AI reading, by layer (see the table):
- Same engine: the federal datasets, terrain, contours, drainage, and spans of 1 mi or less.
- Screening estimate: sun hours, the climate year, wind, the .epw, OSM surroundings, and spans of 2 mi or more.
- Standard method: façade solar (isotropic sky).
- Classroom proxy: groundwater read as a site water table, and the Givoni strategy mix.
- : traced parcel, section cut, maps and exports.
- AI reading: every model pass.
- Trust it for: Which way the land falls and drains. Which slopes are buildable. Relative sun and shade. The shape of the climate year. Which federal datasets flag a problem (SFHA flood zone, hydric soil, NWI wetland, NPL listing, high Seismic Design Category). Registered terrain and context for starting a Rhino model.
- Don't use it for: Grading or finished-floor elevations, legal boundaries, foundation or stormwater design, flood-insurance determinations, seismic design values for permit, or any statement that a site is "clean". All of these need a stamped survey, a geotechnical report, an engineer's hydrology or a Phase I ESA.
- Switch to the pro tool when: A number will be built to, permitted against or priced. At schematic design a surveyor's topo, borings and a Phase I replace this read.
- Which option to use: Use Place for any address or dropped pin. Use Superfund when the question is about a listed NPL site: it adds the EPA record, the boundary and the contamination brief. Keep the span at 1 mi or less for anything at building or parcel scale (26 ft grid). Use 2–5 mi only for landform and watershed context, and read the per-layer notes, because the point layers (soils, flood zone, seismic, wetland) describe one point whatever the span.
In detail
The options at a glance
| Option | What it adds / changes | Fidelity | Closest pro tool | Biggest gap |
|---|---|---|---|---|
| Mode · Place | Geocoded search, a pin, or your location; surveys that exact point | Same engine (per layer) | GIS desk study in ArcGIS Pro / QGIS | No contamination screen at all (NPL dots only, on request) |
| Mode · Superfund | EPA NPL record, EPA boundary polygon, a studio anchor point, and the contamination brief | Same engine record + AI reading brief | ASTM E1527-21 Phase I ESA with a database report; EPA SEMS / ROD | NPL only; the brief is a model reading, not a records review |
| Span 1,000 ft – 1 mi | Terrain grid 39–202 posts a side, ~26 ft (8 m) spacing | Same engine | 3DEP 1 m DEM in ArcGIS; surveyed topo | Still ~8× coarser than 1 m lidar; features under ~53 ft vanish |
| Span 2 mi | Grid capped at 240 posts, ~44 ft (13.5 m) | Screening estimate | Same | Features under ~88 ft vanish; slopes flatten |
| Span 3 mi | ~66 ft (20.2 m); OSM context only in central 2.8 mi | Screening estimate | Same | Outer ring has no buildings for sun hours or sections |
| Span 5 mi | ~110 ft (33.7 m); OSM context partial | Screening estimate | Same | Coarser than 3DEP's 33 ft floor; not a site read |
| Terrain grid (3DEP) | One exportImage GeoTIFF, bilinear, gaps flagged | Same engine | Boundary/topo survey; 3DEP 1 m DEM | Resampled to the span grid; no breaklines |
| Slope & aspect | Zevenbergen–Thorne 4-neighbour slope, 4 bands, buildable <15% | Same engine | ArcGIS Slope (Horn) on 1 m DEM; Civil 3D slope analysis | Grid spacing flattens peaks; not Horn |
| Contours & hillshade | Map: terrarium tiles; export: marching squares on the survey grid | Same engine | Civil 3D surface contours from a TIN | Map and export come from different DEMs |
| Drainage & flow | Priority-Flood fill + D8 + accumulation, thalwegs, outlet | Same engine | ArcGIS Hydrology, WhiteboxTools, StreamStats, HEC-HMS/SWMM | Terrain-only; truncates upstream area at the box edge |
| Sun hours | Ray-marched direct sun over terrain + OSM buildings, 3 days | Screening estimate | Ladybug Direct Sun Hours, ArcGIS Area Solar Radiation | Direct beam only; grid-resolution buildings; guessed heights |
| Climate year | 2023 hourly reanalysis; degree-days, design percentiles, adaptive comfort, Givoni | Screening estimate (Givoni Classroom proxy) | ASHRAE design conditions; TMYx; Climate Consultant | One modelled year, a 6–15 mi model cell, not a station |
| Wind | 16-sector rose, seasonal prevailing wind at 33 ft (10 m) | Screening estimate | Airport ASOS rose; CFD (Eddy3D, Butterfly) | No terrain/building channelling |
| Façade solar & sun path | NOAA solar position; isotropic-sky façade kWh/m²·yr | Standard method | Ladybug incident radiation (Perez sky), EnergyPlus | Isotropic sky; no obstructions |
| .epw export | 8,760-row EPW from the same year | Screening estimate | TMYx / NSRDB TMY | Modelled, one year, many fields missing |
| Flood (FEMA NFHL) | Zone at the point; zone polygons + BFE lines in the box | Same engine | FIRMette; elevation certificate; LOMA | Point zone only; no structure elevations |
| Soils (SSURGO) | Dominant-condition muaggatt at the point | Same engine | Web Soil Survey; geotechnical borings | One map unit at one point |
| Bedrock geology | Macrostrat mapped unit at the point + tiles | Same engine | State geological survey maps; borings | Map unit, no depth to rock |
| Groundwater | Nearest NWIS well reading within ~10 mi | Classroom proxy | Piezometers; boring logs | Not this site's water table |
| Wetlands (NWI) | NWI polygon at the point + overlay | Same engine | Wetland delineation; USACE jurisdictional determination | NWI is not jurisdictional |
| Land cover (NLCD) | 2021 class, % impervious, % canopy at the point + overlays | Same engine | Tree survey; high-res land cover | 98 ft (30 m) cells, one pixel read |
| Watershed & water | WBD HUC12/HUC8 + boundary; NHD and OSM water overlays | Same engine | StreamStats delineation to the site outlet | HUC is miles wide, not the site catchment |
| Seismic | USGS ASCE 7-16 values at Site Class D, Risk Cat. II | Same engine (7-16) | USGS/ASCE hazard tool with ASCE 7-22 + measured site class | Superseded edition; assumed site class |
| EPA NPL record & boundary | EPA FeatureServer record, documents, merged boundary | Same engine | EPA SEMS; Phase I database report | Administrative footprint; holes drawn filled |
| OSM surroundings | Buildings, roads, water, green, clipped to the box (≤2.8 mi) | Screening estimate | City planimetric GIS; surveyed topo; lidar building heights | Completeness varies; heights guessed |
| Traced parcel | Hand-drawn boundary, acreage, terrain stats clipped to it | County parcel GIS; ALTA/NSPS survey | Not a legal line | |
| Section cut | 400-sample profile + OSM buildings/water, SVG/DXF | Civil 3D section view on a surveyed surface | Inherits grid spacing and OSM heights | |
| AI reading passes | Sources, chat, contamination, synthesis, blind-vs-grounded | AI reading | A human researcher / Phase I reviewer | Tags are model self-reports; probing is uneven |
Mode · Place
Survey any point: a geocoded search, a map click or the browser's location.
- What it adds: The point you pick becomes the centre of the study box and the point every point layer reads. Search uses OpenStreetMap Nominatim (8 results). A map click reverse-geocodes the pin and falls back to a coordinate label. No EPA record, boundary or contamination pass runs. You can trace your own boundary (see Traced parcel) and switch on "show all Superfund sites" dots for the current view.
- Method: The payload is
{lat, lon, label, category, spanM}. The server buildsbboxForSpan, a box square on the ground (the longitude half-width is scaled by 1/cos lat), then fires the eleven fetches in parallel. The AI synthesis in this mode is told that no contamination data was gathered and that a Phase I ESA or records check would be needed. - Fidelity: Same engine. The mode adds no computation of its own; every number comes from the per-layer engines below.
- Professional equivalent: A GIS desk study in ArcGIS Pro or QGIS, the first chapter of a site-analysis report.
- Trust it for / don't use it for: Trust it for a fast, registered first read of any US point. Don't use it to conclude a site has no contamination history. Place mode never looks.
- The gap:
- No environmental records search. A Phase I database report searches NPL, RCRA, brownfields, UST/LUST and state lists at ASTM search distances (NPL: 1 mi). Place mode searches nothing unless you switch on the NPL dots, and those show NPL only.
- A geocoder hit is a point, often a road centroid or a building entrance. All point layers read there, not over your parcel.
- Code:
src/app/(app)/site-analysis/site-analysis-tool.tsx(selectCandidate, pickPoint),src/app/api/site-analysis/analyze/route.ts,src/lib/site-analysis/datasources.ts(geocodeSearch, bboxForSpan)
Mode · Superfund
Survey a listed NPL site by EPA ID, with its record, boundary and an AI contamination brief.
- What it adds:
- The record. Search by name, city, county or state against EPA's NPL FeatureServer, or click an orange dot. The server re-fetches the site record by EPA ID: status, dates, and links to the listing narrative, progress profile and Federal Register notices.
- The boundary. It pulls the EPA boundary layer and merges all operable units into one MultiPolygon. Acreage comes from
GIS_AREAonly when its unit is areal. Boundaries over 15,000 vertices are decimated. - The anchor. The five studio sites send a hand-vetted anchor coordinate. It is accepted only inside the boundary bbox padded
0.02° (1.2 mi), or within ~9 mi of the EPA point. The anchor replaces EPA's administrative reference point as the survey centre. - The brief. The AI adds a contamination brief before the synthesis.
- Method: The study box is still
bboxForSpanaround the centroid. The span wins over the boundary, so a site the size of Tar Creek (about 40 sq mi, per EPA) is surveyed only inside the span you pick, while the whole (decimated) boundary is drawn. Point layers read at the anchor or EPA point. If the EPA service fails for a studio site, the page falls back to a coordinate survey and says so. - Fidelity: Same engine for the record and boundary (EPA's own layers). AI reading for the contamination brief (see AI passes).
- Professional equivalent: An ASTM E1527-21 Phase I ESA. That means a commercial database report (EDR/ERIS), a site reconnaissance, interviews, and historical sources (Sanborn maps, aerials, city directories). Then a Phase II with sampling. For a listed site: EPA SEMS documents, the Record of Decision and five-year reviews.
- Trust it for / don't use it for: Trust it to locate the site, read EPA's own status, open the source documents and frame questions. Don't use it for contaminant lists, plume extents or institutional controls without checking the ROD and the deed.
- The gap:
- The EPA boundary is an administrative footprint. Every ring is drawn as its own polygon, so interior holes draw filled.
- The five studio sites ship a prebaked AI reading. It was written in advance, during the site's build, not live by the route: the live route's web search and link probe did not produce it, and its cited links were not probed.
- Only NPL sites. Non-NPL contaminated ground (brownfields, RCRA, state sites) is invisible here.
- Code:
src/lib/site-analysis/datasources.ts(getSite, getBoundary, mergeBoundaryFeatures),src/lib/site-analysis/boundary.ts,src/lib/site-analysis/superfund-search.ts,src/app/(app)/site-analysis/studio-sites-data.ts,src/app/(app)/site-analysis/studio-ai-cache.ts
Span · 1,000 ft, ¼ mi, ½ mi, 1 mi
The building- and parcel-scale spans: the terrain grid holds its ~26 ft target.
What it adds: The span sets the terrain box and everything downstream: slope, contours, drainage, sun hours, flood vectors, the OSM clip and every Rhino export. Grid size is n = round(span ÷ 8 m) + 1, clamped to 32–240.
Span Box area Grid (n × n) Spacing Smallest feature (~2 cells) Channel starts at (1% of grid) 1,000 ft (305 m) 23 acres 39 × 39 26.3 ft (8.0 m) ~53 ft ~0.24 acre ¼ mi (402 m) 40 acres 51 × 51 26.4 ft (8.0 m) ~53 ft ~0.42 acre ½ mi (805 m) 160 acres 102 × 102 26.1 ft (8.0 m) ~52 ft ~1.6 acres 1 mi (1,609 m) 640 acres 202 × 202 26.3 ft (8.0 m) ~53 ft ~6.5 acres Method: 3DEP exportImage, bilinear, is resampled to n × n. Spacing stays at ~26 ft up to ~1.19 mi (1,912 m), where n reaches the 240 cap.
Fidelity: Same engine. It is the same 3DEP mosaic a GIS analyst would download, at 8 m posts.
Professional equivalent: The 3DEP 1 m DEM used at native resolution in ArcGIS or QGIS; for design, a topographic survey (typically 1 ft contours with spot elevations and breaklines).
Trust it for / don't use it for: Trust it for landform, general slope classes and drainage direction on a parcel. Don't use it for curb, swale, retaining-wall or pad-level decisions.
The gap:
- Where 1 m lidar exists, 8 m posts throw away ~98% of the samples. Anything under ~53 ft disappears, and bilinear resampling rounds off breaks in slope.
- The drainage channel threshold scales with the box. A 1,000 ft box draws channels from ~0.24 acre; a 1 mi box needs ~6.5 acres. The "same" swale can appear at one span and vanish at another.
Code:
src/lib/site-analysis/datasources.ts(rasterSizeFor, bboxForSpan, elevationRaster),src/app/(app)/site-analysis/site-analysis-tool.tsx(STUDY_SPANS, StudyAreaBand)
Span · 2 mi (the page default)
The studio's default: landform and neighbourhood context, at coarser ground.
- What it adds: A 4 sq mi box. The 240-post cap is hit, so spacing grows to 44.2 ft (13.5 m). The picker marks it ⚠ and says so ("coarser ground and stretched drape images, not a bigger file"). The terrain card prints the actual n and cell size.
- Method: As above; n = 240. Channels need ~26 acres of upstream area. Features under ~88 ft vanish.
- Fidelity: Screening estimate. Same data and method, but at a resolution where derived slope and drainage are for comparing, not for sizing.
- Professional equivalent: The 1 m or 10 m DEM at native resolution; a USGS topo quad for context.
- Trust it for / don't use it for: Trust it for which way the neighbourhood drains, where ridges and valleys are, and context massing. Don't use it for the slope of a building pad or the buildable percentage of a parcel.
- The gap:
- Mean and maximum slope bias low as spacing grows. The steepest cells are averaged with flatter neighbours.
- Sun-hours rays and section cuts run at 44 ft steps.
- The default (
DEFAULT_SPAN_M) sits above the 1 mi span the tool recommends for building- or parcel-scale work.
- Code: as above
Span · 3 mi
Regional landform; buildings only in the middle.
- What it adds: A 9 sq mi box at 66.3 ft (20.2 m) spacing. Channels need ~58 acres. Features under ~133 ft vanish. OpenStreetMap surroundings are capped at 2.8 mi (4.5 km), so only the central sub-box gets buildings and roads, flagged "partial".
- Fidelity: Screening estimate.
- Professional equivalent: Watershed-scale GIS; USGS StreamStats for catchment questions.
- Trust it for / don't use it for: Trust it for landform and major drainage. Don't use sun hours or sections in the outer band: no buildings means no building shadows there.
- The gap: Sun hours over-light the outer band. The Rhino kit's context stops short of the terrain edge.
- Code:
src/lib/site-analysis/layers.ts(overpassSafeBox), plus the above
Span · 5 mi
The widest box: context only.
- What it adds: A 25 sq mi box at 110.5 ft (33.7 m) spacing, coarser than 3DEP's own 1/3 arc-second (~33 ft / 10 m) floor. Channels need ~161 acres. Features under ~221 ft vanish. OSM is partial, as at 3 mi.
- Fidelity: Screening estimate, bordering Classroom proxy for any building-scale reading. At this spacing the "site" read stops meaning anything at building scale.
- Professional equivalent: A regional GIS basemap or a USGS quad.
- Trust it for / don't use it for: Trust it for orientation and the big landform. Don't use it for slope, buildable area, sun hours or site drainage.
- The gap: Every terrain-derived value is smoothed. The drape images are stretched. The point layers still describe a single point in a 25 sq mi box.
- Code: as above
Terrain grid (USGS 3DEP)
The measured ground everything else is computed on.
- What it adds: One n × n elevation raster over the study box, in metres (displayed in feet).
- Method:
elevationRasterrequests one F32 GeoTIFF from the 3DEP ImageServerexportImage, with bilinear resampling andadjustAspectRatio=falseso pixels stay on the requested bbox. The source mosaic is best-available 3DEP: 1 m lidar where flown, 1/3 arc-second (~33 ft / 10 m) elsewhere.topoFromRasterrejects values outside −1,640 to 29,500 ft (−500 to 9,000 m) and NoData, and rounds to the centimetre. Gaps are back-filled with the grid mean and recorded inmissingMask. If the raster fails, a 12 × 12getSamplesgrid is the fallback. At 2 mi that is ~960 ft (293 m) spacing; the terrain card prints the real n, so it is visible. - Fidelity: Same engine. It is the same USGS mosaic, resampled.
- Professional equivalent: A licensed topographic survey, or an ALTA/NSPS survey with topography. For GIS: the 3DEP 1 m DEM or point cloud processed in ArcGIS Pro or Civil 3D.
- Trust it for / don't use it for: Trust it for bare-earth landform at the span's spacing. Don't use it for spot elevations, finished-floor datums or earthwork quantities (Grade inherits the same grid).
- The gap:
- Resampling to the span grid, with no breaklines, curbs or walls.
- A mixed-vintage mosaic: the lidar collection year varies by county and is not reported.
- Vertical accuracy is USGS's, not a surveyor's.
- Mean back-fill at coverage edges (coast, border) is flagged, and the drainage routing runs over those cells (see Drainage).
- Code:
src/lib/site-analysis/datasources.ts(elevationRaster, topoFromRaster, finishTopo, elevationTopo)
Slope & aspect
Which ground is buildable and which way it faces.
- What it adds: Mean and maximum slope, four slope bands, buildable percentage, an 8-bin aspect distribution with the dominant facing, high and low points, and a suggested grading datum (the low point). The map drapes classed slope and aspect.
- Method: Per interior cell, dz/dx = (z[c+1] − z[c−1]) / 2Δx and dz/dy likewise; slope = √(gx² + gy²) × 100%. This 4-neighbour second-order difference is the Zevenbergen–Thorne slope (GDAL's
-alg ZevenbergenThorne), not Horn's weighted 3 × 3.- Slope bands: <5, 5–10, 10–20 and >20%. Buildable means under 15%.
- Aspect = atan2(−gx, −gy), ignored under 1% slope.
- Cells touching a fabricated cell are skipped in the card statistics.
- The map drape instead clamps at the edges and colours every cell, leaving only fabricated cells transparent.
- Fidelity: Same engine. It is a standard GIS slope algorithm, one GDAL ships, on the survey grid.
- Professional equivalent: ArcGIS Pro Slope/Aspect (Horn by default) on a 1 m DEM; Civil 3D surface slope-band analysis on a surveyed TIN.
- Trust it for / don't use it for: Trust it for slope classes and aspect at landform scale. Don't use it for accessible-route grades, retaining-wall locations or a precise buildable percentage.
- The gap:
- Grid spacing dominates the error. At 26 ft, a 10 ft bank reads as a moderate slope. At 110 ft it may vanish.
- Maximum slope is understated, increasingly with span.
- Zevenbergen–Thorne is somewhat noisier than Horn on rough ground. At these spacings that difference is small next to resolution.
- The 15% buildable cutoff is a rule of thumb, not a zoning or code limit.
- Code:
src/lib/site-analysis/terrain.ts,src/lib/site-analysis/ground-core.ts(slopeAspectGrid, SLOPE_CLASSES)
Contours & hillshade
Linework and relief shading: one source for the map, another for the exports.
- What it adds: Map contours in feet at USGS quad intervals by zoom, plus hillshade and 3-D terrain. Exported contour curves at true elevation (.dxf, .3dm) and a hillshade drape.
- Method:
- Map.
maplibre-contourcuts isolines in a worker from AWS terrarium DEM tiles (3DEP-derived, max zoom 15), converted to feet first, at intervals of 5–200 ft by zoom. - Export.
contourLines3Druns masked marching squares on the surveyed grid at round-foot levels. The default interval is a "nice" step giving about ten contours over the relief. Segments are chained on a 0.4 in (1 cm) key, and cells touching fabricated samples are skipped. - Hillshade drape. 315° azimuth, 45° altitude, using the same 4-neighbour (Zevenbergen–Thorne) derivatives as slope, not Horn's.
- Map.
- Fidelity: Same engine. Marching squares is what GIS contouring runs.
- Professional equivalent: Civil 3D surface contours from a surveyed TIN (with breaklines); GDAL
gdal_contour; the surveyor's own contour drawing. - Trust it for / don't use it for: Trust it for massing and site-model bases. Don't use it for grading plans.
- The gap:
- Map contours and exported contours come from different DEMs and can disagree slightly.
- Grid contours cannot show features smaller than the spacing.
- No breaklines, so contours cross curbs and walls smoothly.
- Code:
src/lib/site-analysis/ground-core.ts,src/lib/site-analysis/contour-core.ts,src/app/(app)/site-analysis/SiteMapGL.tsx
Drainage & flow
Where the water goes on this ground.
- What it adds: A flow-accumulation drape in five log classes, thalweg polylines exported as real curves, the outlet (the edge cell carrying the most water), the percentage of the box that is channelised, and the percentage the fill had to raise.
- Method:
- Priority-Flood depression filling (Barnes, Lehman & Mulla) from the box edges on a heap, with ε = 1e-5 m (0.0004 in) per cell.
- D8 steepest descent, slope divided by true diagonal distance.
- Accumulation in one high-to-low pass.
- Channels are cells with accumulation ≥ max(8, 1% of n²), walked from channel heads.
- Fidelity: Same engine. It is the textbook GIS pipeline (ArcGIS Fill → Flow Direction → Flow Accumulation, with Priority-Flood as in WhiteboxTools and RichDEM).
- Professional equivalent: The ArcGIS Pro Hydrology toolset or WhiteboxTools (often breaching rather than filling, or D-infinity/MFD routing). USGS StreamStats to delineate the contributing area and get regression peak flows. HEC-HMS or EPA SWMM, with pipes and inlets, for a civil engineer's stormwater report.
- Trust it for / don't use it for: Trust it for flow direction, where water collects, which edge it leaves by, and what a flow path crosses (important on a contaminated site). Don't use it for flow rates, pipe or detention sizing, or floodplain limits.
- The gap:
- Terrain only: no storm sewers, culverts, curbs, infiltration or rainfall.
- The box edge is both outlet and watershed limit. A creek entering from uphill carries only the area inside the box, so accumulation is understated for through-flowing streams.
- The channel threshold is 1% of the box, so channel density changes with span (0.24 acre at 1,000 ft, 161 acres at 5 mi).
- Filling (rather than breaching) floods road embankments into false lakes.
- Fabricated (mean-filled) cells take part in fill and routing; they are only hidden in the drape.
- Code:
src/lib/site-analysis/drainage.ts
Sun hours
Hours of direct sun per cell on a solstice or equinox, with hills and neighbours in the way.
- What it adds: A classed drape (2/4/6/8 h breaks), the share of ground with 6 h or more and with under 2 h, and the mean. It is also exported as a Rhino drape.
- Method:
- Height field. The height field is the 3DEP grid raised under OSM building footprints. Height is the
heighttag, elsebuilding:levels× 10.5 ft (3.2 m), else 14.8 ft (4.5 m). - Timesteps. The dates are June 21, March 21 and December 21, in 30-minute steps; steps with the sun below 0.5° are skipped. Sun position is NOAA/Meeus.
- Ray march. Per cell, a ray marches toward the sun one cell per step, climbing tan(altitude) per step against a bilinear height field. It stops when it leaves the grid (counted lit) or clears the tallest point.
- Height field. The height field is the 3DEP grid raised under OSM building footprints. Height is the
- Fidelity: Screening estimate. The physics is right for direct beam; the obstructions are simplified.
- Professional equivalent: Ladybug Direct Sun Hours or ClimateStudio on the actual 3-D model; ArcGIS Area Solar Radiation (direct plus diffuse over a viewshed).
- Trust it for / don't use it for: Trust it for comparing spots on the site and for the shading effect of big terrain and mapped buildings. Don't use it for solar access compliance, PV yield or courtyard daylight hours.
- The gap:
- Direct beam only: no diffuse sky, no cloud (every hour is treated as clear), no trees.
- Buildings are rasterised to the grid, so a 40 ft street at 26 ft spacing is one or two cells; at 2–5 mi, narrower still.
- Untagged heights are guesses, and OSM coverage is uneven.
- Distant horizons outside the box are ignored. A ridge a mile away never casts, which over-states winter sun in valleys.
- At 3 and 5 mi the outer band has no buildings.
- Code:
src/lib/site-analysis/sun-hours.ts,src/lib/site-analysis/geo.ts(solarPosition)
Climate year
One hourly year at the site: temperatures, humidity, degree-days, design conditions, comfort, precipitation.
- What it adds: Monthly temperature and RH. HDD/CDD on base 65°F (18.33°C). Mean diurnal swing. Heating 99.6/99% and cooling 0.4/1/2% dry-bulb, plus extremes. ASHRAE-55 adaptive comfort hours by month. A Givoni strategy mix. Daylight hours. Precipitation and snow.
- Method:
- Data. Open-Meteo archive API for 2023 only (
CLIMATE_YEAR): twelve hourly variables,timezone=auto. The request names no model, so Open-Meteo's default "Best Match" blend applies, which Open-Meteo documents as combining ECMWF IFS HRES (~5.6 mi / 9 km, from 2017), ERA5 (0.25°, ~15 mi / 25 km) and ERA5-Land. A 2023 year is therefore probably served largely by the IFS; the per-variable mix is not documented. - Design days. Percentiles of the sorted 8,760 hours.
- Adaptive comfort. Tcomf = 0.31 × Trm + 17.8°C, where Trm is an exponentially weighted (α = 0.8) mean of prior days, clamped to 50–92°F (10–33.5°C). The band is ±6.3°F (±3.5°C), with air temperature standing in for operative temperature.
- Givoni. Mutually exclusive dry-bulb and humidity-ratio boxes, labelled "clearly an approximation" in code.
- Data. Open-Meteo archive API for 2023 only (
- Fidelity: Screening estimate for the year and its percentiles and comfort. Classroom proxy for the Givoni mix.
- Professional equivalent: The ASHRAE Handbook, Fundamentals, climatic design conditions: station-based, multi-decade percentiles. TMY3/TMYx station files in Climate Consultant or Ladybug. For comfort, CBE Comfort Tool with operative temperature.
- Trust it for / don't use it for: Trust it for the shape of the seasons, whether heating or cooling dominates, and rough comfort share. Don't use it for HVAC sizing or code design temperatures.
- The gap:
- One year (2023) carries that year's anomalies. ASHRAE's percentiles span decades.
- Reanalysis smooths extremes, so the 99.6% and 0.4% values are likely less extreme than the station values.
- A 6–15 mi model cell misses urban heat island, coastal and valley effects; diurnal swing can be off by several °F.
- Adaptive comfort without mean radiant temperature overstates comfort in sunny hours.
- Code:
src/lib/site-analysis/climate.ts,src/app/api/site-analysis/analyze/route.ts(summarizeClimate, climateExtras)
Wind
Prevailing wind by year and season.
- What it adds: A 16-sector rose with speed bands at 4.5, 8.9, 13.4 and 17.9 mph (2, 4, 6, 8 m/s); calm is under 1.1 mph (0.5 m/s). Also the prevailing direction by meteorological season. It is also drawn in the .3dm.
- Method: It bins the same hourly 10 m (33 ft) wind speed and direction from the climate year.
- Fidelity: Screening estimate. It is regional prevailing wind from a model cell.
- Professional equivalent: A wind rose from the nearest airport ASOS station (multi-year). For site-level flow: CFD (Eddy3D, Butterfly/OpenFOAM, Autodesk CFD) or a wind-tunnel study for tall buildings.
- Trust it for / don't use it for: Trust it for which quarter winter and summer winds come from, for siting outdoor rooms and ventilation openings. Don't use it for pedestrian comfort, gust or downdraft questions.
- The gap: No channelling by valleys, streets or buildings. A single year. Speeds are for open terrain at 10 m and overstate wind at ground level in built-up areas.
- Code:
src/lib/site-analysis/geo.ts(windRose),src/lib/site-analysis/climate.ts(seasonalWind)
Façade solar & sun path
Where the sun goes, and how much reaches each façade orientation.
- What it adds: Sun-path arcs (every 30 minutes) and annual incident solar in kWh/m²·yr on eight vertical orientations plus the roof.
- Method: NOAA/Meeus solar position is computed per hour. Per hour and orientation: DNI × cos(incidence) + DHI × 0.5 (isotropic sky share for a vertical plane) + GHI × 0.2 albedo × 0.5 ground share. Irradiance comes from the same modelled year.
- Fidelity: Standard method. It is the isotropic-sky (Liu–Jordan) hand method on modelled irradiance.
- Professional equivalent: Ladybug Incident Radiation or ClimateStudio (Radiance with a cumulative sky), and EnergyPlus's Perez anisotropic sky on the real geometry with context shading.
- Trust it for / don't use it for: Trust it for ranking orientations and the south-versus-west trade. Don't use it for PV yield or glazing heat-gain loads.
- The gap:
- The isotropic sky spreads circumsolar diffuse evenly, so it understates sun-facing façades and overstates north ones relative to Perez.
- No shading from terrain, neighbours or the building itself.
- Sun position is computed at each hour's timestamp, while Open-Meteo documents its radiation variables as the mean of the preceding hour. Incidence is therefore evaluated about 30 minutes after the middle of the hour it describes, and an hour whose end-stamp falls after sunset is left out even though it carried sun. This matters most on east and west façades.
- Code:
src/lib/site-analysis/climate.ts(facadeSolar),src/lib/site-analysis/geo.ts(solarPosition, sunPaths)
.epw export
The climate year as an EnergyPlus weather file, and the pipe to Eco-Architect and Skin.
- What it adds: A downloadable .epw and the same file handed to other tools through localStorage.
- Method: Eight header lines and 8,760 rows, with the leap day dropped.
- Written: dry bulb, dew point, RH, pressure, GHI, DNI, DHI, wind, and sky cover (cloud ÷ 10, written to both total and opaque).
- Left as EPW missing codes: illuminance, IR, visibility, precipitation and the rest. DESIGN CONDITIONS and GROUND TEMPERATURES are 0.
- Header: says "NOT a measured TMY".
- Refusal: it refuses to write if the year is not 8,760 hours.
- Hour labels: each row's hour is Open-Meteo hour + 1.
- Fidelity: Screening estimate.
- Professional equivalent: TMYx files (climate.onebuilding.org), NREL NSRDB TMY (satellite-derived irradiance), Meteonorm.
- Trust it for / don't use it for: Trust it for early Ladybug and Honeybee comparisons at a site with no nearby station file. Don't use it for energy-code compliance, LEED or equipment sizing.
- The gap:
- One actual year, not a typical year.
- Modelled irradiance.
- Illuminance fields are missing, so daylight-illuminance workflows that read them fail.
- Opaque sky cover is copied from total cover.
- Each row is one hour later than the hour it describes. Open-Meteo stamps temperature, humidity, wind and pressure as instants at the timestamp and radiation as the mean of the preceding hour, which is already EPW's convention for hour N (radiation over the hour ending at N, instants at N). With the +1 mapping, Open-Meteo's 13:00 values are written to EPW hour 14, so allow for the one-hour offset when hourly timing matters.
- Code:
src/lib/site-analysis/exporters.ts(climateEPW),src/app/(app)/site-analysis/site-pipe.ts
Flood (FEMA NFHL)
The flood zone at the point, and the zones and BFE lines across the box.
- What it adds: The zone, subtype, SFHA yes/no and static BFE at the survey point. It separates a mapped Zone X from an unmapped area by testing FIRM panel coverage. Zone polygons (up to 200 records) and BFE lines (feet, NAVD88) are clipped to the box and exported as curves.
- Method: NFHL layer 28 point query, then layer 3 (panels) if no zone is found. Vectors come from layers 28 and 14 via an envelope query, generalised to 1/2000 of the box, and are clipped with Sutherland–Hodgman / Liang–Barsky.
- Fidelity: Same engine. The same effective NFHL data a FIRMette is printed from, where the NFHL is digitised.
- Professional equivalent: A FIRMette from the FEMA Map Service Center. An elevation certificate by a surveyor (structure elevations against BFE). A LOMA or LOMR. The local floodplain administrator. For risk beyond the regulatory map: First Street-type models or HEC-RAS.
- Trust it for / don't use it for: Trust it for whether the point or any part of the box is in an SFHA, and where BFE lines run. Don't use it for insurance ratings, lender determinations or finished-floor elevations.
- The gap:
- The zone card is the centre point only. The polygons show the rest, but no per-structure read.
- Preliminary or pending maps and paper-only FIRMs are not in the NFHL. The code treats "no panel" as unmapped.
- No ground elevations relative to BFE unless you compare against the coarse grid yourself.
- The regulatory map excludes pluvial flooding and future conditions.
- Code:
src/lib/site-analysis/datasources.ts(floodAt, floodVectorsAt)
Soils (USDA SSURGO)
The mapped soil at the survey point.
- What it adds: Map unit name, drainage class, hydrologic group (A–D), minimum annual water-table depth, depth to bedrock, available water storage (0–100 cm), flood frequency, hydric percentage, representative slope, and the SSURGO ratings for dwellings without basements and small commercial buildings.
- Method: One T-SQL POST to Soil Data Access joining
mapunittomuaggatt(dominant condition) for the map unit intersecting the point. NOTCOM or empty units count as no coverage. - Fidelity: Same engine. It is the same database Web Soil Survey reads.
- Professional equivalent: Web Soil Survey over a drawn area of interest (area-weighted ratings across all units). A geotechnical investigation: borings with SPT, lab tests, a bearing-capacity and settlement recommendation. Percolation or infiltration tests for stormwater.
- Trust it for / don't use it for: Trust it for early flags: hydric soils, D-group runoff, shallow water table or bedrock, "very limited" for dwellings. Don't use it for foundation design or infiltration sizing.
- The gap:
- One map unit at one point, even in a 5 mi box.
- Map units are drawn at county survey scale and include dissimilar components; "dominant condition" hides them.
- Urban and fill soils are poorly characterised.
- Nothing below about 6.6 ft (2 m).
- Water-table and bedrock depths are delivered in cm (converted for display).
- Code:
src/lib/site-analysis/layers.ts(soilsAt)
Bedrock geology (Macrostrat)
The mapped geologic unit under the point.
- What it adds: Unit name, age and lithology from the point query, plus a Macrostrat tile overlay and drape.
- Method: Macrostrat
geologic_units/mapat the point. It is a harmonised compilation of state and national geologic maps. - Fidelity: Same engine for the map. It says nothing about depth.
- Professional equivalent: The state geological survey's quadrangle map. Boring logs to refusal. Seismic refraction for depth to rock.
- Trust it for / don't use it for: Trust it for the regional story (karst, glacial till over limestone). Don't use it for depth to rock or excavation difficulty.
- The gap: Map scale varies widely by area. Surficial deposits may be what matters, not bedrock. There is no depth.
- Code:
src/lib/site-analysis/layers.ts(geologyAt)
Groundwater (USGS NWIS well)
The nearest real depth-to-water reading.
- What it adds: Well name, distance, latest depth to water in feet (parameter 72019) and date. The well is drawn on the map.
- Method: NWIS
gwlevelsin a ±0.15° box (~10 mi north–south, somewhat less east–west), over the last 1,095 days. It takes the nearest well's most recent non-negative reading. - Fidelity: Classroom proxy as a reading of this site's water table. The number itself is a real measurement, somewhere else.
- Professional equivalent: Groundwater levels logged in geotechnical borings. Piezometers or monitoring wells on site. On a contaminated site, the monitoring-well network in the remedial investigation.
- Trust it for / don't use it for: Trust it for whether groundwater is plausibly shallow in the area. Don't use it for basement or dewatering decisions.
- The gap: The well can be miles away, in a different aquifer (confined or deep) and at a different ground elevation. It is one reading, not a seasonal high. SSURGO's water-table field is often the better local proxy.
- Code:
src/lib/site-analysis/layers.ts(groundwaterAt)
Wetlands (USFWS NWI)
Whether the point sits in a mapped wetland.
- What it adds: The Cowardin code, wetland type and polygon acreage at the point (null on dry ground, not counted as a coverage failure), plus a map overlay and drape.
- Method: NWI MapServer point query.
- Fidelity: Same engine. It is the same NWI data.
- Professional equivalent: A wetland delineation by a qualified delineator to the 1987 USACE manual and regional supplement. A USACE jurisdictional determination.
- Trust it for / don't use it for: Trust it as a red flag that triggers a delineation. Don't use it to conclude there are no wetlands.
- The gap:
- NWI is photo-interpreted, often decades old, and not jurisdictional. It misses small and forested wetlands.
- The point query checks one point; the overlay shows the rest visually only.
- The AI synthesis does not see this result.
- Code:
src/lib/site-analysis/layers.ts(wetlandAt)
Land cover (NLCD 2021)
What covers the ground: class, impervious share, tree canopy.
- What it adds: NLCD class, % developed impervious and % tree canopy at the point, plus three overlays and drapes.
- Method: Three MRLC WMS GetFeatureInfo reads of the centre pixel of a 101-pixel render. The layers are
NLCD_2021_Land_Cover_L48,NLCD_2021_Impervious_L48andnlcd_tcc_conus_2021_v2021-4(lower 48 only). - Fidelity: Same engine. It is the NLCD product at its 98 ft (30 m) cells.
- Professional equivalent: A tree survey by an arborist. A planimetric survey of impervious area (what stormwater fees are billed on). High-resolution (~3 ft / 1 m) land cover from aerial imagery. i-Tree for canopy benefits.
- Trust it for / don't use it for: Trust it for neighbourhood character and the rough impervious share. Don't use it for stormwater credit calculations or tree-preservation plans.
- The gap:
- A 30 m pixel read at one point.
- 2021 vintage.
- Alaska and Hawaii are not covered by these layers.
- Code:
src/lib/site-analysis/layers.ts(landCoverAt),src/lib/site-analysis/map-layer-urls.ts
Watershed & surface water
Which watershed the site is in, and the streams around it.
- What it adds:
- HUC12 and HUC8 names and codes, HUC12 area, and the HUC12 boundary.
- Map overlays: USGS NHD surface water, and a bold "rivers and streams" layer drawn from the OSM surroundings.
- Method: WBD MapServer layers 6 and 4 point queries. The boundary is generalised to about 130 ft (40 m).
- Fidelity: Same engine.
- Professional equivalent: USGS StreamStats, which delineates the catchment to your own outlet and gives regression peak flows. An engineer's drainage-area map.
- Trust it for / don't use it for: Trust it for the receiving waters and the watershed plan that may govern. Don't use it for the area draining onto your parcel.
- The gap: A HUC12 is typically tens of square miles. The site-scale catchment is what Drainage approximates, truncated at the box.
- Code:
src/lib/site-analysis/layers.ts(watershedAt)
Seismic (USGS, ASCE 7-16)
Seismic design parameters for an early Seismic Design Category.
- What it adds: Ss, S1, SDS, SD1 and SDC.
- Method: USGS
building-codes/asce7-16/calculatewithsiteClass=D,riskCategory=II. - Fidelity: Same engine for ASCE 7-16 at the assumed inputs.
- Professional equivalent: The ASCE Hazard Tool or the USGS web service for ASCE 7-22, which IBC 2024 references, with site class from a geotechnical report (measured shear-wave velocity or SPT). ASCE 7-22 adds intermediate site classes (BC, CD, DE) and multi-period spectra. Its default for unknown soil (§11.4.3) is the most critical of Site Classes C, CD and D at each period, not simply D, unless the authority having jurisdiction finds DE, E or F soils.
- Trust it for / don't use it for: Trust it for whether seismic design will shape the structure (SDC A/B versus D+). Don't use it for design values.
- The gap:
- Superseded edition. It may still match a local code if the jurisdiction is on IBC 2018 or 2021; check.
- Site Class D is assumed; soft soils (E/F) or rock change the values materially.
- Risk Category II is assumed; schools and essential facilities differ.
- One point.
- Code:
src/lib/site-analysis/layers.ts(seismicAt)
EPA NPL record & boundary
EPA's own record of a listed site (Superfund mode) and the NPL dots layer (either mode).
- What it adds: Covered under Mode · Superfund. Separately, "show all Superfund sites" scatters every NPL site in the current view (refused past 30° across). Clicking a dot runs a full Superfund survey.
- Method: ArcGIS FeatureServer queries on EPA's NPL and boundary layers.
- Fidelity: Same engine.
- Professional equivalent: EPA SEMS / Cleanups in My Community. The NPL section of a Phase I database report.
- Trust it for / don't use it for: Trust it for the listing status and the documents. Don't use it as a proximity search for other contamination.
- The gap: NPL only. The boundary is administrative, and holes are drawn filled.
- Code:
src/lib/site-analysis/datasources.ts,src/app/api/site-analysis/search/route.ts
OSM surroundings
Buildings, roads, rail, water and green space around the site.
- What it adds: Footprints extruded as solids, linework by class, water and green. They are used by sun hours, sections, the rivers layer and every export.
- Method: Overpass API (two mirrors). Results are fetched for the terrain bbox and clipped to it. Above 2.8 mi (4.5 km) only the central sub-box is fetched and flagged partial. Heights come from tags, else 10.5 ft (3.2 m) per level, else a default.
- Fidelity: Screening estimate. Community-mapped geometry of uneven completeness, with guessed heights.
- Professional equivalent: City or county planimetric GIS. The surveyed topo (buildings, curbs, utilities). Lidar-derived building heights or a city 3-D model.
- Trust it for / don't use it for: Trust it for context massing and street pattern. Don't use it for setbacks, adjacency distances or exact heights.
- The gap:
- Completeness varies by town.
- Untagged heights are guessed.
- No trees, fences or topography of roofs.
- Partial at 3 and 5 mi.
- Code:
src/lib/site-analysis/layers.ts(contextInBBox, overpassSafeBox),src/app/api/site-analysis/context/route.ts
Traced parcel
Your own boundary, drawn on the map (Place mode).
- What it adds:
- An orange boundary with acreage.
- Terrain statistics recomputed over the parcel only.
- Exports on the boundary layers.
- Saved with the site and carried in share links.
- Method: Validation rejects degenerate or self-intersecting rings. Acreage is the shoelace area in the local projection.
clipTopoToParcelmasks cells outside the ring (parcel.ts). - Fidelity: .
- Professional equivalent: County parcel GIS or Regrid for the assessor's line. An ALTA/NSPS or boundary survey for the legal one.
- Trust it for / don't use it for: Trust it for studying the ground you intend to design on. Don't use it for area-based zoning math on a real lot.
- The gap:
- It is as accurate as your clicks on a web basemap.
- The AI synthesis does not see the traced parcel; it reads the whole-box result.
- Code:
src/lib/site-analysis/parcel.ts,src/app/(app)/site-analysis/site-analysis-tool.tsx
Section cut
A site section between two points you drop.
- What it adds: A ground profile with OSM buildings (at tagged or estimated heights) and water crossings. Fabricated ground is drawn dashed. Output is SVG and DXF.
- Method: 400 evenly spaced samples of the bilinear grid along the line. Crossings are found by sampling footprints along the line.
- Fidelity: on Same engine ground.
- Professional equivalent: A Civil 3D section view from a surveyed surface, or a Rhino section through a surveyed model.
- Trust it for / don't use it for: Trust it for studio site sections and a vertical-exaggeration read of landform. Don't use it for grading sections.
- The gap: Ground detail is limited to the span's grid spacing. Building heights are OSM's. There are no trees or below-grade structures.
- Code:
src/lib/site-analysis/section.ts,src/app/(app)/site-analysis/section-card.tsx
AI reading passes
Five optional model passes: sign-in, metered, and none of them overwrite a measured number.
What it adds:
- Sources. Automatic when a place lands: authoritative links.
- Chat. "Ask about this place".
- Contamination brief. Superfund mode only.
- Design synthesis.
- Blind vs grounded. The hallucination lesson.
Method:
- Tiers. Fast = Claude Haiku 4.5 (default). Deep = Claude Sonnet 5. Open = an env-gated open-weight MiniMax model; the sources and blind-vs-grounded passes refuse Open. A stalled attempt retries on the fast model with a smaller search budget.
- Sources get the place plus the bundle (≤24,000 characters), with web search capped at 4 uses behind a deny-list.
- Chat gets the dossier (≤60,000 characters, 16 turns), with 4 searches.
- Contamination gets the EPA record re-fetched server-side, with 5 searches.
- Synthesis gets the compacted client bundle (≤200 KB) with no search. The bundle holds climate, flood point, terrain statistics, soils, land cover, watershed, seismic, geology, groundwater and the contamination brief. It does not include wetlands, drainage, sun hours, OSM surroundings (buildings) or the traced parcel.
- Blind vs grounded runs the same profile prompt with no tools and with 5 searches.
What is checked: Link probing is uneven across the passes:
Pass Links probed (HEAD, then GET) before render? Sources Yes, unless the soft timeout fired Chat Yes, unless the soft timeout fired Contamination Yes: sourcesand every claim link are probed; dead links are dropped or blankedSynthesis No: deny-list and scheme check only (the pass is asked to return no links) Blind vs grounded No, deliberately Claims are tagged verified / plausible-unverified / likely-hallucination. The rule that an ungrounded pass may tag nothing "verified" describes what the prompt asks for; it is not a check enforced in code. The synthesis prompt forbids new figures and demands cross-layer intersections.
Fidelity: AI reading.
Professional equivalent: A human researcher or environmental professional doing an ASTM E1527 records review and interviews. A landscape architect's site-analysis narrative.
Trust it for / don't use it for: Trust it for a reading list, questions to ask, and a synthesis that cross-references measured layers. Don't use it for contaminant lists, institutional controls or anything quoted as fact without opening the source.
The gap:
- "Verified" is the model's self-report against pages it found. Links are checked for being reachable, not for supporting the claim.
- The contamination card's "(EPA-grounded)" title describes what the prompt asks for, not a code-enforced check; it appears on every run, including an Open-tier run without web grounding.
- The studio sites' cached readings were not produced by this pipeline (see Superfund).
Code:
src/app/api/site-analysis/{sources,chat,contamination,synthesis,blind-vs-grounded}/route.ts,src/lib/anthropic/site-analysis-prompts.ts,src/lib/anthropic/link-check.ts,src/lib/anthropic/source-quality.ts
Shared across all options
- Fetching. Every fetch is keyless, runs in parallel, and degrades to null. A coverage strip names what failed. Terrain, flood, soils, land cover, watershed, wetlands, wells and seismic are US-only. Climate and OSM are global.
- Projection. One equirectangular local projection about the box's south-west corner registers terrain, contours, boundary, context and every export.
- Units. Units display imperial by default (with a metric toggle). The data stays SI.
- Exports. Exports are client-side and ungated:
- .3dm kit as surfaces and as mesh
- .obj kit
- .dxf contours, surroundings and boundary
- .geojson
- .epw
- metrics CSV
- Dossier JSON/MD
- atlas PNG/SVG
- Hand-offs. Grade, Eco-Architect, Proving Ground, Skin and Relief receive the grid, identity and .epw through one localStorage key. All exports inherit the span's grid spacing ().
- Share links. A share link or saved site stores the request (mode, span, point or EPA ID, parcel), not the result, so it re-runs against live sources.