@urbankitstudio/atlas 0.6.7 → 0.6.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -76,7 +76,7 @@ For single-address owner lookups in the browser, the free [Owner Lookup](https:/
76
76
 
77
77
  | Function | Returns |
78
78
  |---|---|
79
- | `listStates()` | `StateIndexEntry[]` — all 50 states + `populated` flag |
79
+ | `listStates()` | `StateIndexEntry[]` — all 50 states and DC + `populated` flag |
80
80
  | `findState(stateSlug)` | `StateFile \| undefined` |
81
81
  | `findCounty(stateSlug, countySlug)` | `CountyRecord \| undefined` |
82
82
  | `findCountyByFips(fips)` | `CountyRecord \| undefined` — match by 5-digit county FIPS |
@@ -134,9 +134,9 @@ Omit `?fips=` to get every tracked county in one call.
134
134
 
135
135
  ## Coverage today
136
136
 
137
- The atlas bundles **233 counties across all 50 US states** (245 verified endpoints), covering the largest counties in each. Call `listStates()` to enumerate the full set.
137
+ The atlas bundles **235 counties across all 50 US states and DC** (247 verified endpoints), covering the largest counties in each. Call `listStates()` to enumerate the full set.
138
138
 
139
- Every state has at least one county on record, and 227 of the 233 carry a verified endpoint. The other 6 have `hasPublicRest: false` and an empty `endpoints` array, with `notes` recording the reason and who to contact. Those reasons vary: a subscription-only regional GIS partner, a statewide server that requires an auth token, a state with no county-level parcel authority, a county viewer with no public query API, a county that does not publish owner names online. They ship rather than being omitted, so `findCounty()` still resolves them. **Check `hasPublicRest`** rather than assuming every county has an endpoint; `totals.countiesWithEndpoint` gives the queryable count directly.
139
+ Every state has at least one county on record, and 229 of the 235 carry a verified endpoint. The other 6 have `hasPublicRest: false` and an empty `endpoints` array, with `notes` recording the reason and who to contact. Those reasons vary: a subscription-only regional GIS partner, a statewide server that requires an auth token, a state with no county-level parcel authority, a county viewer with no public query API, a county that does not publish owner names online. They ship rather than being omitted, so `findCounty()` still resolves them. **Check `hasPublicRest`** rather than assuming every county has an endpoint; `totals.countiesWithEndpoint` gives the queryable count directly.
140
140
 
141
141
  Counties are added as their public REST endpoints are verified. Package versions bump when data refreshes — pin to a minor range (`^0.x`) to receive new counties without breaking changes.
142
142
 
@@ -0,0 +1,52 @@
1
+ {
2
+ "stateSlug": "district-of-columbia",
3
+ "stateName": "District of Columbia",
4
+ "stateAbbrev": "DC",
5
+ "lastUpdated": "2026-09-26",
6
+ "counties": [
7
+ {
8
+ "id": "dc-district-of-columbia",
9
+ "state": "DC",
10
+ "stateName": "District of Columbia",
11
+ "stateSlug": "district-of-columbia",
12
+ "county": "District of Columbia",
13
+ "countySlug": "district-of-columbia",
14
+ "countyFips": "11001",
15
+ "hasPublicRest": true,
16
+ "endpoints": [
17
+ {
18
+ "url": "https://maps2.dcgis.dc.gov/dcgis/rest/services/DCGIS_DATA/Property_and_Land_WebMercator/FeatureServer/40",
19
+ "serviceType": "FeatureServer",
20
+ "layerIndex": 40,
21
+ "layerName": "Owner Polygons (Common Ownership Layer)",
22
+ "supportsQuery": true,
23
+ "corsEnabled": true,
24
+ "searchFields": [
25
+ { "name": "SSL", "label": "Square, Suffix, Lot (Parcel ID)", "searchable": true },
26
+ { "name": "OWNERNAME", "label": "Owner Name", "searchable": true },
27
+ { "name": "CAREOFNAME", "label": "Care Of Name", "searchable": false },
28
+ { "name": "PREMISEADD", "label": "Premise (Situs) Address", "searchable": true },
29
+ { "name": "ADDRESS1", "label": "Owner Mailing Address", "searchable": true },
30
+ { "name": "ADDRESS2", "label": "Owner Mailing Address 2", "searchable": false },
31
+ { "name": "CITYSTZIP", "label": "Owner Mailing City/State/ZIP", "searchable": true },
32
+ { "name": "USECODE", "label": "Use Code", "searchable": false },
33
+ { "name": "LANDAREA", "label": "Land Area", "searchable": false },
34
+ { "name": "ASSESSMENT", "label": "Assessment", "searchable": false }
35
+ ],
36
+ "sampleQuery": "https://maps2.dcgis.dc.gov/dcgis/rest/services/DCGIS_DATA/Property_and_Land_WebMercator/FeatureServer/40/query?where=OWNERNAME%20LIKE%20'SMITH%25'&outFields=SSL,OWNERNAME,PREMISEADD,ADDRESS1,CITYSTZIP&returnGeometry=false&f=json&resultRecordCount=10",
37
+ "license": "open-data",
38
+ "licenseUrl": "https://creativecommons.org/licenses/by/4.0/",
39
+ "status": "live",
40
+ "lastVerified": "2026-09-26",
41
+ "verifiedBy": "manual"
42
+ }
43
+ ],
44
+ "contact": {
45
+ "department": "DC Office of the Chief Technology Officer (OCTO) GIS and Office of the Surveyor; data attributed daily from the Office of Tax and Revenue's Real Property Tax Administration (RPTA) Integrated Tax System Public Extract (ITSPE)",
46
+ "url": "https://opendata.dc.gov/datasets/DCGIS::common-ownership-lots",
47
+ "email": null
48
+ },
49
+ "notes": "The District of Columbia is one county-equivalent (FIPS 11001) with no counties inside it. Layer 40, Owner Polygons (Common Ownership Layer), is the District's general ownership layer: 137,400 lot polygons merged from the Record, Tax, Parcel, Reservation and Air Rights lot layers and regenerated daily from the Office of Tax and Revenue's Integrated Tax System Public Extract (ITSPE). Layers 49 (District Land) and 50 (Federal Land) on the same service are narrower views of it. The parcel ID is the SSL (square, suffix, lot), written either as 'SQUARE SUFFIX LOT' (e.g. '1929 7056') or as 'PAR NNNNNNNN' for Parcel-type lots; both answer an SSL LIKE prefix search. The owner mailing address (ADDRESS1, ADDRESS2, CITYSTZIP) is separate from the premise address (PREMISEADD). Verified 2026-09-26: OWNERNAME LIKE 'SMITH%' returns 939 lots, and a PREMISEADD search returns individual homeowners alongside institutions.\n\nCoverage: the layer maps land, one polygon per lot. A condominium building is a single lot on it, and 3,921 of its 4,142 condominium lots carry no owner name, so an owner search finds lot owners, not unit owners. The tax extract published on the same service lists 221,622 records; unit-level condominium data sits in separate tables there, which this layer does not join. The service's ArcGIS Online item (Common Ownership Lots, item 1f6708b1f3774306bef2fa81e612a725, owner DCGISopendata) licenses the data under Creative Commons Attribution 4.0 International, so reuse credits the District of Columbia; the District's open-data terms apply CC0 only where no other license is noted, and this item notes one. OTR's Real Property Public Extract is a different product: a bulk file restricted to mortgage companies."
50
+ }
51
+ ]
52
+ }
package/data/index.json CHANGED
@@ -2,10 +2,10 @@
2
2
  "version": "0.3.0",
3
3
  "lastUpdated": "2026-09-26",
4
4
  "totals": {
5
- "states": 50,
6
- "counties": 233,
7
- "endpoints": 245,
8
- "countiesWithEndpoint": 227,
5
+ "states": 51,
6
+ "counties": 235,
7
+ "endpoints": 247,
8
+ "countiesWithEndpoint": 229,
9
9
  "countiesUnprobeable": 1
10
10
  },
11
11
  "states": [
@@ -73,6 +73,14 @@
73
73
  "endpointCount": 1,
74
74
  "populated": true
75
75
  },
76
+ {
77
+ "slug": "district-of-columbia",
78
+ "name": "District of Columbia",
79
+ "abbrev": "DC",
80
+ "countyCount": 1,
81
+ "endpointCount": 1,
82
+ "populated": true
83
+ },
76
84
  {
77
85
  "slug": "florida",
78
86
  "name": "Florida",
@@ -285,8 +293,8 @@
285
293
  "slug": "ohio",
286
294
  "name": "Ohio",
287
295
  "abbrev": "OH",
288
- "countyCount": 7,
289
- "endpointCount": 7,
296
+ "countyCount": 8,
297
+ "endpointCount": 8,
290
298
  "populated": true
291
299
  },
292
300
  {
@@ -26,21 +26,17 @@
26
26
  { "name": "ALTPARNO", "label": "Alternate Parcel Number", "searchable": true },
27
27
  { "name": "PPIN", "label": "PPIN", "searchable": true },
28
28
  { "name": "OWNNAME", "label": "Owner Name", "searchable": true },
29
- { "name": "MAILADD1", "label": "Mailing Address 1", "searchable": false },
30
- { "name": "MCITY1", "label": "Mailing City 1", "searchable": false },
31
- { "name": "MSTATE1", "label": "Mailing State 1", "searchable": false },
32
- { "name": "MZIP1", "label": "Mailing ZIP 1", "searchable": false },
33
29
  { "name": "SITEADD", "label": "Site Address", "searchable": true },
34
30
  { "name": "SCITY", "label": "Site City", "searchable": false },
35
31
  { "name": "SSTATE", "label": "Site State", "searchable": false },
36
32
  { "name": "SZIP", "label": "Site ZIP", "searchable": false },
37
33
  { "name": "SUBNAME", "label": "Subdivision Name", "searchable": false }
38
34
  ],
39
- "sampleQuery": "https://opcgis.deq.state.ms.us/opcgis/rest/services/Government/HINDS_PARCELS/MapServer/0/query?where=UPPER(OWNNAME)+LIKE+UPPER('%25SMITH%25')&outFields=PARNO,OWNNAME,MAILADD1,SITEADD,SCITY&returnGeometry=false&f=json&resultRecordCount=10",
35
+ "sampleQuery": "https://opcgis.deq.state.ms.us/opcgis/rest/services/Government/HINDS_PARCELS/MapServer/0/query?where=UPPER(OWNNAME)+LIKE+UPPER('%25SMITH%25')&outFields=*&returnGeometry=false&f=json&resultRecordCount=10",
40
36
  "license": "public",
41
37
  "licenseUrl": "https://www.gis.ms.gov/",
42
38
  "status": "live",
43
- "lastVerified": "2026-05-15",
39
+ "lastVerified": "2026-09-26",
44
40
  "verifiedBy": "manual"
45
41
  }
