Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 0 additions & 25 deletions pipeline/fetch_mvum.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,31 +30,6 @@
PAGE_SIZE = 1000
DATA_DIR = Path(__file__).resolve().parent.parent / "data"

# Attribute fields we keep. Includes display fields, the per-vehicle-class yes/no
# permission flags, and their seasonal `*_datesopen` companions.
OUT_FIELDS = ",".join(
[
# identity / display
"name", "id", "forestname", "districtname",
"surfacetype", "operationalmaintlevel", "symbol", "mvum_symbol_name",
"seasonal", "gis_miles",
# vehicle-class permissions
"passengervehicle", "highclearancevehicle", "truck", "bus", "motorhome",
"fourwd_gt50inches", "twowd_gt50inches",
"tracked_ohv_gt50inches", "other_ohv_gt50inches",
"atv", "motorcycle", "otherwheeled_ohv",
"tracked_ohv_lt50inches", "other_ohv_lt50inches",
"e_bike_class1", "e_bike_class2", "e_bike_class3",
# seasonal date windows
"passengervehicle_datesopen", "highclearancevehicle_datesopen",
"truck_datesopen", "bus_datesopen", "motorhome_datesopen",
"fourwd_gt50_datesopen", "twowd_gt50_datesopen",
"tracked_ohv_gt50_datesopen", "other_ohv_gt50_datesopen",
"atv_datesopen", "motorcycle_datesopen", "otherwheeled_ohv_datesopen",
"tracked_ohv_lt50_datesopen", "other_ohv_lt50_datesopen",
]
)


def _query_page(client: httpx.Client, layer: int, where: str, offset: int) -> dict:
"""One page of a layer query as GeoJSON, with transfer-limit info."""
Expand Down
14 changes: 10 additions & 4 deletions web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@
content="Statewide California National Forest Motor Vehicle Use Map (MVUM): roads and trails open to motor vehicles by class and season, with live wildfire, smoke, and snow overlays."
/>

<!-- Open Graph / social. Update og:url to the real deploy URL on launch.
og:image intentionally omitted for now — add a hosted share image (follow-up). -->
<!-- Open Graph / social. social.png is a copy of docs/screenshot.png (1440×813). -->
<meta property="og:type" content="website" />
<meta property="og:url" content="https://example.com/" />
<meta property="og:url" content="https://ca-mvum.typearson.dev/" />
<meta
property="og:title"
content="California MVUM — motor vehicle routes, live fire / smoke / snow"
Expand All @@ -23,7 +22,12 @@
property="og:description"
content="Statewide California National Forest Motor Vehicle Use Map (MVUM): roads and trails open to motor vehicles by class and season, with live wildfire, smoke, and snow overlays."
/>
<meta name="twitter:card" content="summary" />
<meta property="og:image" content="https://ca-mvum.typearson.dev/social.png" />
<meta
property="og:image:alt"
content="Map of California National Forest motor-vehicle routes with the open network drawn in purple"
/>
<meta name="twitter:card" content="summary_large_image" />
<meta
name="twitter:title"
content="California MVUM — motor vehicle routes, live fire / smoke / snow"
Expand All @@ -32,6 +36,7 @@
name="twitter:description"
content="Statewide California National Forest Motor Vehicle Use Map (MVUM): roads and trails open to motor vehicles by class and season, with live wildfire, smoke, and snow overlays."
/>
<meta name="twitter:image" content="https://ca-mvum.typearson.dev/social.png" />
</head>
<body>
<div id="map" aria-label="Map of California National Forest motor-vehicle routes"></div>
Expand Down Expand Up @@ -81,6 +86,7 @@ <h1>California MVUM</h1>
<p id="fire-status" class="status" role="status" aria-live="polite"></p>
<p id="smoke-status" class="status" role="status" aria-live="polite"></p>
<p id="aqi-status" class="status" role="status" aria-live="polite"></p>
<p id="snow-status" class="status" role="status" aria-live="polite"></p>
</fieldset>

<div class="legend">
Expand Down
Binary file added web/public/social.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 15 additions & 6 deletions web/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ const style: maplibregl.StyleSpecification = {
tiles: ["https://basemap.nationalmap.gov/arcgis/rest/services/USGSTopo/MapServer/tile/{z}/{y}/{x}"],
attribution: "USGS The National Map",
},
// The "routes" vector source is added in map.on("load") once the in-memory
// PMTiles archive (archiveReady) is registered with the protocol — see above.
// The "routes" vector source is added in map.on("load"); PMTiles fetches
// tiles lazily over HTTP range requests — see the protocol setup above.
},
layers: [
{
Expand Down Expand Up @@ -92,6 +92,7 @@ const snowToggle = $("layer-snow") as HTMLInputElement;
const fireStatus = $("fire-status") as HTMLParagraphElement;
const smokeStatus = $("smoke-status") as HTMLParagraphElement;
const aqiStatus = $("aqi-status") as HTMLParagraphElement;
const snowStatus = $("snow-status") as HTMLParagraphElement;

// Grouped selector: Street-legal (plated) vs Off-road only (green/red sticker).
const groups = new Map<string, HTMLOptGroupElement>();
Expand Down Expand Up @@ -176,9 +177,12 @@ async function toggleAqi(on: boolean): Promise<void> {
try {
const worst = await refreshAqi(map);
const cat = AQI_CATEGORIES.find((c) => c.code === worst);
aqiStatus.textContent = worst <= 1
? "Air quality: Good across California right now"
: `Air quality reaches “${cat?.label ?? "elevated"}” somewhere in California today`;
aqiStatus.textContent =
worst === 0
? "No AirNow air-quality data for California right now"
: worst === 1
? "Air quality: Good across California right now"
: `Air quality reaches “${cat?.label ?? "elevated"}” somewhere in California today`;
} catch (e) {
aqiStatus.textContent = "Couldn't load air quality — try again later";
console.error(e);
Expand All @@ -188,7 +192,12 @@ async function toggleAqi(on: boolean): Promise<void> {
fireToggle.addEventListener("change", () => void toggleFire(fireToggle.checked));
smokeToggle.addEventListener("change", () => void toggleSmoke(smokeToggle.checked));
aqiToggle.addEventListener("change", () => void toggleAqi(aqiToggle.checked));
snowToggle.addEventListener("change", () => setSnowVisible(map, snowToggle.checked));
snowToggle.addEventListener("change", () => {
setSnowVisible(map, snowToggle.checked);
snowStatus.textContent = snowToggle.checked
? "Showing modeled snow depth (NOHRSC) — darker = deeper; verify locally"
: "";
});
vehicleSel.addEventListener("change", applyFilters);
dateInput.addEventListener("change", applyFilters);
hideClosed.addEventListener("change", applyFilters);
Expand Down
Loading