A Typhoon Tracker Built in One Sleepless Night Is Now Open for Anyone to Harden
This is a co-building guide for developers, designers, and weather enthusiasts. It's also a ramble about why I made this.
Repository: https://github.com/Trade-Offf/typhoon-bavi-tracker Live: https://chinaupdated.com
1. Origin
On the night Super Typhoon Bavi approached, I couldn't sleep.
Not out of fear, but because after a day of grinding as a corporate drone, my brain was fried. Lying in bed, I habitually opened my phone to check the typhoon situation. The more I scrolled, the more confused I got:
- This blogger says, "Strongest in history, don't go out."
- That blogger says, "It's not that serious, just clickbait."
- Swipe twice and see a three-day-old news piece, with people arguing in the comments about "who to believe."
After twenty minutes of scrolling, I hadn't figured out a single piece of information, but I did learn three kinds of "typhoon outfits" and two "typhoon BGM" tracks. Lying in my rented apartment, only three questions remained in my head:
- Where is the typhoon now, and how strong is it?
- How long until it reaches my home?
- What exactly should I do right now?
Just these three questions. I searched through every app on my phone, and not a single one could answer them clearly in one place.
So I got up, opened my computer, and used Claude Fable 5 to hammer out the idea bit by bit. After putting the track data from four agencies—the China Meteorological Administration (CMA), the Japan Meteorological Agency (JMA), the US Joint Typhoon Warning Center (JTWC), and the Taiwan Central Weather Administration (CWA)—onto the same map, many things became clear at a glance. For example, at this moment, the predicted landfall points from several agencies are converging near Wenzhou.
Then I added a few more things:
- Real-time news aggregation. Faster than official data, a secondary verification of distributed data, but not necessarily accurate—please use your own judgment.
- City impact countdown. An estimate of how long until Bavi reaches your city, based on wind speed and map vector calculations—not necessarily accurate.
- Emergency guide and hotlines. So you don't have to search for them when you really need them.
This website was made purely for myself: no ads, no data collection, all data sources are official. For disaster prevention decisions, please rely on official warnings (do not believe or spread rumors).
There was only one thought while making this: If the people around me can know a little earlier, they can feel a little more at ease.
If you have friends in Jiangsu, Zhejiang, or Shanghai, feel free to forward it to them. If you're a developer, keep reading—I'll lay out how it works, where it's still rough, and how you can help.
2. What It Looks Like
Pictures first, then the tech talk.
A Moving Map on Open
The observed path is colored by the national standard's six-level intensity scale, "burning" from the deep ocean to the coastal waters. A list of city countdowns hangs on the left, with the most urgent ones at the top. A warning banner at the top tells you who is in the most danger right now.
Click on a City You Care About
The camera flies over, and a small card pops up: when the wind circle is expected to arrive, the closest distance in kilometers, and what to do now. A share link is also ready for you—?city=Wenzhou, send it to a friend in Wenzhou, and it opens directly focused on their home.
Four Agencies' Forecasts, Side by Side
The forecast dotted lines from the four agencies—China, Japan, the US, and Taiwan—can be toggled on and off independently. Forecasts inherently have disagreements; the divergence itself is information. The tighter the four lines converge, the more certain the path; the more they spread out, the more you need to stay alert.
News and Guides, All at Hand
News is from a media perspective, faster than official bulletins, but please use your own judgment. The guide is static content, covering everything from "48 hours before landfall" to "safety checks afterward." Emergency numbers are all listed—in a real moment of panic, no one has the patience to search again.
3. How It Works
The architecture is almost embarrassingly simple: one Cloudflare Worker, a bunch of pure functions, no database, no server.
┌─────────────────────────────────────────────────────────────┐
│ User Browser (MapLibre GL + TypeScript) │
│ · Path replay / Wind circle animation / City markers / HUD / Deep-link sharing │
└──────────────────────────┬──────────────────────────────────┘
│ /api/typhoon/:id /api/news
┌──────────────────────────▼──────────────────────────────────┐
│ Cloudflare Worker (Edge Proxy + Cache + Disaster Recovery) │
│ · normalize.ts Dual-source normalization │
│ · news.ts RSS feed aggregation │
│ · Cache: Typhoon 5min / News 10min │
└──────────┬─────────────────────────────┬────────────────────┘
│ │
Zhejiang Water Resources Google/Bing News RSS
Dept. API (Primary)
CMA NMC (Backup)
But the simplicity is intentional. In the face of a disaster, the simpler the system, the more reliable it is. There's no database to crash, no server to wake up and restart in the middle of the night. If one edge node goes down, there's another. The first thing a disaster prevention tool must do is not fall over itself.
The same thinking guided the tech choices:
| Layer | Choice | Why |
|---|---|---|
| Edge Compute | Cloudflare Workers | Zero ops, global CDN, accessible in China |
| Frontend Map | MapLibre GL | Open-source, flexible, no Google dependency |
| Basemap | Amap Satellite + CN labels | Stable domestic CDN, Chinese labels, compliant |
| Build | Vite + TypeScript | Fast, with type safety net |
| Data | No database | Origin returns full track; edge cache is enough |
Directory Overview
worker/
index.ts # Routing, edge caching, dual-source disaster recovery
normalize.ts # CMA/ZJ data → TyphoonData (pure function)
news.ts # RSS parsing, aggregation, and snapshot merging (pure function)
src/
app.ts # Entry: playback control, HUD, sharing, countdown refresh
map.ts # MapLibre layers, city markers, wind circle animation
impact.ts # City impact countdown algorithm (pure function)
geo.ts # Spherical distance, wind circle polygon, track interpolation
guide.ts # Emergency guide content
news.ts # News panel rendering
mobile.ts # Mobile layout: top live strip + bottom 3-drawer panel
slogan.ts # Positive energy slogan carousel
A few habits kept while coding:
- Data normalization and algorithms are written as pure functions (
normalize.ts,impact.ts,geo.ts) wherever possible—easy to test, easy to reuse, and easy to locate issues. - Drawing and animation are all confined to
map.ts; business logic doesn't tangle with rendering. - The Worker only acts as a proxy and cache. The dumber it is, the less likely it is to break.
A Pitfall I Stepped Into, Shared with You
I fell for a trap once with the news aggregation. The original logic was to overwrite the cached snapshot on each fetch. One time, Google was rate-limited and Bing happened to return only 1 result. This meager result wiped out the previously accumulated 30-item complete snapshot. When a user opened the page, the news panel had only a single lonely entry.
After the fix, the refresh logic was changed to a merge: new items take priority, historical items are deduplicated and fill in the gaps, and within a seven-day window, the data only grows, never shrinks. This lesson is worth writing down here: For a disaster prevention tool, a single bad fetch should never destroy the accumulation already built.
4. How to Get Started?
git clone [email protected]:Trade-Offf/typhoon-bavi-tracker.git
cd typhoon-bavi-tracker
npm install
npm run dev # Vite dev server
npm run typecheck # TypeScript check
npm run preview # Build + wrangler local Worker simulation
When running vite dev locally, /api/typhoon proxies to the Zhejiang Water Resources Department interface. To see the full Worker behavior (caching, disaster recovery, news aggregation), use npm run preview.
5. These Tasks, Waiting for You
The directions below are sorted by "how much more they can help a person," not by technical difficulty. In this project, adding a city is more valuable than swapping a framework.
Directly Enhance Disaster Prevention Value
| Direction | Description | Where to Modify |
|---|---|---|
| Add a city | Add { name, lng, lat } to the CITIES array. That's it. |
src/impact.ts |
| 10/12-level wind circle countdown | Extend computeImpacts to return multi-level ETAs. |
src/impact.ts |
| Sort cities by location | navigator.geolocation + distance sorting. |
src/app.ts |
| Multi-typhoon switching | Change TYPHOON_ID to a route parameter—typhoons come every year, this site shouldn't live just for Bavi. |
src/app.ts · worker/index.ts |
| Localized guides | Provincial flood prevention rules, shelters. You know your city better than I do. | src/guide.ts |
Experience & Dissemination
| Direction | Description |
|---|---|
| i18n Traditional Chinese / English | For residents of Hong Kong, Macau, Taiwan, and foreign nationals. |
| Warning level integration | Connect to CMA warning signals. |
| PWA offline cache | The last data before disconnection, viewable offline—network loss is most common during typhoons. |
| Dynamic share card generation | Real-time rendering of OG images based on city countdown. |
Data Source Expansion (Requires Compliance Assessment)
| Source | Current Status | Idea |
|---|---|---|
| Xiaohongshu (RED) | Anti-scraping, cannot fetch anonymously | Requires user authorization or official API. |
| Requires visitor Cookie | Implement cautiously on Worker side, mind the ToS. | |
| Local weather bureaus | Most have public interfaces | Add a fetcher module in worker/. |
Performance To-Dos (Welcome to Claim)
- Simplify wind circle polygon points on demand (low zoom levels)
- Service Worker cache for the latest API response
- WebP compression for screenshots/OG images
- Unit tests:
impact.ts·normalize.ts·geo.ts
6. How to Submit an MR
The process is standard: Fork, branch, self-test, send a PR:
git checkout -b feat/your-feature-name
npm run typecheck # Must pass
npm run build # Must pass
npm run preview # Run Worker + frontend locally to verify
A few small conventions:
- Commit messages explain the "why," not just the "what."
- One MR does one thing. Adding a city, fixing a data source, changing styles—submit them separately.
- Attach a verification method. A screenshot or screen recording so a reviewer can confirm in two minutes.
For example:
feat(impact): add Xiamen, Quanzhou city countdowns
- Added southern Fujian coastal cities to the CITIES array
- Verification: open /?city=Xiamen to see the countdown popup
During review, I'll look at type safety, dependency size, and data source timeouts and disaster recovery. But one rule outweighs all code standards:
Every line of text in this project might be read late at night by someone worried about their family. We provide certainty, not anxiety; convey urgency, not panic. The disclaimer must remain: the countdown is an estimate, and disaster prevention decisions should be based on official warnings.
7. Why Open Source
Disaster prevention information should not be locked in anyone's server—including mine.
This project was born on a sleepless night, but it shouldn't belong only to that night. Typhoons come every year, data sources will expire, city lists will become outdated, and guides will need updating. One person's passion cannot sustain something that needs to exist long-term; only a community can.
After open-sourcing, things become imaginable: a data source goes down, someone submits a fix within half an hour; a friend in Fujian adds Fujian's shelters; someone forks and deploys it to their own domain. Even if chinaupdated.com disappears one day, the code remains and can still help in an emergency.
People who write code often doubt whether what they make has meaning. But disaster prevention gives a rare, clear answer—
A technologist's idealism is sometimes just writing a piece of code so that one more person can see danger ahead of time.
Every bug you fix might be the last refresh a user grabs before the network cuts out; every city you add has real people living behind it. There are no KPIs here, no growth curves, just a simple metric: did someone, because of it, reinforce their windows early, stock up on water, or move their elderly parents to safety?
Welcome to Star, Fork, raise an Issue, submit an MR. One person's strength is limited, but many hands make light work, always illuminating a little more of the road ahead.
The typhoon will pass, the code will remain. May it be better the next time it is needed.
Appendix
The custom domain is configured in the routes section of wrangler.jsonc, currently bound to chinaupdated.com and www.chinaupdated.com.
Screenshot Index
| File | Description |
|---|---|
docs/screenshots/01-overview-city-countdown.png |
Overview: Amap basemap + city list + warning bar |
docs/screenshots/02-city-popup.png |
Click city: countdown popup + action suggestion |
docs/screenshots/03-news-panel.png |
Real-time news: multi-source media reports |
docs/screenshots/04-guide-panel.png |
Emergency guide: five-section checklist |
docs/screenshots/05-forecast-compare.png |
Four-agency forecast path comparison |
Top 7 of 11 from juejin.cn, machine-translated. The original thread is authoritative.
Bug: Style is not done loading. at cn._checkLoaded (maplibre-wqmL2Hxp.js:796:86493) at cn.addSource (maplibre-wqmL2Hxp.js:796:91133) at Yo.addSource (maplibre-wqmL2Hxp.js:800:109763) at Gt.setupLayers (index-C1flaEsg.js:2:6218) at index-C1flaEsg.js:107:3324 at s (index-C1flaEsg.js:2:5974)
Got it, I'll take a look after work. Probably a sporadic network issue. Gotta be a beast of burden for a while longer [downcast]
There really is a bug crawling around [dog with eye-roll]
I want to try it right now, deploy it quickly.
https://chinaupdated.com/ , it's live online. Can't you open it?
[grin] Just saw it.
OP is fast. Did you have a server before? How can you be this fast? Even with AI assistance, it's still incredibly fast.
Don't you know about a real-time typhoon path website developed in Zhejiang? But yours has some unique features, more information.
Can't open it. It keeps showing 'Fetching Bavi real-time observation data...'
The above is an ops doc. Talk about the tech stack. What engineering template is this, and how to deploy it on Cloudflare?
Some ramblings: https://www.bilibili.com/video/BV148Ms6MET9/?spm_id_from=333.1387.homepage.video.card_click&vd_source=0bcafb665fe6140f5a86a181137e5c7d