46
42
  ],
@@ -49,7 +45,7 @@
49
45
  "url": "https://www.gis.ms.gov/",
50
46
  "email": null
51
47
  },
52
- "notes": "Hinds County (Jackson, pop. 231,000; state capital) parcel layer hosted on MDEQ OPCGIS server. Mississippi DEQ hosts parcel layers for many MS counties under the 'Government' folder on opcgis.deq.state.ms.us. 20 fields confirmed: OBJECTID, CAMA, PARNO, ALTPARNO, PPIN, OWNNAME, MAILADD1/2, MCITY1/2, MSTATE1/2, MZIP1/2, SITEADD, SCITY, SSTATE, SZIP, SUBNAME. OWNNAME field returns owner name in mixed format. Verified 2026-05-15: SMITH returns Jackson MS addresses. The same server also has DeSoto County parcels and other MS county datasets."
48
+ "notes": "Hinds County (Jackson, pop. 231,000; state capital) parcel layer hosted on MDEQ OPCGIS server. Mississippi DEQ hosts parcel layers for many MS counties under the 'Government' folder on opcgis.deq.state.ms.us. The layer publishes 54 fields: OBJECTID, CAMA, PARNO, ALTPARNO, PPIN, OWNNAME, MAILADD1/2, MCITY1/2, MSTATE1/2, MZIP1/2, SITEADD, SCITY, SSTATE, SZIP, SUBNAME, deed and plat references, assessed values, acreage, ZONING, LEGLDESC and geometry measures. OWNNAME field returns owner name in mixed format. Verified 2026-05-15: SMITH returns Jackson MS site addresses. The same server also has DeSoto County parcels and other MS county datasets. 2026-09-26: the layer now refuses any query that names its outFields (HTTP 200 carrying error 400 \"Failed to execute query.\", measured twice each on the enrichment, radius and liveness query shapes) and answers outFields=* with 54 fields, so every UrbanKit query to this service sends outFields=* and the sample query above does the same. Measured the same day with returnCountOnly: MAILADD1, MAILADD2, MCITY1, MSTATE1 and MZIP1 are blank on every one of the layer's 114,814 parcels (0 rows each where the column IS NOT NULL AND <> '', against 114,547 for OWNNAME and 114,514 for SITEADD), so the record lists no mailing field and this county serves owner names and site addresses, not mailing addresses."
53
49
  },
