원클릭으로
atlas-tx-water-data-lane
Build Atlas TX water/flood intelligence slices using verified public endpoints, county joins, and TDD-first adapters.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Build Atlas TX water/flood intelligence slices using verified public endpoints, county joins, and TDD-first adapters.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Bootstrap the Atlas TX project from zero: create public GitHub repo, scaffold Next.js app, lock MVP Texas datasets, add county normalization, and add initial Socrata adapter helpers with TDD.
Add approachable acronym definitions and lightweight glossary tooltips to Atlas TX without changing the product tone or introducing heavy client-side UI.
Extend Atlas TX's MCP surface to mirror filing-level permit workflows and plan/ship snapshot-pipeline automation without splitting web and MCP data paths.
Build or extend Atlas TX's /permits page using the stable TCEQ water-quality pending-permits Socrata dataset plus an optional snapshot-backed CID open-cases lane with explicit coverage caveats.
Extend Atlas TX's permits workflow with filing-level red-flag scoring, `/permits/[tceqId]` detail pages, and non-legal protest-helper UX built on CID procedural data.
Build Atlas TX county/data feature lanes using structured public endpoints, county-normalized summaries, and honest map layers before heavier geospatial analytics.
| name | atlas-tx-water-data-lane |
| description | Build Atlas TX water/flood intelligence slices using verified public endpoints, county joins, and TDD-first adapters. |
| version | 1.0.0 |
| author | Hermes Agent |
| license | MIT |
| metadata | {"hermes":{"tags":["atlas-tx","water","flood","texas","nextjs","socrata","usgs","nws","tdd"],"related_skills":["writing-plans","test-driven-development"]}} |
Use when extending /home/stathis/Projects/atlas-tx with water/flood features.
https://hazards.fema.gov/arcgis/rest/services/public/NFHL/MapServer?f=pjsonhttps://waterservices.usgs.gov/nwis/site/?format=rdb&stateCd=tx&siteType=ST&siteStatus=activehttps://api.weather.gov/alerts/active?area=TXhttps://data.texas.gov/resource/8kc5-95uk.json?$limit=1https://data.texas.gov/resource/6pm5-am5m.json?$limit=1https://data.texas.gov/resource/hr84-s96f.json?$limit=1https://data.texas.gov/resource/auk8-env9.json?$limit=1https://data.texas.gov/resource/iuez-sv34.json?$limit=1Important: auk8-env9 and iuez-sv34 are live Socrata resources but are not in the current MVP dataset registry, so fetchDatasetRows() from src/lib/texas-open-data.ts will reject them. For governance work, fetch them directly from /resource/<id>.json instead of routing through the MVP registry helper.
Create under src/lib/water/:
types.tswater-source-registry.tscounty-lookup.tsnws.tsusgs.tstceq-sewer-overflows.tstceq-general-permits.tswater-governance.tswater-summary-service.tsAPI routes:
src/app/api/water/overview/route.tssrc/app/api/water/counties/[slug]/route.tssrc/app/api/water/alerts/route.tssrc/app/api/water/gauges/route.tsUI:
src/app/water/page.tsxTests:
tests/water-source-registry.test.tstests/nws-water-alerts.test.tstests/usgs-water.test.tstests/tceq-sewer-overflows.test.tstests/tceq-general-permits.test.tstests/water-governance.test.tstests/water-governance-summary.test.tstests/water-summary-service.test.tstests/water-api-routes.test.tstests/water-alerts-route.test.tstests/water-gauges-route.test.tstests/water-page.test.tstests/water-page-governance.test.tsnormalizeCountyName() and countySlug().county-lookup.ts helper backed by src/lib/texas-county-centroids.ts so county FIPS can resolve to county names/slugs.travis-county must normalize back to Travis County. Fix by replacing hyphens with spaces inside normalizeBaseCountyName() in src/lib/counties.ts.areaDesc by splitting on commas/semicolons.Travis County form.# comment lines.48.county-lookup.ts.incident_location_county through county helpers.amount_unit to gallons.MGD as value * 1_000_000.tceq-general-permits.ts once the first water slice is green.county_name through county helpers.permit_no, permit_status, permit_type, site_name, and lat/lon.generalPermitCount before doing deeper permit-status analytics.water-governance.ts after permits are stable.hr84-s96f into WaterGovernanceEntity with:
district_number -> entityIddistict_name -> entityNamedistrict_type -> entityTypeactivity_status -> activityStatus/resource/*.json calls, not the MVP registry helper.puct-water-iou, set entityType to Investor-Owned Utility.puct-water-submeter, preserve utility_type when present and fall back to Submeter Utility.primary_county for the first county join; do not explode all_counties yet.waterDistrictCount for tceq-water-districtswaterUtilityCount for all PUCT utility recordsCountyWaterSummary.generalPermitCount before attempting a richer permit score.waterDistrictCount and waterUtilityCount.permits and governance alongside alerts/gauges/sewer overflows.tceq-water-districts separately from PUCT utility sources.metrics.floodplainFeatureCount from joined NFHL political-jurisdiction counts and set overlays.hasFloodplainLayer from that real count.getCountyWaterBreakdown() still resolves the county and returns a note like NFHL political jurisdictions mapped: N.https://echo.epa.gov/tools/data-downloadshttps://echo.epa.gov/files/echodownloads/SDWA_latest_downloads.ziphttps://echo.epa.gov/tools/data-downloads/sdwa-download-summarySDWA_PUB_WATER_SYSTEMS.csvSDWA_FACILITIES.csvSDWA_GEOGRAPHIC_AREAS.csvSDWA_EVENTS_MILESTONES.csvSDWA_VIOLATIONS_ENFORCEMENT.csvhttps://echo.epa.gov/files/echodownloads/Data-Analytics/WQI/https://echo.epa.gov/maps/water-quality-indicatorswqi_stations_summary_<timestamp>.zipwqi_monthly_sample_data_<timestamp>.ziphttps://echo.epa.gov/tools/data-downloads/national-pfas-datasetshttps://mytapscore.com/pages/us-water-datahttps://mytapscore.com/pages/tap-score-algorithmsrc/lib/water/lcra-hydromet.tssrc/app/api/water/lcra/hydromet/stage-flow/route.tssrc/app/api/water/lcra/hydromet/lake-levels/route.tstests/lcra-hydromet.test.tstests/lcra-hydromet-routes.test.tsLcraStageFlowReading
sourceId: 'lcra-hydromet-stageflow'siteNumber as stringstationName from locationobservedAt from dateTimestageFeet, flowCfs, bankfullFeet, floodStageFeetLcraLakeLevelReading
sourceId: 'lcra-hydromet-lakelevels'siteNumber as stringstationName from locationobservedAt from dateTimeelevationFeet?siteNumber=<id> and filter server-side{ readings, freshness }buildWaterFreshness(['lcra-hydromet-stageflow']) or buildWaterFreshness(['lcra-hydromet-lakelevels'])src/lib/water/freshness.tslcra-hydromet-stageflowlcra-hydromet-lakelevelslcra-arrp-outfallslcra-arrp-land-permitssrc/lib/water/water-source-registry.ts, update tests/water-source-registry.test.ts immediately or the full suite will fail on expected source count/order and source counthttps://hydromet.lcra.org/api/GetStageFlowForAllSites/https://hydromet.lcra.org/api/GetLakeLevelsForAllSiteshttps://waterquality.lcra.org/api/Sites/GetSiteshttps://waterquality.lcra.org/arrp/api/Outfallhttps://waterquality.lcra.org/arrp/api/LandPermitsrc/lib/water/lcra-arrp.tssrc/app/api/water/lcra/arrp/outfalls/route.tssrc/app/api/water/lcra/arrp/land-permits/route.tstests/lcra-arrp.test.tstests/lcra-arrp-routes.test.ts{ result: [...], id, exception, status, isCompleted, ... }payload.result first, then normalize recordsLcraArrpOutfall
sourceId: 'lcra-arrp-outfalls'recordId from objectidpermitNumber from permitNumpermitteeName from permitteecountyName normalized via normalizeCountyName()status, segmentId, basinId, outfallNumber, latitude, longitudeLcraArrpLandPermit
sourceId: 'lcra-arrp-land-permits'recordId from recordIdpermitNumber from permitNumpermitteeName from permitteecountyName normalized via normalizeCountyName()status, segmentId, basinId, permitType from permittype, reviewType from revtype, latitude, longitude/api/water/lcra/arrp/outfalls?county=<slug> returns { outfalls, freshness }/api/water/lcra/arrp/land-permits?county=<slug> returns { permits, freshness }countySlug()Agency='LCRA' rows, and 169 ImpairedSegment=true rowsCurrent and 9 PendingCurrent and 9 PendingsiteNumber, location, dateTime, stage, flow, bankfull, floodStage, elevationSiteId, SiteName, SegmentId, SegmentName, RootSegmentId, Latitude, Longitude, LastDate, Agency, IsActive, ImpairedSegmentpermitNum, permittee, status, county, latDd, longDd, segment, basinoutfalllcra-hydromet-stageflow, lcra-hydromet-lakelevels, lcra-water-quality-sites, lcra-arrp-outfalls, lcra-arrp-land-permits, lcra-crwnhydromet_gauge, lake_level_station, basin_water_quality_site, wastewater_outfall, land_application_permithydrometGaugeCount, activeFloodGaugeCount, reservoirStationCount, waterQualitySiteCount, activeWaterQualitySiteCount, impairedSegmentSiteCount, wastewaterOutfallCount, landApplicationPermitCountperformance.getEntriesByType('resource') or page JS first, then hit discovered /api/... URLs directly.waterquality.lcra.org:
https://waterquality.lcra.org/api/Sites/GetSite/<siteId>https://waterquality.lcra.org/api/Sites/GetSiteParameters/<siteId>https://waterquality.lcra.org/api/Sites/GetSiteData/<siteId>https://waterquality.lcra.org/api/Sites/GetSiteData/<siteId>?IncludeProfile=truehttps://waterquality.lcra.org/api/Segments/GetSegment/<segmentId>https://waterquality.lcra.org/api/Segments/GetSegmentParameters/<segmentId>https://waterquality.lcra.org/api/Segments/GetSegmentData/<segmentId>GetSite returns SiteId, SiteName, SegmentId, SegmentName, RootSegmentId, RootSegmentName, Latitude, Longitude, LastDate, Agency, IsActive, ImpairedSegment, SurfaceDataOverrideGetSiteParameters rows return SiteId, SegmentId, StoretCode, StoretName, StoretCategory, HasSurfaceDataGetSiteData rows return SiteId, SegmentId, StoretCode, StoretName, StoretCategory, Depth, Agency, Symbol, Value, DateGetSegment returns SegmentId, SegmentName, RootSegmentId, RootSegmentName, SiteIds, Agencies, ImpairedSegment, Sites[]src/lib/water/lcra-water-quality.tssrc/app/api/water/lcra/quality/sites/route.tssrc/app/api/water/lcra/quality/sites/[siteId]/route.tssrc/app/api/water/lcra/quality/sites/[siteId]/parameters/route.tssrc/app/api/water/lcra/quality/sites/[siteId]/observations/route.tstests/lcra-water-quality.test.tstests/lcra-water-quality-routes.test.tsLcraWaterQualitySite
sourceId: 'lcra-water-quality-sites'siteId, siteName, segmentId, segmentName, rootSegmentId, rootSegmentName, latitude, longitude, lastObservedAt, agency, isActive, impairedSegment, surfaceDataOverrideLcraWaterQualityParameter
sourceId: 'lcra-water-quality-parameters'siteId, segmentId, storetCode, storetName, storetCategory, hasSurfaceDataLcraWaterQualityObservation
sourceId: 'lcra-water-quality-observations'siteId, segmentId, storetCode, storetName, storetCategory, depth, agency, symbol, value, observedAt/api/water/lcra/quality/sites returns { sites, freshness }/api/water/lcra/quality/sites/[siteId] returns { site }/api/water/lcra/quality/sites/[siteId]/parameters returns { parameters }/api/water/lcra/quality/sites/[siteId]/observations returns { observations } with optional ?storetCode= and ?includeProfile=truesrc/app/api/water/lcra/quality/segments/[segmentId]/route.tssrc/app/api/water/lcra/quality/segments/[segmentId]/parameters/route.tssrc/app/api/water/lcra/quality/segments/[segmentId]/observations/route.ts/api/water/lcra/quality/segments/[segmentId] returns { segment }/api/water/lcra/quality/segments/[segmentId]/parameters returns { parameters }/api/water/lcra/quality/segments/[segmentId]/observations returns { observations } with optional ?storetCode= and ?includeProfile=trueLcraWaterQualitySegment
sourceId: 'lcra-water-quality-segments'segmentId, segmentName, rootSegmentId, rootSegmentNamesiteIds from both SiteIds CSV and Sites[] merged + dedupedagencies from CSV splitimpairedSegment, siteCountGetSegment can expose both a SiteIds CSV string and a Sites[] array.lcra-water-quality-sites should be wired into src/lib/water/freshness.tslcra-water-quality-site:<siteId>lcra-water-quality-parameters:<siteId>lcra-water-quality-observations:<siteId>:surface|profilewaterquality.lcra.org TLS verification can fail in some local Python/Node contexts on this machine (unable to verify the first certificate / UNABLE_TO_VERIFY_LEAF_SIGNATURE)safeLoad(() => fetcher(), fallback) worked well for optional LCRA enrichment.src/lib/texas-county-centroids.tsactiveLcraQualitySiteCountlatestLcraObservationAtavailableLcraParameterCountimpairedLcraMonitoringSiteCountDO (2), Temperature (1), Phosphorus (1)IsActive, ImpairedSegment, LastDate)availableLcraParameterCount and top STORET summaries there.src/lib/water/cache.ts with createWaterDataCache() and getGlobalWaterDataCache().getOrLoad(key, ttlMs, loader) so concurrent callers share the same pending Promise and repeated calls inside the TTL do not re-fetch.AbortSignal, bypass the cache and call the uncached loader directly.limit, do not reuse the generic cached entry for those parameterized calls.getFreshness(key) returning { cached, cachedAt, expiresAt, ttlMs } so API routes can expose cache state without re-fetching.src/lib/water/freshness.ts helper that maps public sourceIds to cache keys and builds a { generatedAt, sources } freshness payload for API responses./api/water/overview, /api/water/alerts, /api/water/gauges, and /api/water/fema/nfhl/levees.Source freshness section on /water with one badge/card per source showing Cached until <timestamp> and TTL in minutes. This makes live-demo reliability visible without opening APIs./api/water/fema/nfhl/levees-by-county that summarizes levees into { county, leveeCount, leveeNames, leveeIds } and attach freshness metadata there too.GET /api/water/sources/[slug]?month=YYYY-MMevidenceWindow: { month, timelinePoint, communitySamples }^\d{4}-\d{2}$; return 400 for invalid input/water/sources/[slug], anomaly cards should deep-link to evidence and exact timeline rows:
/api/water/sources/<slug>?month=<YYYY-MM>timeline-<YYYY-MM>src/lib/water/source-network.tssrc/app/api/water/sources/network/route.tstests/water-source-network.test.tstests/water-source-network-route.test.tsnodes[]: countySlug, countyName, lat, lon, multiCountySourceCount, contagionScoreedges[]: undirected shared-provider links with sharedSourceCount + sample sharedSourcesdirectedEdges[]: upstreamCountySlug, downstreamCountySlug, sharedSourceCount, sharedSourcesflowDirectionMethod: explicitly label heuristic, e.g. centroid-gulf-proxy-v1src/lib/water/hydrology-seed-edges.tssrc/lib/water/hydrology-dependencies.tssrc/app/api/water/sources/network/hydrology/route.tstests/water-hydrology-dependencies.test.tstests/water-hydrology-dependencies-route.test.tsseeded-river-network-v1upstreamContributionScoredownstreamDependencyScorecontagionScoresrc/app/water/network/page.tsx/water via RoutePill to /water/networktests/water-network-page.test.tsxtests/water-network-scatter.test.tsxtests/water-network-neighbors.test.tsxtests/water-page-network-link.test.tsx?county=<slug>&scope=<all|top10>#network-workspacedata-selected-county, data-selected-scatter, data-scatter-countyUpstream counties / Downstream counties lists and edge evidence/water/counties/<slug> and /water/sources/<slug>src/lib/water/network-analytics.tsflowDirectionMethod) so UI/API consumers know whether flow direction is inferred or physically modeledsource-network direction, add a separate hydrology-specific graph route and keep method labels explicit.src/lib/water/hydrology-seed-edges.tssrc/lib/water/hydrology-dependencies.tssrc/app/api/water/sources/network/hydrology/route.tssrc/app/water/network/page.tsxtests/water-hydrology-dependencies.test.tstests/water-hydrology-dependencies-route.test.tstests/water-network-page.test.tsxtests/water-network-scatter.test.tsxtests/water-network-analytics.test.tsflowDirectionMethod: 'seeded-river-network-v1'nodes[] with upstreamContributionScore, downstreamDependencyScore, contagionScore, and centroid fieldsedges[] with directed upstreamCountySlug, downstreamCountySlug, weight, evidencedownstreamDependencyScore = weighted incoming edgesupstreamContributionScore = weighted outgoing edgescontagionScore = blend of downstream-heavy + upstream contribution (first pass used 0.7 / 0.3)Upstream↔Downstream, Downstream↔Contagion, Upstream↔Contagion)x=upstream, y=downstream, bubble size=contagion) with URL-scoped mode toggle (scope=all|top10)searchParams (e.g. function Page({searchParams} = {})) so existing tests calling pageModule.default() do not crashdata-scatter-county=<slug>) for resilient testsDependency scatter, axis text, flow method) rather than brittle coordinate valuesflowDirectionMethod visible in UI copy and API payload until NHDPlus/USGS connectivity replaces seeds.src/lib/water/hydrology-seed-edges.tssrc/lib/water/hydrology-dependencies.tssrc/app/api/water/sources/network/hydrology/route.tssrc/app/water/network/page.tsxGET /api/water/sources/network/hydrology{ generatedAt, schemaVersion, flowDirectionMethod, nodes, edges }flowDirectionMethod value: seeded-river-network-v1upstreamContributionScore: sum of outgoing edge weightsdownstreamDependencyScore: sum of incoming edge weightscontagionScore: weighted blend (first pass used 0.7*downstream + 0.3*upstream)/water/network as a dedicated map-first routeupstreamCountySlug -> downstreamCountySlugcontagionScoreTop downstream dependency counties)/water to /water/networkrenderToStaticMarkup) asserting:
/api/water/alerts and /api/water/gauges should accept optional ?county= and filter server-side.src/app/water/page.tsx with a county table + selected-county detail panel; do this before maps if the API surface is still moving.src/lib/texas-county-centroids.ts and project lat/lon into a fixed SVG box; style counties by a simple heuristic combining floodplainFeatureCount, alert count, sewer-overflow count, and gauge count.data-county-slug / data-gauge-site attributes so page tests can assert on map content without brittle pixel checks./api/water/fema/nfhl/counties from the /water page once the FEMA county join route exists.renderToStaticMarkup() instead of JSON.stringify() or util.inspect() if you need to assert on real text content.module as a forbidden variable name in tests (@next/next/no-assign-module-variable). Use names like pageModule instead.any in mocked route tests; use small inline structural types so npm run lint stays green./water/sources/[slug] analytical UX, a high-signal pattern is:
openSignal = alerts + sewerOverflows + permitscoverageRatio = communitySampleCount / openSignal (0 when openSignal is 0)low, moderate, high) and color timeline rows + badges by severityTop anomalous months panel with jump links into anchored timeline rows (id=timeline-YYYY-MM) and an evidence API linkprofile.timeline, sort by score descending, slice top N, and assert rendered labels/links in tests/water-source-page.test.tsx.WaterBreakdown.layers, update all test fixtures immediately or page tests will fail on missing properties like governance.length./water starts reading overview.freshness, update all mocked getWaterOverview() fixtures in page tests to include at least freshness: { generatedAt, sources: {} }, otherwise server-component tests will crash before assertions.CountyWaterSummary or WaterBreakdown (for example LCRA after surface-water-quality), re-read and merge the latest src/lib/water/types.ts and src/lib/water/water-summary-service.ts before editing. These files are active integration hubs and are likely to diverge on metrics, overlays, and layers.lcraArrpOutfallCount, lcraArrpLandPermitCountlcraArrpOutfalls, lcraArrpLandPermitstypes.ts or water-summary-service.ts, do not pick one side. Manually merge both feature sets, then rerun the full verification loop before pushing.Run:
npm testnpm run lintnpm run buildExpected first useful routes:
/api/water/overview/api/water/counties/[slug]src/lib/water/fema-nfhl.ts before any polygon-heavy ingest.fetchNfhlServiceMetadata()normalizeNfhlServiceMetadata(...)extractCountyRelevantNfhlLayers(...)buildNfhlLayerQueryUrl(...)fetchNfhlDiscoveryBundle()buildTexasPoliticalJurisdictionsQueryUrl(limit?)normalizeNfhlPoliticalJurisdictionsResponse(...)fetchTexasNfhlPoliticalJurisdictions(limit?)Political Jurisdictions (layer 22)Levees (layer 23)Water Lines (layer 20)Political Jurisdictions:
where=ST_FIPS='48'outFields=OBJECTID,DFIRM_ID,POL_NAME1,POL_NAME2,POL_NAME3,CO_FIPS,ST_FIPS,COMM_NO,CIDreturnGeometry=falseresultRecordCount=<limit>Levees:
where=DFIRM_ID LIKE '48%'outFields=OBJECTID,DFIRM_ID,LEVEE_ID,LEVEE_NM,LEVEE_TYP,WTR_NM,LEVEE_STAT,OWNER,DISTRICTreturnGeometry=falseresultRecordCount=<limit>src/app/api/water/fema/nfhl/route.tssrc/app/api/water/fema/nfhl/political-jurisdictions/route.tssrc/app/api/water/fema/nfhl/levees/route.tssrc/app/api/water/fema/nfhl/counties/route.ts/api/water/fema/nfhl returns normalized metadata plus county-relevant layers/api/water/fema/nfhl/political-jurisdictions?limit=N returns the first live Texas jurisdiction slice/api/water/fema/nfhl/levees?limit=N returns the first live Texas levee slice/api/water/fema/nfhl/levees?county=<slug> filters levees by Atlas county using NFHL political-jurisdiction dfirmIds; this is a practical first county filter before polygon math/api/water/fema/nfhl/counties returns Atlas county joins built from political jurisdictionswhereoutFieldsreturnGeometryresultRecordCountf=pjsonPOL_NAME1/2/3, CO_FIPS, ST_FIPS, COMM_NO, and CID; layer 23 currently exposes LEVEE_ID, LEVEE_NM, LEVEE_TYP, WTR_NM, LEVEE_STAT, OWNER, and DISTRICT.ST_FIPS + CO_FIPS, padding CO_FIPS to 3 digits, then resolving that full FIPS through county-lookup.ts.opengbra-gbra.hub.arcgis.com), Hydrolakes, water-quality and Clean Rivers surfacessariverauthority-sara-tx.opendata.arcgis.com), Floodplain Viewer, Water Quality Viewer, Watershed Master Plan Viewer, River Basin Report Carddata.edwardsaquifer.org) and aquifer-conditions surfacesrc/lib/water/gbra-hydrology.tssrc/app/api/water/gbra/hydrology/major-rivers/route.tssrc/app/api/water/gbra/hydrology/gvhs-lakes/route.tstests/gbra-hydrology.test.tstests/gbra-hydrology-routes.test.tshttps://opengbra-gbra.hub.arcgis.com/api/feed/dcat-us/1.1.jsonhttps://services7.arcgis.com/Q6vsXnxTnYcWB7qg/arcgis/rest/services/GBRA_Hydrology/FeatureServer1 = Major Rivers2 = GVHS LakesGbraHydrologyMajorRiver
sourceId: 'gbra-hydrology-major-rivers'objectId from OBJECTIDname from GNIS_Namemiles from MilesshapeLength from Shape__LengthGbraHydrologyLake
sourceId: 'gbra-hydrology-gvhs-lakes'objectId from OBJECTIDname from NAMEareaAcres from AREAshapeArea from Shape__AreashapeLength from Shape__Length/api/water/gbra/hydrology/major-rivers returns { sourceId, featureCount, rivers, freshness }/api/water/gbra/hydrology/gvhs-lakes returns { sourceId, featureCount, lakes, freshness }?name= and filter case-insensitively on the normalized name fieldsrc/lib/water/water-source-registry.tssrc/lib/water/freshness.tstests/water-source-registry.test.tsapi/v3/datasets endpoint can return noisy cross-tenant/public datasets that are not actually GBRA-specific enough to trust as your first selector./api/v3/datasets to the domain DCAT feed and then hit the discovered FeatureServer directly.d27bbbc66f8e448e8505ac14742c83fahttps://services7.arcgis.com/Q6vsXnxTnYcWB7qg/ArcGIS/rest/services/Water_Quality_Sample_Stations/FeatureServer0 = CRP Water Quality Monitoring Sites (2019)1 = Surface Water Quality Monitoring Stations (TCEQ)(2019)https://www.gbra.org/environmental/water-quality/sites/<county>/https://waterservices.gbra.org/crp/*.csvhttps://waterservices.gbra.org/crp/*.xlshttps://www.gbra.org/environmental/water-quality/sites/hays/https://waterservices.gbra.org/crp/12672.csvLast-Modified was current in 2026 while ArcGIS metadata was still stalestationId.csv alone200, others 404Guadalupe River Basin Surface Water Quality Monitoring Program GBRA Monitoring LocationsGuadalupe River Basin Surface Water Quality Monitoring Program TCEQ Monitoring Locations<tr id="<stationId>"> rows and table cells rather than trying to infer data from proseCollect Date,Collect Time,Parameter,Reported Result,Units,Parameter CodecollectedAtparameterreportedResultunitsparameterCodestationName/api/water/gbra/quality/sites/api/water/gbra/quality/sites/[stationId]/api/water/gbra/quality/sites/[stationId]/observationsfetchGbraWaterQualitySite() re-fetches county pages through fetchGbraWaterQualitySites(), so mocked fetch sequences must include the county-page responses again before the CSV responsegetCountyBySlugOrName() can return slugs like hays-county; normalize them before storing water-quality site countySlug values so API/tests stay on Atlas short slugs like haysdata|map|dashboard|quality|flood|rain|level|flow|arcgis|onerain|monitor.browser_navigate + browser_console to enumerate links in-page.