尚未收集儲存庫資訊。
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
HiveWatch Utah: Wasatch Front air quality and pollen, in plain words. Sister site to Prepare Utah and FaultLine Utah.
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗The air we all share. A calm, plain-language air quality and pollen site for the Wasatch Front (Salt Lake, Davis, Utah and Weber counties, plus Cache, Box Elder, Tooele and Wasatch), at hiveairutah.com. Sister site to Prepare Utah (household readiness) and FaultLine Utah (earthquake hazards by address).
index.html): a newspaper front page, built every 30 minutes from Utah DAQ and EPA AirNow. A headline and deck say how the air is in the four core counties. Under them, a lead (the highest current reading, today's forecast and burn levels, which counties are on watch, and what to do at today's worst level), then a column per county (AQI now, AQI by pollutant, the past 24 hours, 3-day health forecast, burn level, smoke and dust alerts). A rail down the right holds the hand-typed Hive Status line and the four guides.air.html): the AQI in six colors, health level versus action (burn) level, the burn rules, monitors versus sensors versus models, and which forecast covers each county.seasons.html): winter inversions, summer ozone, wildfire smoke, Great Salt Lake dust, who breathes the worst air, what Utah is doing, and common questions written the way people search.pollen.html): the pollen calendar, local plants, how to read a count, where to find a real one, and when to get care.breathe.html): what to do at each level, a clean-air room, filters, masks, timing, schools, and when to get care.about.html): a short note on who makes the site, where the numbers come from, and privacy.It's a plain static site: HTML, CSS and a little JavaScript. One Python script turns three public feeds into a small site/data/air.json. Visitors' browsers load only this site: no accounts, cookies, analytics, outside fonts, or calls to the agencies.
HiveAir Utah is for education only. It is not medical advice, not an official alert, and not affiliated with Utah DEQ, EPA, AirNow, the National Weather Service, AAAAI, or any government agency.
Called HiveWatch Utah until Oct 29, 2026, when the project folder became
Websites/HiveAir. The site moved from hivewatchutah.com to hiveairutah.com on Oct 30, 2026, and the GitHub repo (formerlyhivewatchutah) and Git database were renamed to match.The first version (Oct 22, 2026, the first commit) was a scanner and tip-routing site. That content has since moved out of this project.
site/ ← the website; this folder is what gets published
*.html one file per page, edited by hand
assets/css/style.css all styling (every color is at the top), plus print styles
assets/js/air.js the home page's live front page; reads data/air.json and nothing else
assets/js/common.js mobile menu
assets/favicon.svg
assets/img/share.png link-preview image, drawn by scripts/make_images.swift
data/air.json built by scripts/fetch_data.py (not committed)
sitemap.xml, robots.txt, _headers
scripts/
fetch_data.py builds site/data/air.json from Utah DAQ, AirNow and NWS
serve.py local preview server
make_images.swift draws site/assets/img/share.png
.github/workflows/
pages.yml fetches data and publishes site/ on every push and every 30 minutes
keepalive.yml weekly; keeps GitHub from switching its backup schedule off
python3 scripts/fetch_data.py
python3 scripts/serve.py
Then open http://localhost:8739. Press Ctrl+C in the terminal to stop it. (FaultLine Utah uses port 8737 and Prepare Utah 8738, so they can all run at once.) Run fetch_data.py again whenever you want fresh numbers; without it the front page says the readings didn't load.
Unknown addresses show the browser's plain "File not found" locally. GitHub Pages serves site/404.html instead; its links start with / so it works at any depth.
There is no build step for the pages: edit the HTML file and reload.
| What | Where |
|---|---|
| Hive Status line | site/index.html (see below) |
| Guide pages | site/air.html, seasons.html, pollen.html, breathe.html |
| Pollen calendar | the <table class="cal"> in site/pollen.html; each month cell's data-lvl is 0 (none), 1 (some), 2 (in season) or 3 (peak) |
| Burn-day wording in the county columns | burnLine() in site/assets/js/air.js |
| When the shimmer marker shows, and its "Watch:" words | watchReasons() in site/assets/js/air.js |
| The front page's headline and deck | frontHeadline() in site/assets/js/air.js |
| The lead under them | frontSummary() in site/assets/js/air.js |
| The what-to-do tips in the lead | TIPS in site/assets/js/air.js, copied from the level cards in site/breathe.html#levels; change both together |
| Which counties get columns, and their notes | COUNTIES in scripts/fetch_data.py |
| Header menu and footer | repeated in every site/*.html file; change all seven together. The home page has its own nameplate above the same menu |
| Who makes this, data sources, privacy | site/about.html |
| Link-preview image | scripts/make_images.swift; run swift scripts/make_images.swift from the project root |
| The front page's layout and type sizes | the rules under .paper in site/assets/css/style.css; the other pages don't use them |
Each guide cites its sources next to the claim (the small rounded links) and ends with "Checked [date]". When you re-check a page, update that date.
When style.css or a .js file changes after launch, bump the ?v= date on its <link>/<script> tags in every page so browsers fetch the new file. A second change on the same day needs a suffix (?v=2026-10-29b).
The live columns cover the AQI and burn levels. The Hive Status line is the desk's hand-typed note on what they don't: pollen season, smoke on its way, a long inversion coming. Nothing fetches it.
Open site/index.html and find id="hive-status".
Replace the text inside <p class="status-line">, keeping the shape and the middle dots:
As of [time] · [quiet|watch] · [one dry sentence] · Source: […]
Set data-level on that paragraph to the same word: quiet (sage edge: nothing to plan around) or watch (honey edge: one thing worth planning around; still not an alert). An unknown word leaves the edge gray.
One sentence. Name a source; if you can't, leave the line alone. Don't add a third level: anyone having trouble breathing should call 911, and every page says so.
Commit and push.
scripts/fetch_data.py (Python standard library only) reads:
| Feed | What it gives | Notes |
|---|---|---|
| Utah DAQ forecast CSV | 3-day health level and action (burn) level per county | The authority on burn days. Only good/unrestricted had been seen when this was written (Oct 24, 2026); other words come from DAQ's legend. Any unexpected word is shown as received with a link to DAQ. |
| AirNow reportingarea.dat | Current NowCast AQI per reporting area | Shown unchanged. "Salt Lake City" is the worst of eight Salt Lake and Davis monitors; Ogden is Harrisville; Provo is Lindon and Spanish Fork; no area covers Wasatch or Summit. |
| NWS active alerts | Air Quality Alert, Air Stagnation, Dense Smoke, Blowing Dust and Dust Storm alerts | Filtered to the counties above plus Summit and Morgan. |
GitHub Actions runs it (pages.yml) and publishes the result with the site. cron-job.org starts that run every 30 minutes; see The 30-minute trigger under Publishing.
air.json is reused, and the page says which source is older. Forecast days and alerts that have already passed are dropped, never carried forward.data_at in the file), the page shows a "these numbers are N hours old" warning and points to air.utah.gov. A single reading older than 3 hours is dimmed. A tab left open refreshes itself every 15 minutes.keepalive.yml re-enables them weekly. If the warning ever appears and stays, check the cron-job.org job first (its token may have expired), then the repo's Actions tab, where Deploy site may need re-enabling.history (from the previous air.json plus the new reading), shown as a strip of hourly columns in the AQI colors with a hairline at 100. The strip fills in over the first day after a fresh start, and needs at least two readings to show.AirNow's Data Exchange Guidelines ask for credit (in every footer), "preliminary" labels (on the home page and footer), official AQI colors (in style.css, not themed), unaltered values, and notice to AirNow and the state agency. See the to-do list.
The dark night palette (blue-black ground, cream type, honey accents) and every other color are variables in the :root block at the top of site/assets/css/style.css. Two sets are fixed on purpose:
--aqi-*) are EPA's official values, which AirNow asks sites to use unchanged.--pollen-1 to --pollen-3) is one honey hue from dim to bright, checked as an ordered scale against the card color. Each cell also carries text for screen readers.Text meets WCAG AA contrast on the dark background. Printing switches to a light palette.
Set up the same way as FaultLine Utah and Prepare Utah. The code lives at https://github.com/prepareutah/hiveairutah (public). Every push to main republishes the site, and so does the data refresh every 30 minutes. Watch deploys under the repo's Actions tab.
git add -A
git commit -m "Describe the change"
git push
The 30-minute trigger. GitHub's own schedule isn't reliable enough here: in late October 2026 the 20,50 * * * * schedule in pages.yml ran only every 4 to 7 hours, long enough to set off the site's old-data warning. It stays as a backup, and a free cron-job.org job does the timing by asking GitHub to start Deploy site:
| Setting | Value |
|---|---|
| URL | https://api.github.com/repos/prepareutah/hiveairutah/actions/workflows/pages.yml/dispatches |
| Schedule | Every 30 minutes |
| Method | POST |
| Headers | Authorization: Bearer <token>, Accept: application/vnd.github+json, X-GitHub-Api-Version: 2022-11-28, Content-Type: application/json |
| Body | {"ref":"main"} |
A good request returns 204. The token is a fine-grained personal access token limited to this one repo with Actions: write, which can start runs but can't change code. It lives only in the cron-job.org job, never in this repo. To replace it, make a new one, choose Only select repositories and this repo, and paste it into the job's Authorization header. If the repo is ever renamed, update the job's URL too. AirNow publishes new readings hourly, so a new reading reaches the site within about 30 minutes of its release; the readings themselves stay hourly.
Git and iCloud. This folder is in iCloud Drive, which corrupts Git's internal files if it syncs them. So Git's database lives outside iCloud at ~/.git-repos/hiveairutah.git, and the .git here is a one-line pointer to it. On another computer, clone from GitHub instead of opening this iCloud folder. iCloud conflict copies (file 2.html) are kept out of commits by .gitignore and are safe to delete.
Domain. hiveairutah.com is registered at GoDaddy. Its DNS points at GitHub Pages (set Oct 30, 2026), with the default parked A records removed:
| Type | Name | Value |
|---|---|---|
| A | @ | 185.199.108.153 |
| A | @ | 185.199.109.153 |
| A | @ | 185.199.110.153 |
| A | @ | 185.199.111.153 |
| CNAME | www | prepareutah.github.io |
The repo's Settings → Pages has Source set to GitHub Actions, hiveairutah.com as the custom domain, and Enforce HTTPS on. The Let's Encrypt certificate covers hiveairutah.com and www.hiveairutah.com and renews automatically. If a certificate doesn't start on its own after a DNS change, removing the custom domain and adding it back gets it issued at once, as with FaultLine and this site's first domain. Do the same if DNS ever changes and the certificate stalls.
Accounts and setup
hiveairutah (Oct 30, 2026).[email protected]). Add it to About and to USER_AGENT in scripts/fetch_data.py (NWS asks API users for contact details).Content
og:image) for links posted on social media (Oct 28, 2026).Re-check on a schedule (each guide shows its "Checked" date)
Review
air.js, and the questions below.For the clinician. All of it paraphrases EPA, AirNow, CDC, NHLBI, AAAAI, ACAAI, Utah DHHS, University of Utah Health or Intermountain Health, but none of it has had a clinician's eye:
Questions for Utah DAQ (the fact-checkers found these unresolved on Oct 24, 2026):
good and unrestricted, and what an action level means for Wasatch County, which is outside R307-302.isWinter() in air.js stops at the end of February, so on March 1 the page drops the county's stricter voluntary-day sentence.For education only. Not medical advice and not an official alert or forecast. Air data from the Utah DEQ Division of Air Quality and U.S. EPA AirNow, preliminary and not quality assured. Trouble breathing? Call 911.