54
50
  {
55
51
  "id": "ms-desoto",
package/data/ohio.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "stateSlug": "ohio",
3
3
  "stateName": "Ohio",
4
4
  "stateAbbrev": "OH",
5
- "lastUpdated": "2026-05-15",
5
+ "lastUpdated": "2026-09-26",
6
6
  "counties": [
7
7
  {
8
8
  "id": "oh-montgomery",
@@ -304,6 +304,53 @@
304
304
  "email": null
305
305
  },
306
306
  "notes": "Lucas County, Ohio (Toledo metro, county seat Toledo, pop. ~430K) serves parcels from the Lucas County Auditor's AREIS (Assessment Real Estate Information System) via a hosted FeatureServer. Owner name is owner; the site address is property_address (full street/city/state/zip in one field); mailing is mailing_address; identifiers are assessor_num (8-digit) and parid (7-digit). The county's canonical Cadastre_Dataset FeatureServer (layer 8) carries only lot/block geometry with no owner field -- use OSE_ParcelsAddresses_AREIS for owner-name queries. Owner search uses UPPER(owner) LIKE. Verified live 2026-05-30 (owner = MARTRE TAMERA L & BILL)."
307
+ },
308
+ {
309
+ "id": "oh-mahoning",
310
+ "state": "OH",
311
+ "stateName": "Ohio",
312
+ "stateSlug": "ohio",
313
+ "county": "Mahoning",
314
+ "countySlug": "mahoning-county",
315
+ "countyFips": "39099",
316
+ "hasPublicRest": true,
317
+ "endpoints": [
318
+ {
319
+ "url": "https://gisapp.mahoningcountyoh.gov/arcgis/rest/services/PUBLIC_WEBSITE_CADASTRAL/MapServer/2",
320
+ "serviceType": "MapServer",
321
+ "layerIndex": 2,
322
+ "layerName": "PROPERTY BOUNDARIES",
323
+ "supportsQuery": true,
324
+ "corsEnabled": true,
325
+ "searchFields": [
326
+ { "name": "PARCEL_ID", "label": "Parcel ID", "searchable": true },
327
+ { "name": "OWNNAME1", "label": "Owner Name 1", "searchable": true },
328
+ { "name": "OWNNAME2", "label": "Owner Name 2", "searchable": true },
329
+ { "name": "MVP_ADDRESS", "label": "Site Address", "searchable": true },
330
+ { "name": "LOCSTREET", "label": "Site Street Name", "searchable": true },
331
+ { "name": "LOCCITY", "label": "Site City", "searchable": true },
332
+ { "name": "LOCZIP", "label": "Site ZIP", "searchable": true },
333
+ { "name": "MAIL_ADDRESS", "label": "Owner Mailing Address", "searchable": true },
334
+ { "name": "MAILCITY", "label": "Owner Mailing City", "searchable": true },
335
+ { "name": "MAILSTATE", "label": "Owner Mailing State", "searchable": false },
336
+ { "name": "MAILZIP", "label": "Owner Mailing ZIP", "searchable": false },
337
+ { "name": "LANDUSE", "label": "Land Use Code", "searchable": false },
338
+ { "name": "ACRES", "label": "Acres", "searchable": false }
339
+ ],
340
+ "sampleQuery": "https://gisapp.mahoningcountyoh.gov/arcgis/rest/services/PUBLIC_WEBSITE_CADASTRAL/MapServer/2/query?where=UPPER(OWNNAME1)%20LIKE%20UPPER('%25SMITH%25')&outFields=*&returnGeometry=false&f=json&resultRecordCount=10",
341
+ "license": "unknown",
342
+ "licenseUrl": "https://www.mahoningcountyoh.gov/161/GIS",
343
+ "status": "live",
344
+ "lastVerified": "2026-09-26",
345
+ "verifiedBy": "manual"
346
+ }
347
+ ],
348
+ "contact": {
349
+ "department": "Mahoning County GIS",
350
+ "url": "https://www.mahoningcountyoh.gov/161/GIS",
351
+ "email": null
352
+ },
353
+ "notes": "Mahoning County (county seat Youngstown) publishes its parcels as layer 2 'PROPERTY BOUNDARIES' of the PUBLIC_WEBSITE_CADASTRAL MapServer on its own ArcGIS Server. The layer carries PARCEL_ID, owner names OWNNAME1 to OWNNAME3, the site address (MVP_ADDRESS combined, LOC* components), the owner mailing address (MAIL_ADDRESS combined, MAIL* components), a separate tax-bill mailing block (TAX*), land use, market values and the last sale. SERVER QUIRK: any query that names specific outFields fails with HTTP 400 'Failed to execute query.', and only outFields=* succeeds, so a client must request every field and pick columns out of the response. Measured across seven request variants on 2026-09-25 and confirmed again on 2026-09-26. CORS reflects the request's Origin. Re-verified 2026-09-26: the layer holds 160,722 parcels and an owner-name query returned live rows. The county's GIS page describes its maps as informational only and not suitable for legal, engineering or surveying use; no open-data license is stated."
307
354
  }
308
355
  ]
309
356
  }
