Build / Bots
Team alert bot
Post to your team chat when a county you watch reaches grade C or worse.
TypeScriptWebhookCron

What it does
A scheduled script you host. It reads the free county forecast, and if the grade is C or worse it posts a short message to an incoming webhook (Slack, Discord or similar). You own the webhook and the schedule.
- Run it from cron every few hours. Forecasts refresh four times a day.
- Add a dedupe step so the same alert does not repeat.
API calls
Set your key once: export TFX_KEY=tfx_live_.... Free previews need no key.
Free: county forecast
curl "https://data.truefixr.com/v1/data?dataset=risk&county=Dallas&state=TX"
Code (TypeScript)
Cut down on purpose. Print the real response keys on your first call before you map fields.
const WATCH = [{ county: "Dallas", state: "TX" }];
const WORSE = new Set(["C", "D", "F"]);
async function check(county: string, state: string) {
const url = `https://data.truefixr.com/v1/data?dataset=risk&county=${encodeURIComponent(county)}&state=${state}`;
const res = await fetch(url);
if (!res.ok) throw new Error(`risk lookup failed: ${res.status}`);
return res.json() as Promise<{ grade: string; grade_label: string; total_leads: number; storm_types: Record<string, number> }>;
}
async function post(text: string) {
// Slack and Discord both accept a JSON body at an incoming webhook URL; check your tool's field name
await fetch(process.env.WEBHOOK_URL!, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ text, content: text }),
});
}
async function main() {
for (const w of WATCH) {
const d = await check(w.county, w.state);
if (WORSE.has(d.grade)) {
const types = Object.keys(d.storm_types ?? {}).join(", ");
await post(`Storm watch: ${w.county}, ${w.state}. Grade ${d.grade} (${d.grade_label}). ${types}. Forecasts show what could happen, not what will.`);
}
}
}
main();