Broadcasting an Alert
Some events can't wait for someone to happen to glance at the right camera: a spreading fire, an evacuation boundary, a hazard other agencies need to know about now. The Alerts feature lets an authorized operator draw that event on the map and push it — as a marker every user can see, and as email/SMS/phone notifications to everyone whose subscription matches.
The form
AlertMessage (in components/molecules/Notifications/) collects the alert: a location picked
interactively on the map (latitude, longitude, and a radius up to 10 miles), an urgency level, a
message, the recipients (specific agencies, specific users, or broadcast), and optionally a
snapshot of the map for spatial context.
Validation is react-hook-form + a Zod schema, and the schema is the contract worth reading:
const AlertMessageSchema = z.object({
message: z.string(),
latitude: z.number(),
longitude: z.number(),
radiusInMiles: z.number().min(0).max(10),
recipientAgencyIds: z.array(z.number()).nullable(),
recipientEntraUserIds: z.array(z.string()).nullable(),
imageUrl: z.string().nullable(),
cameraId: z.string(),
urgencyLevel: z.number().min(0).max(4), // 0=None, 1=Low, 2=Medium, 4=High
mapImage: z.instanceof(Blob).nullable(),
});
Note urgencyLevel — those aren't sequential values. They're bitmask levels, and the
subscription side depends on that; the next lesson explains the
scheme.
The journey after submit
Because the payload can carry a map-image Blob, this route breaks the usual JSON pattern: the
form posts multipart FormData to /api/alerts/alert-create, where the BFF parses the
multipart body, re-validates, and forwards fields plus image to the backend.
From there, the backend takes over — this is the hand-off boundary where frontend work ends:
- A marker is created on the ESRI map, visible to users with map access (clicking it goes through the AGOL click pipeline)
- The alert's location, radius, urgency, and timing are matched against user subscriptions
- Notifications go out on each recipient's chosen channels
Frontend feedback is standard: inline Zod errors before submit, success/error surfaced in the UI after.
Wrapping up
One form, one Zod contract, one multipart hop through the BFF — then the backend fans it out to the map and to every matching subscriber. Which subscribers match is the other half of the story: Notification Settings.