package/dist/index.cjs CHANGED
@@ -17,10 +17,10 @@ var data_default = {
17
17
  version: "0.3.0",
18
18
  lastUpdated: "2026-09-26",
19
19
  totals: {
20
- states: 50,
21
- counties: 233,
22
- endpoints: 245,
23
- countiesWithEndpoint: 227,
20
+ states: 51,
21
+ counties: 235,
22
+ endpoints: 247,
23
+ countiesWithEndpoint: 229,
24
24
  countiesUnprobeable: 1
25
25
  },
26
26
  states: [
@@ -88,6 +88,14 @@ var data_default = {
88
88
  endpointCount: 1,
89
89
  populated: true
90
90
  },
91
+ {
92
+ slug: "district-of-columbia",
93
+ name: "District of Columbia",
94
+ abbrev: "DC",
95
+ countyCount: 1,
96
+ endpointCount: 1,
97
+ populated: true
98
+ },
91
99
  {
92
100
  slug: "florida",
93
101
  name: "Florida",
@@ -300,8 +308,8 @@ var data_default = {
300
308
  slug: "ohio",
301
309
  name: "Ohio",
302
310
  abbrev: "OH",
303
- countyCount: 7,
304
- endpointCount: 7,
311
+ countyCount: 8,
312
+ endpointCount: 8,
305
313
  populated: true
306
314
  },
307
315
  {
@@ -3119,6 +3127,60 @@ var delaware_default = {
3119
3127
  ]
3120
3128
  };
3121
3129
 
3130
+ // data/district-of-columbia.json
3131
+ var district_of_columbia_default = {
3132
+ stateSlug: "district-of-columbia",
3133
+ stateName: "District of Columbia",
3134
+ stateAbbrev: "DC",
3135
+ lastUpdated: "2026-09-26",
3136
+ counties: [
3137
+ {
3138
+ id: "dc-district-of-columbia",
3139
+ state: "DC",
3140
+ stateName: "District of Columbia",
3141
+ stateSlug: "district-of-columbia",
3142
+ county: "District of Columbia",
3143
+ countySlug: "district-of-columbia",
3144
+ countyFips: "11001",
3145
+ hasPublicRest: true,
3146
+ endpoints: [
3147
+ {
3148
+ url: "https://maps2.dcgis.dc.gov/dcgis/rest/services/DCGIS_DATA/Property_and_Land_WebMercator/FeatureServer/40",
3149
+ serviceType: "FeatureServer",
3150
+ layerIndex: 40,
3151
+ layerName: "Owner Polygons (Common Ownership Layer)",
3152
+ supportsQuery: true,
3153
+ corsEnabled: true,
3154
+ searchFields: [
3155
+ { name: "SSL", label: "Square, Suffix, Lot (Parcel ID)", searchable: true },
3156
+ { name: "OWNERNAME", label: "Owner Name", searchable: true },
3157
+ { name: "CAREOFNAME", label: "Care Of Name", searchable: false },
3158
+ { name: "PREMISEADD", label: "Premise (Situs) Address", searchable: true },
3159
+ { name: "ADDRESS1", label: "Owner Mailing Address", searchable: true },
3160
+ { name: "ADDRESS2", label: "Owner Mailing Address 2", searchable: false },
3161
+ { name: "CITYSTZIP", label: "Owner Mailing City/State/ZIP", searchable: true },
3162
+ { name: "USECODE", label: "Use Code", searchable: false },
3163
+ { name: "LANDAREA", label: "Land Area", searchable: false },
3164
+ { name: "ASSESSMENT", label: "Assessment", searchable: false }
3165
+ ],
3166
+ sampleQuery: "https://maps2.dcgis.dc.gov/dcgis/rest/services/DCGIS_DATA/Property_and_Land_WebMercator/FeatureServer/40/query?where=OWNERNAME%20LIKE%20'SMITH%25'&outFields=SSL,OWNERNAME,PREMISEADD,ADDRESS1,CITYSTZIP&returnGeometry=false&f=json&resultRecordCount=10",
3167
+ license: "open-data",
3168
+ licenseUrl: "https://creativecommons.org/licenses/by/4.0/",
3169
+ status: "live",
3170
+ lastVerified: "2026-09-26",
3171
+ verifiedBy: "manual"
3172
+ }
3173
+ ],
3174
+ contact: {
3175
+ department: "DC Office of the Chief Technology Officer (OCTO) GIS and Office of the Surveyor; data attributed daily from the Office of Tax and Revenue's Real Property Tax Administration (RPTA) Integrated Tax System Public Extract (ITSPE)",
3176
+ url: "https://opendata.dc.gov/datasets/DCGIS::common-ownership-lots",
3177
+ email: null
3178
+ },
3179
+ notes: "The District of Columbia is one county-equivalent (FIPS 11001) with no counties inside it. Layer 40, Owner Polygons (Common Ownership Layer), is the District's general ownership layer: 137,400 lot polygons merged from the Record, Tax, Parcel, Reservation and Air Rights lot layers and regenerated daily from the Office of Tax and Revenue's Integrated Tax System Public Extract (ITSPE). Layers 49 (District Land) and 50 (Federal Land) on the same service are narrower views of it. The parcel ID is the SSL (square, suffix, lot), written either as 'SQUARE SUFFIX LOT' (e.g. '1929 7056') or as 'PAR NNNNNNNN' for Parcel-type lots; both answer an SSL LIKE prefix search. The owner mailing address (ADDRESS1, ADDRESS2, CITYSTZIP) is separate from the premise address (PREMISEADD). Verified 2026-09-26: OWNERNAME LIKE 'SMITH%' returns 939 lots, and a PREMISEADD search returns individual homeowners alongside institutions.\n\nCoverage: the layer maps land, one polygon per lot. A condominium building is a single lot on it, and 3,921 of its 4,142 condominium lots carry no owner name, so an owner search finds lot owners, not unit owners. The tax extract published on the same service lists 221,622 records; unit-level condominium data sits in separate tables there, which this layer does not join. The service's ArcGIS Online item (Common Ownership Lots, item 1f6708b1f3774306bef2fa81e612a725, owner DCGISopendata) licenses the data under Creative Commons Attribution 4.0 International, so reuse credits the District of Columbia; the District's open-data terms apply CC0 only where no other license is noted, and this item notes one. OTR's Real Property Public Extract is a different product: a bulk file restricted to mortgage companies."
3180
+ }
3181
+ ]
3182
+ };
3183
+
3122
3184
  // data/florida.json
3123
3185
  var florida_default = {
3124
3186
  stateSlug: "florida",
@@ -15492,21 +15554,17 @@ var mississippi_default = {
15492
15554
  { name: "ALTPARNO", label: "Alternate Parcel Number", searchable: true },
15493
15555
  { name: "PPIN", label: "PPIN", searchable: true },
15494
15556
  { name: "OWNNAME", label: "Owner Name", searchable: true },
15495
- { name: "MAILADD1", label: "Mailing Address 1", searchable: false },
15496
- { name: "MCITY1", label: "Mailing City 1", searchable: false },
15497
- { name: "MSTATE1", label: "Mailing State 1", searchable: false },
15498
- { name: "MZIP1", label: "Mailing ZIP 1", searchable: false },
15499
15557
  { name: "SITEADD", label: "Site Address", searchable: true },
15500
15558
  { name: "SCITY", label: "Site City", searchable: false },
15501
15559
  { name: "SSTATE", label: "Site State", searchable: false },
15502
15560
  { name: "SZIP", label: "Site ZIP", searchable: false },
15503
15561
  { name: "SUBNAME", label: "Subdivision Name", searchable: false }
15504
15562
  ],
15505
- sampleQuery: "https://opcgis.deq.state.ms.us/opcgis/rest/services/Government/HINDS_PARCELS/MapServer/0/query?where=UPPER(OWNNAME)+LIKE+UPPER('%25SMITH%25')&outFields=PARNO,OWNNAME,MAILADD1,SITEADD,SCITY&returnGeometry=false&f=json&resultRecordCount=10",
15563
+ sampleQuery: "https://opcgis.deq.state.ms.us/opcgis/rest/services/Government/HINDS_PARCELS/MapServer/0/query?where=UPPER(OWNNAME)+LIKE+UPPER('%25SMITH%25')&outFields=*&returnGeometry=false&f=json&resultRecordCount=10",
15506
15564
  license: "public",
15507
15565
  licenseUrl: "https://www.gis.ms.gov/",
15508
15566
  status: "live",
15509
- lastVerified: "2026-05-15",
15567
+ lastVerified: "2026-09-26",
15510
15568
  verifiedBy: "manual"
15511
15569
  }
15512
15570
  ],
@@ -15515,7 +15573,7 @@ var mississippi_default = {
15515
15573
  url: "https://www.gis.ms.gov/",
15516
15574
  email: null
15517
15575
  },
15518
- notes: "Hinds County (Jackson, pop. 231,000; state capital) parcel layer hosted on MDEQ OPCGIS server. Mississippi DEQ hosts parcel layers for many MS counties under the 'Government' folder on opcgis.deq.state.ms.us. 20 fields confirmed: OBJECTID, CAMA, PARNO, ALTPARNO, PPIN, OWNNAME, MAILADD1/2, MCITY1/2, MSTATE1/2, MZIP1/2, SITEADD, SCITY, SSTATE, SZIP, SUBNAME. OWNNAME field returns owner name in mixed format. Verified 2026-05-15: SMITH returns Jackson MS addresses. The same server also has DeSoto County parcels and other MS county datasets."
15576
+ notes: `Hinds County (Jackson, pop. 231,000; state capital) parcel layer hosted on MDEQ OPCGIS server. Mississippi DEQ hosts parcel layers for many MS counties under the 'Government' folder on opcgis.deq.state.ms.us. The layer publishes 54 fields: OBJECTID, CAMA, PARNO, ALTPARNO, PPIN, OWNNAME, MAILADD1/2, MCITY1/2, MSTATE1/2, MZIP1/2, SITEADD, SCITY, SSTATE, SZIP, SUBNAME, deed and plat references, assessed values, acreage, ZONING, LEGLDESC and geometry measures. OWNNAME field returns owner name in mixed format. Verified 2026-05-15: SMITH returns Jackson MS site addresses. The same server also has DeSoto County parcels and other MS county datasets. 2026-09-26: the layer now refuses any query that names its outFields (HTTP 200 carrying error 400 "Failed to execute query.", measured twice each on the enrichment, radius and liveness query shapes) and answers outFields=* with 54 fields, so every UrbanKit query to this service sends outFields=* and the sample query above does the same. Measured the same day with returnCountOnly: MAILADD1, MAILADD2, MCITY1, MSTATE1 and MZIP1 are blank on every one of the layer's 114,814 parcels (0 rows each where the column IS NOT NULL AND <> '', against 114,547 for OWNNAME and 114,514 for SITEADD), so the record lists no mailing field and this county serves owner names and site addresses, not mailing addresses.`
15519
15577
  },
15520
15578
  {
15521
15579
  id: "ms-desoto",
@@ -18902,7 +18960,7 @@ var ohio_default = {
18902
18960
  stateSlug: "ohio",
18903
18961
  stateName: "Ohio",
18904
18962
  stateAbbrev: "OH",
18905
- lastUpdated: "2026-05-15",
18963
+ lastUpdated: "2026-09-26",
18906
18964
  counties: [
18907
18965
  {
18908
18966
  id: "oh-montgomery",
@@ -19204,6 +19262,53 @@ var ohio_default = {
19204
19262
  email: null
19205
19263
  },
19206
19264
  notes: "Lucas County, Ohio (Toledo metro, county seat Toledo, pop. ~430K) serves parcels from the Lucas County Auditor's AREIS (Assessment Real Estate Information System) via a hosted FeatureServer. Owner name is owner; the site address is property_address (full street/city/state/zip in one field); mailing is mailing_address; identifiers are assessor_num (8-digit) and parid (7-digit). The county's canonical Cadastre_Dataset FeatureServer (layer 8) carries only lot/block geometry with no owner field -- use OSE_ParcelsAddresses_AREIS for owner-name queries. Owner search uses UPPER(owner) LIKE. Verified live 2026-05-30 (owner = MARTRE TAMERA L & BILL)."
19265
+ },
19266
+ {
19267
+ id: "oh-mahoning",
19268
+ state: "OH",
19269
+ stateName: "Ohio",
19270
+ stateSlug: "ohio",
19271
+ county: "Mahoning",
19272
+ countySlug: "mahoning-county",
19273
+ countyFips: "39099",
19274
+ hasPublicRest: true,
19275
+ endpoints: [
19276
+ {
19277
+ url: "https://gisapp.mahoningcountyoh.gov/arcgis/rest/services/PUBLIC_WEBSITE_CADASTRAL/MapServer/2",
19278
+ serviceType: "MapServer",
19279
+ layerIndex: 2,
19280
+ layerName: "PROPERTY BOUNDARIES",
19281
+ supportsQuery: true,
19282
+ corsEnabled: true,
19283
+ searchFields: [
19284
+ { name: "PARCEL_ID", label: "Parcel ID", searchable: true },
19285
+ { name: "OWNNAME1", label: "Owner Name 1", searchable: true },
19286
+ { name: "OWNNAME2", label: "Owner Name 2", searchable: true },
19287
+ { name: "MVP_ADDRESS", label: "Site Address", searchable: true },
19288
+ { name: "LOCSTREET", label: "Site Street Name", searchable: true },
19289
+ { name: "LOCCITY", label: "Site City", searchable: true },
19290
+ { name: "LOCZIP", label: "Site ZIP", searchable: true },
19291
+ { name: "MAIL_ADDRESS", label: "Owner Mailing Address", searchable: true },
19292
+ { name: "MAILCITY", label: "Owner Mailing City", searchable: true },
19293
+ { name: "MAILSTATE", label: "Owner Mailing State", searchable: false },
19294
+ { name: "MAILZIP", label: "Owner Mailing ZIP", searchable: false },
19295
+ { name: "LANDUSE", label: "Land Use Code", searchable: false },
19296
+ { name: "ACRES", label: "Acres", searchable: false }
19297
+ ],
19298
+ sampleQuery: "https://gisapp.mahoningcountyoh.gov/arcgis/rest/services/PUBLIC_WEBSITE_CADASTRAL/MapServer/2/query?where=UPPER(OWNNAME1)%20LIKE%20UPPER('%25SMITH%25')&outFields=*&returnGeometry=false&f=json&resultRecordCount=10",
19299
+ license: "unknown",
19300
+ licenseUrl: "https://www.mahoningcountyoh.gov/161/GIS",
19301
+ status: "live",
19302
+ lastVerified: "2026-09-26",
19303
+ verifiedBy: "manual"
19304
+ }
19305
+ ],
19306
+ contact: {
19307
+ department: "Mahoning County GIS",
19308
+ url: "https://www.mahoningcountyoh.gov/161/GIS",
19309
+ email: null
19310
+ },
19311
+ notes: "Mahoning County (county seat Youngstown) publishes its parcels as layer 2 'PROPERTY BOUNDARIES' of the PUBLIC_WEBSITE_CADASTRAL MapServer on its own ArcGIS Server. The layer carries PARCEL_ID, owner names OWNNAME1 to OWNNAME3, the site address (MVP_ADDRESS combined, LOC* components), the owner mailing address (MAIL_ADDRESS combined, MAIL* components), a separate tax-bill mailing block (TAX*), land use, market values and the last sale. SERVER QUIRK: any query that names specific outFields fails with HTTP 400 'Failed to execute query.', and only outFields=* succeeds, so a client must request every field and pick columns out of the response. Measured across seven request variants on 2026-09-25 and confirmed again on 2026-09-26. CORS reflects the request's Origin. Re-verified 2026-09-26: the layer holds 160,722 parcels and an owner-name query returned live rows. The county's GIS page describes its maps as informational only and not suitable for legal, engineering or surveying use; no open-data license is stated."
19207
19312
  }
19208
19313
  ]
19209
19314
  };
@@ -21837,6 +21942,7 @@ var POPULATED_STATES = {
21837
21942
  colorado: colorado_default,
21838
21943
  connecticut: connecticut_default,
21839
21944
  delaware: delaware_default,
21945
+ "district-of-columbia": district_of_columbia_default,
21840
21946
  florida: florida_default,
21841
21947
  georgia: georgia_default,
21842
21948
  hawaii: hawaii_default,
@@ -21926,10 +22032,10 @@ function listCountiesByState(stateSlug) {
21926
22032
  function slugify(s) {
21927
22033
  return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
21928
22034
  }
22035
+ var COUNTY_UNIT_SUFFIX = /\b(?:County|Parish|Borough|Municipality|Census Area|City|Statewide|Planning Region|District of Columbia)$/i;
21929
22036
  function countySlugFromName(county) {
21930
- const lc = county.toLowerCase();
21931
- const hasSuffix = lc.endsWith(" county") || lc.endsWith(" parish") || lc.endsWith(" borough") || lc.endsWith(" census area");
21932
- return slugify(hasSuffix ? county : `${county} County`);
22037
+ const name = county.trim();
22038
+ return slugify(COUNTY_UNIT_SUFFIX.test(name) ? name : `${name} County`);
21933
22039
  }
21934
22040
  function buildParcelLookupDeepLink(endpoint, base = "https://urbankitstudio.com/tools/parcel-lookup") {
21935
22041
  const params = new URLSearchParams();
package/dist/index.d.cts CHANGED
@@ -218,8 +218,9 @@ declare function findCountyByFips(fips: string): CountyRecord | undefined;
218
218
  declare function findState(stateSlug: string): StateFile | undefined;
219
219
 
220
220
  /**
221
- * List all 50 US states from the atlas index, including those without
222
- * populated county data yet (use the `populated` flag to filter).
221
+ * List all 50 US states and the District of Columbia from the atlas index,
222
+ * including those without populated county data yet (use the `populated` flag
223
+ * to filter).
223
224
  */
224
225
  declare function listStates(): StateIndexEntry[];
225
226
 
package/dist/index.d.ts CHANGED
@@ -218,8 +218,9 @@ declare function findCountyByFips(fips: string): CountyRecord | undefined;
218
218
  declare function findState(stateSlug: string): StateFile | undefined;
219
219
 
220
220
  /**
221
- * List all 50 US states from the atlas index, including those without
222
- * populated county data yet (use the `populated` flag to filter).
221
+ * List all 50 US states and the District of Columbia from the atlas index,
222
+ * including those without populated county data yet (use the `populated` flag
223
+ * to filter).
223
224
  */
224
225
  declare function listStates(): StateIndexEntry[];
225
226
 
package/dist/index.js CHANGED
@@ -15,10 +15,10 @@ var data_default = {
15
15
  version: "0.3.0",
16
16
  lastUpdated: "2026-09-26",
17
17
  totals: {
18
- states: 50,
19
- counties: 233,
20
- endpoints: 245,
21
- countiesWithEndpoint: 227,
18
+ states: 51,
19
+ counties: 235,
20
+ endpoints: 247,
21
+ countiesWithEndpoint: 229,
22
22
  countiesUnprobeable: 1
23
23
  },
24
24
  states: [
@@ -86,6 +86,14 @@ var data_default = {
86
86
  endpointCount: 1,
87
87
  populated: true
88
88
  },
89
+ {
90
+ slug: "district-of-columbia",
91
+ name: "District of Columbia",
92
+ abbrev: "DC",
93
+ countyCount: 1,
94
+ endpointCount: 1,
95
+ populated: true
96
+ },
89
97
  {
90
98
  slug: "florida",
91
99
  name: "Florida",
@@ -298,8 +306,8 @@ var data_default = {
298
306
  slug: "ohio",
299
307
  name: "Ohio",
300
308
  abbrev: "OH",
301
- countyCount: 7,
302
- endpointCount: 7,
309
+ countyCount: 8,
310
+ endpointCount: 8,
303
311
  populated: true
304
312
  },
305
313
  {
@@ -3117,6 +3125,60 @@ var delaware_default = {
3117
3125
  ]
3118
3126
  };
3119
3127
 
3128
+ // data/district-of-columbia.json
3129
+ var district_of_columbia_default = {
3130
+ stateSlug: "district-of-columbia",
3131
+ stateName: "District of Columbia",
3132
+ stateAbbrev: "DC",
3133
+ lastUpdated: "2026-09-26",
3134
+ counties: [
3135
+ {
3136
+ id: "dc-district-of-columbia",
3137
+ state: "DC",
3138
+ stateName: "District of Columbia",
3139
+ stateSlug: "district-of-columbia",
3140
+ county: "District of Columbia",
3141
+ countySlug: "district-of-columbia",
3142
+ countyFips: "11001",
3143
+ hasPublicRest: true,
3144
+ endpoints: [
3145
+ {
3146
+ url: "https://maps2.dcgis.dc.gov/dcgis/rest/services/DCGIS_DATA/Property_and_Land_WebMercator/FeatureServer/40",
3147
+ serviceType: "FeatureServer",
3148
+ layerIndex: 40,
3149
+ layerName: "Owner Polygons (Common Ownership Layer)",
3150
+ supportsQuery: true,
3151
+ corsEnabled: true,
3152
+ searchFields: [
3153
+ { name: "SSL", label: "Square, Suffix, Lot (Parcel ID)", searchable: true },
3154
+ { name: "OWNERNAME", label: "Owner Name", searchable: true },
3155
+ { name: "CAREOFNAME", label: "Care Of Name", searchable: false },
3156
+ { name: "PREMISEADD", label: "Premise (Situs) Address", searchable: true },
3157
+ { name: "ADDRESS1", label: "Owner Mailing Address", searchable: true },
3158
+ { name: "ADDRESS2", label: "Owner Mailing Address 2", searchable: false },
3159
+ { name: "CITYSTZIP", label: "Owner Mailing City/State/ZIP", searchable: true },
3160
+ { name: "USECODE", label: "Use Code", searchable: false },
3161
+ { name: "LANDAREA", label: "Land Area", searchable: false },
3162
+ { name: "ASSESSMENT", label: "Assessment", searchable: false }
3163
+ ],
3164
+ sampleQuery: "https://maps2.dcgis.dc.gov/dcgis/rest/services/DCGIS_DATA/Property_and_Land_WebMercator/FeatureServer/40/query?where=OWNERNAME%20LIKE%20'SMITH%25'&outFields=SSL,OWNERNAME,PREMISEADD,ADDRESS1,CITYSTZIP&returnGeometry=false&f=json&resultRecordCount=10",
3165
+ license: "open-data",
3166
+ licenseUrl: "https://creativecommons.org/licenses/by/4.0/",
3167
+ status: "live",
3168
+ lastVerified: "2026-09-26",
3169
+ verifiedBy: "manual"
3170
+ }
3171
+ ],
3172
+ contact: {
3173
+ department: "DC Office of the Chief Technology Officer (OCTO) GIS and Office of the Surveyor; data attributed daily from the Office of Tax and Revenue's Real Property Tax Administration (RPTA) Integrated Tax System Public Extract (ITSPE)",
3174
+ url: "https://opendata.dc.gov/datasets/DCGIS::common-ownership-lots",
3175
+ email: null
3176
+ },
3177
+ notes: "The District of Columbia is one county-equivalent (FIPS 11001) with no counties inside it. Layer 40, Owner Polygons (Common Ownership Layer), is the District's general ownership layer: 137,400 lot polygons merged from the Record, Tax, Parcel, Reservation and Air Rights lot layers and regenerated daily from the Office of Tax and Revenue's Integrated Tax System Public Extract (ITSPE). Layers 49 (District Land) and 50 (Federal Land) on the same service are narrower views of it. The parcel ID is the SSL (square, suffix, lot), written either as 'SQUARE SUFFIX LOT' (e.g. '1929 7056') or as 'PAR NNNNNNNN' for Parcel-type lots; both answer an SSL LIKE prefix search. The owner mailing address (ADDRESS1, ADDRESS2, CITYSTZIP) is separate from the premise address (PREMISEADD). Verified 2026-09-26: OWNERNAME LIKE 'SMITH%' returns 939 lots, and a PREMISEADD search returns individual homeowners alongside institutions.\n\nCoverage: the layer maps land, one polygon per lot. A condominium building is a single lot on it, and 3,921 of its 4,142 condominium lots carry no owner name, so an owner search finds lot owners, not unit owners. The tax extract published on the same service lists 221,622 records; unit-level condominium data sits in separate tables there, which this layer does not join. The service's ArcGIS Online item (Common Ownership Lots, item 1f6708b1f3774306bef2fa81e612a725, owner DCGISopendata) licenses the data under Creative Commons Attribution 4.0 International, so reuse credits the District of Columbia; the District's open-data terms apply CC0 only where no other license is noted, and this item notes one. OTR's Real Property Public Extract is a different product: a bulk file restricted to mortgage companies."
3178
+ }
3179
+ ]
3180
+ };
3181
+
3120
3182
  // data/florida.json
3121
3183
  var florida_default = {
3122
3184
  stateSlug: "florida",
@@ -15490,21 +15552,17 @@ var mississippi_default = {
15490
15552
  { name: "ALTPARNO", label: "Alternate Parcel Number", searchable: true },
15491
15553
  { name: "PPIN", label: "PPIN", searchable: true },
15492
15554
  { name: "OWNNAME", label: "Owner Name", searchable: true },
15493
- { name: "MAILADD1", label: "Mailing Address 1", searchable: false },
15494
- { name: "MCITY1", label: "Mailing City 1", searchable: false },
15495
- { name: "MSTATE1", label: "Mailing State 1", searchable: false },
15496
- { name: "MZIP1", label: "Mailing ZIP 1", searchable: false },
15497
15555
  { name: "SITEADD", label: "Site Address", searchable: true },
15498
15556
  { name: "SCITY", label: "Site City", searchable: false },
15499
15557
  { name: "SSTATE", label: "Site State", searchable: false },
15500
15558
  { name: "SZIP", label: "Site ZIP", searchable: false },
15501
15559
  { name: "SUBNAME", label: "Subdivision Name", searchable: false }
15502
15560
  ],
15503
- sampleQuery: "https://opcgis.deq.state.ms.us/opcgis/rest/services/Government/HINDS_PARCELS/MapServer/0/query?where=UPPER(OWNNAME)+LIKE+UPPER('%25SMITH%25')&outFields=PARNO,OWNNAME,MAILADD1,SITEADD,SCITY&returnGeometry=false&f=json&resultRecordCount=10",
15561
+ sampleQuery: "https://opcgis.deq.state.ms.us/opcgis/rest/services/Government/HINDS_PARCELS/MapServer/0/query?where=UPPER(OWNNAME)+LIKE+UPPER('%25SMITH%25')&outFields=*&returnGeometry=false&f=json&resultRecordCount=10",
15504
15562
  license: "public",
15505
15563
  licenseUrl: "https://www.gis.ms.gov/",
15506
15564
  status: "live",
15507
- lastVerified: "2026-05-15",
15565
+ lastVerified: "2026-09-26",
15508
15566
  verifiedBy: "manual"
15509
15567
  }
15510
15568
  ],
@@ -15513,7 +15571,7 @@ var mississippi_default = {
15513
15571
  url: "https://www.gis.ms.gov/",
15514
15572
  email: null
15515
15573
  },
15516
- notes: "Hinds County (Jackson, pop. 231,000; state capital) parcel layer hosted on MDEQ OPCGIS server. Mississippi DEQ hosts parcel layers for many MS counties under the 'Government' folder on opcgis.deq.state.ms.us. 20 fields confirmed: OBJECTID, CAMA, PARNO, ALTPARNO, PPIN, OWNNAME, MAILADD1/2, MCITY1/2, MSTATE1/2, MZIP1/2, SITEADD, SCITY, SSTATE, SZIP, SUBNAME. OWNNAME field returns owner name in mixed format. Verified 2026-05-15: SMITH returns Jackson MS addresses. The same server also has DeSoto County parcels and other MS county datasets."
15574
+ notes: `Hinds County (Jackson, pop. 231,000; state capital) parcel layer hosted on MDEQ OPCGIS server. Mississippi DEQ hosts parcel layers for many MS counties under the 'Government' folder on opcgis.deq.state.ms.us. The layer publishes 54 fields: OBJECTID, CAMA, PARNO, ALTPARNO, PPIN, OWNNAME, MAILADD1/2, MCITY1/2, MSTATE1/2, MZIP1/2, SITEADD, SCITY, SSTATE, SZIP, SUBNAME, deed and plat references, assessed values, acreage, ZONING, LEGLDESC and geometry measures. OWNNAME field returns owner name in mixed format. Verified 2026-05-15: SMITH returns Jackson MS site addresses. The same server also has DeSoto County parcels and other MS county datasets. 2026-09-26: the layer now refuses any query that names its outFields (HTTP 200 carrying error 400 "Failed to execute query.", measured twice each on the enrichment, radius and liveness query shapes) and answers outFields=* with 54 fields, so every UrbanKit query to this service sends outFields=* and the sample query above does the same. Measured the same day with returnCountOnly: MAILADD1, MAILADD2, MCITY1, MSTATE1 and MZIP1 are blank on every one of the layer's 114,814 parcels (0 rows each where the column IS NOT NULL AND <> '', against 114,547 for OWNNAME and 114,514 for SITEADD), so the record lists no mailing field and this county serves owner names and site addresses, not mailing addresses.`
15517
15575
  },
15518
15576
  {
15519
15577
  id: "ms-desoto",
@@ -18900,7 +18958,7 @@ var ohio_default = {
18900
18958
  stateSlug: "ohio",
18901
18959
  stateName: "Ohio",
18902
18960
  stateAbbrev: "OH",
18903
- lastUpdated: "2026-05-15",
18961
+ lastUpdated: "2026-09-26",
18904
18962
  counties: [
18905
18963
  {
18906
18964
  id: "oh-montgomery",
@@ -19202,6 +19260,53 @@ var ohio_default = {
19202
19260
  email: null
19203
19261
  },
19204
19262
  notes: "Lucas County, Ohio (Toledo metro, county seat Toledo, pop. ~430K) serves parcels from the Lucas County Auditor's AREIS (Assessment Real Estate Information System) via a hosted FeatureServer. Owner name is owner; the site address is property_address (full street/city/state/zip in one field); mailing is mailing_address; identifiers are assessor_num (8-digit) and parid (7-digit). The county's canonical Cadastre_Dataset FeatureServer (layer 8) carries only lot/block geometry with no owner field -- use OSE_ParcelsAddresses_AREIS for owner-name queries. Owner search uses UPPER(owner) LIKE. Verified live 2026-05-30 (owner = MARTRE TAMERA L & BILL)."
19263
+ },
19264
+ {
19265
+ id: "oh-mahoning",
19266
+ state: "OH",
19267
+ stateName: "Ohio",
19268
+ stateSlug: "ohio",
19269
+ county: "Mahoning",
19270
+ countySlug: "mahoning-county",
19271
+ countyFips: "39099",
19272
+ hasPublicRest: true,
19273
+ endpoints: [
19274
+ {
19275
+ url: "https://gisapp.mahoningcountyoh.gov/arcgis/rest/services/PUBLIC_WEBSITE_CADASTRAL/MapServer/2",
19276
+ serviceType: "MapServer",
19277
+ layerIndex: 2,
19278
+ layerName: "PROPERTY BOUNDARIES",
19279
+ supportsQuery: true,
19280
+ corsEnabled: true,
19281
+ searchFields: [
19282
+ { name: "PARCEL_ID", label: "Parcel ID", searchable: true },
19283
+ { name: "OWNNAME1", label: "Owner Name 1", searchable: true },
19284
+ { name: "OWNNAME2", label: "Owner Name 2", searchable: true },
19285
+ { name: "MVP_ADDRESS", label: "Site Address", searchable: true },
19286
+ { name: "LOCSTREET", label: "Site Street Name", searchable: true },
19287
+ { name: "LOCCITY", label: "Site City", searchable: true },
19288
+ { name: "LOCZIP", label: "Site ZIP", searchable: true },
19289
+ { name: "MAIL_ADDRESS", label: "Owner Mailing Address", searchable: true },
19290
+ { name: "MAILCITY", label: "Owner Mailing City", searchable: true },
19291
+ { name: "MAILSTATE", label: "Owner Mailing State", searchable: false },
19292
+ { name: "MAILZIP", label: "Owner Mailing ZIP", searchable: false },
19293
+ { name: "LANDUSE", label: "Land Use Code", searchable: false },
19294
+ { name: "ACRES", label: "Acres", searchable: false }
19295
+ ],
19296
+ sampleQuery: "https://gisapp.mahoningcountyoh.gov/arcgis/rest/services/PUBLIC_WEBSITE_CADASTRAL/MapServer/2/query?where=UPPER(OWNNAME1)%20LIKE%20UPPER('%25SMITH%25')&outFields=*&returnGeometry=false&f=json&resultRecordCount=10",
19297
+ license: "unknown",
19298
+ licenseUrl: "https://www.mahoningcountyoh.gov/161/GIS",
19299
+ status: "live",
19300
+ lastVerified: "2026-09-26",
19301
+ verifiedBy: "manual"
19302
+ }
19303
+ ],
19304
+ contact: {
19305
+ department: "Mahoning County GIS",
19306
+ url: "https://www.mahoningcountyoh.gov/161/GIS",
19307
+ email: null
19308
+ },
19309
+ notes: "Mahoning County (county seat Youngstown) publishes its parcels as layer 2 'PROPERTY BOUNDARIES' of the PUBLIC_WEBSITE_CADASTRAL MapServer on its own ArcGIS Server. The layer carries PARCEL_ID, owner names OWNNAME1 to OWNNAME3, the site address (MVP_ADDRESS combined, LOC* components), the owner mailing address (MAIL_ADDRESS combined, MAIL* components), a separate tax-bill mailing block (TAX*), land use, market values and the last sale. SERVER QUIRK: any query that names specific outFields fails with HTTP 400 'Failed to execute query.', and only outFields=* succeeds, so a client must request every field and pick columns out of the response. Measured across seven request variants on 2026-09-25 and confirmed again on 2026-09-26. CORS reflects the request's Origin. Re-verified 2026-09-26: the layer holds 160,722 parcels and an owner-name query returned live rows. The county's GIS page describes its maps as informational only and not suitable for legal, engineering or surveying use; no open-data license is stated."
19205
19310
  }
19206
19311
  ]
19207
19312
  };
@@ -21835,6 +21940,7 @@ var POPULATED_STATES = {
21835
21940
  colorado: colorado_default,
21836
21941
  connecticut: connecticut_default,
21837
21942
  delaware: delaware_default,
21943
+ "district-of-columbia": district_of_columbia_default,
21838
21944
  florida: florida_default,
21839
21945
  georgia: georgia_default,
21840
21946
  hawaii: hawaii_default,
@@ -21924,10 +22030,10 @@ function listCountiesByState(stateSlug) {
21924
22030
  function slugify(s) {
21925
22031
  return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
21926
22032
  }
22033
+ var COUNTY_UNIT_SUFFIX = /\b(?:County|Parish|Borough|Municipality|Census Area|City|Statewide|Planning Region|District of Columbia)$/i;
21927
22034
  function countySlugFromName(county) {
21928
- const lc = county.toLowerCase();
21929
- const hasSuffix = lc.endsWith(" county") || lc.endsWith(" parish") || lc.endsWith(" borough") || lc.endsWith(" census area");
21930
- return slugify(hasSuffix ? county : `${county} County`);
22035
+ const name = county.trim();
22036
+ return slugify(COUNTY_UNIT_SUFFIX.test(name) ? name : `${name} County`);
21931
22037
  }
21932
22038
  function buildParcelLookupDeepLink(endpoint, base = "https://urbankitstudio.com/tools/parcel-lookup") {
21933
22039
  const params = new URLSearchParams();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@urbankitstudio/atlas",
3
- "version": "0.6.7",
4
- "description": "JS SDK for the UrbanKit County Parcel REST API Atlas: 233 counties across all 50 US states, 245 verified public ArcGIS REST endpoints for county parcel data, with searchable field metadata, sample queries and license info.",
3
+ "version": "0.6.9",
4
+ "description": "JS SDK for the UrbanKit County Parcel REST API Atlas: 235 counties across all 50 US states and DC, 247 verified public ArcGIS REST endpoints for county parcel data, with searchable field metadata, sample queries and license info.",
5
5
  "keywords": [
6
6
  "parcel",
7
7
  "arcgis",