Skip to content

Notification Subscription UI/UX Plan

Reviewed: 2026-07-08

This is a rough product and implementation plan for the public outage alert subscription UI. It is intentionally practical: enough detail to guide the first Angular build without turning the UI into a large dashboard or a second backend design document.

Create a simple authenticated UI that lets people subscribe to outage notifications without understanding the notification pipeline internals.

The UI should make the main task feel obvious:

  1. Choose what alerts they care about.
  2. Choose the places or keywords they care about.
  3. Create the subscription.
  4. Open the generated ntfy subscription link.
  5. Manage their saved alerts from their account.

This plan assumes the frontend will be built with current Angular using signals for local state, derived UI state, and async data boundaries. It was reviewed against Angular v22 docs on 2026-07-08. Spartan UI will provide the component system.

  • A first-time user can create an alert in under a minute.
  • A signed-in user can create and manage their own alerts.
  • The UI uses plain language: “alerts”, “areas”, “places”, and “notify me” instead of internal terms like “feed”, “destination”, or “filter”.
  • Mobile is the primary layout. Desktop should feel roomier, not like a different product.
  • The ntfy subscription step is explicit so users understand that creating an alert is not enough; they still need to open or copy the ntfy link.
  • Advanced targeting is available without making the common path feel technical.
  • The design leaves room for future email, maps, and analytics without forcing them into the MVP.
  • Start with the user’s question: “How do I get alerts for places I care about?”
  • Prefer one clear decision per screen.
  • Default to safe, broad choices, then let users narrow down.
  • Keep technical concepts behind labels and summaries.
  • Use progressive disclosure for feeders, keyword match mode, and other power-user filters.
  • Make every destructive or high-friction action reversible or clearly confirmed.
  • Treat subscription IDs as sensitive enough to avoid logging or sharing unnecessarily.

A resident wants outage alerts for the places they care about, such as a neighborhood, barangay, feeder, subdivision, or nearby landmark.

They should not need to know how notifications are stored, deduplicated, rendered, or delivered.

A user comes back to the alerts area to edit areas, pause alerts, send a test notification, or delete the subscription.

Someone helping another person should be able to walk through the screen and explain what each choice does without needing developer context.

The first version should be a focused alert subscription tool, not a dashboard.

Recommended routes:

Route Purpose
/alerts User’s alert list, empty state, and create entry point.
/alerts/new Create subscription flow.
/alerts/success/:publicId Success screen with ntfy subscribe link and test action.
/alerts/:publicId Edit, test, pause, resume, or delete an owned subscription.
/alerts/help Short help page for ntfy setup and troubleshooting.

The UI can start as one Angular feature area. It does not need a new backend module, event bus, or admin shell.

The page headline should be direct:

Get outage alerts for your area

The first screen should show the task immediately, not a marketing page.

Recommended layout:

  • Short headline.
  • One sentence of support copy.
  • Primary action: Create alert.
  • Secondary link: View my alerts.

Use user-facing labels backed by the feed IDs returned by the API.

Recommended options:

UI Label API Meaning
Power outage alerts Power outage notification feed.
Scheduled outage alerts Scheduled outage notification feed.

Avoid a broad “All alerts” option in the first pass unless the UI clearly explains that it may create more than one subscription behind the scenes. The current API creates one subscription per feed, so a “Both” option should either:

  • create two subscriptions in sequence, or
  • be deferred until the product intentionally supports bundled subscriptions.

Pragmatic MVP recommendation: start with one feed per subscription.

Recommended default:

  • If the user entered from a power outage page, preselect power outage alerts.
  • Otherwise, show both choices with neither selected until the user chooses.

This is the most important UX step.

Use friendly copy:

Choose the places you care about

The UI should support entering location keywords such as barangay names, road names, neighborhoods, substations, or other feed text users recognize.

Use two clear choices:

Choice API Filter
All areas Empty filter values. This matches all events for the selected feed.
Specific places One or more locationKeywords, with optional advanced values.

Do not force a location keyword for MVP. Some users may want the whole feed.

Recommended fields:

  • Area, barangay, road, or landmark
  • Add button or Enter-to-add behavior.
  • Chips for selected keywords.
  • Optional helper examples from common local language.

Advanced options can be hidden behind a disclosure:

  • Feeder names or IDs.
  • Exact event keywords.
  • Match mode.

Do not make feeder IDs the primary path unless users commonly know them.

Validation rules to mirror the API:

  • each filter list can contain up to 20 values,
  • each filter value should be 100 characters or fewer,
  • duplicate entries should collapse case-insensitively,
  • blank chip values should be ignored before submit.

Show plain labels. Map them to event types internally.

Examples:

UI Label Event Type Meaning
New outage reported NewOutage Notify when a new outage appears.
Outage restored Restoration Notify when power is restored or the outage is removed.
Already restored outage announced RestoredAnnouncement Notify when an outage first appears after it was already restored.
Scheduled outage added NewEntry Notify when a scheduled outage is published.
Scheduled outage updated Updated Notify when a scheduled outage changes.
Scheduled outage cancelled Cancelled Notify when a scheduled outage is removed or cancelled.
Weekly scheduled outage summary WeeklyDigest Notify when the weekly scheduled outage digest is sent.
Daily scheduled outage update DailyUpdate Notify when daily schedule changes are summarized.
Tomorrow reminder DayBeforeReminder Notify before scheduled outages happening tomorrow.

The feed metadata endpoint should drive the available event types where possible, so the UI does not become stale when backend feed definitions change.

Recommended default:

  • Preselect all event types for the chosen feed.
  • Let users uncheck types only after they choose “Customize event types”.
  • If all event types are selected, submit an empty eventTypes list so the backend treats it as “all supported events”.

Before creating, show a compact summary:

  • Alert type.
  • Areas or keywords.
  • Event types.
  • Delivery method: ntfy.

The create button should be explicit:

Create alert

After the API creates the subscription, the success screen should focus on the next required action.

Primary card:

  • Open in ntfy
  • Copy subscribe link
  • Send test notification

Recommended success-state order:

  1. Open or copy ntfy subscribe link.
  2. Send test notification.

The user should leave the page knowing whether they subscribed successfully. A created subscription without an opened/copied ntfy link is only half done.

The manage screen should load from the authenticated user’s subscription list or an owned public subscription ID.

Recommended sections:

  1. Status summary.
  2. Current alert type.
  3. Areas and filters.
  4. Event types.
  5. ntfy subscribe link.
  6. Test notification.
  7. Pause or resume.
  8. Delete alert.

Users should be able to update:

  • area/location keywords,
  • event types,
  • active/inactive status,
  • match mode if exposed.

The UI should show unsaved changes clearly and keep the save action sticky on small screens.

The test action should be obvious after creation and on the manage screen.

Recommended copy:

Send a test notification

Successful test:

Test sent. Check your ntfy app or browser subscription.

Failure:

The test could not be sent. Check that the ntfy topic is still available, then try again.

Use a confirmation dialog.

Recommended copy:

Delete this alert?

Explain that deleting stops future notifications but does not delete outage history or analytics data.

Implementation note: the current API treats delete as deactivation. The UI can say “Delete alert” to the user, but the product behavior is “stop this alert from sending again.” Inactive subscriptions can be shown as stopped and may be resumed unless the API later introduces hard delete.

The UI should use the authenticated notification subscription endpoints.

Action Endpoint
List available feeds GET /api/notification-feeds
List my subscriptions GET /api/notification-subscriptions
Create subscription POST /api/notification-subscriptions
Get subscription GET /api/notification-subscriptions/{publicId}
Update subscription PUT /api/notification-subscriptions/{publicId}
Delete subscription DELETE /api/notification-subscriptions/{publicId}
Send test notification POST /api/notification-subscriptions/{publicId}/test

The backend owns:

  • generated public subscription IDs,
  • generated ntfy topics,
  • destination validation,
  • per-user subscription limits,
  • ownership checks,
  • delivery provider details.

The frontend should not ask the user to enter an ntfy topic manually in the MVP.

The create flow should start by loading feed metadata.

[
{
"id": "beneco.power-outages",
"displayName": "BENECO Power Outages",
"eventTypes": ["NewOutage", "Restoration", "RestoredAnnouncement"],
"filterableFields": [
{ "name": "feeder", "displayName": "Feeder" },
{ "name": "area", "displayName": "Area" },
{ "name": "cause", "displayName": "Cause" },
{ "name": "status", "displayName": "Status" },
{ "name": "keywords", "displayName": "Keywords" }
],
"allowsUserSubscriptions": true
}
]

Use allowsUserSubscriptions to hide feeds that should not appear in the public create flow.

The UI should send the smallest useful payload.

{
"displayName": "Home outage alerts",
"feedId": "beneco.power-outages",
"filter": {
"locationKeywords": ["Bakakeng"],
"eventTypes": ["NewOutage", "Restoration"],
"matchMode": "Any"
},
"provider": "Ntfy"
}

Do not send destination for public ntfy subscriptions. The backend rejects client-provided destinations and generates the topic itself.

The created response includes everything needed for the success page.

{
"publicId": "ns_example1234",
"displayName": "Home outage alerts",
"feedId": "beneco.power-outages",
"filter": {
"feeders": [],
"locationKeywords": ["Bakakeng"],
"keywords": [],
"eventTypes": ["NewOutage", "Restoration"],
"matchMode": "Any"
},
"provider": "Ntfy",
"destination": "beneco-outages-alerts-example1234",
"subscribeUrl": "https://ntfy.example.com/beneco-outages-alerts-example1234",
"isActive": true,
"createdAt": "2026-07-08T00:00:00+00:00",
"lastSentAt": null
}

Map backend error codes to user-facing text.

Error Code User Message
NotificationSubscription.InvalidFeed This alert type is no longer available. Refresh and try again.
NotificationSubscription.FeedNotAllowed This alert type is not available for public subscriptions yet.
NotificationSubscription.UnsupportedProvider Public alerts currently support ntfy only.
NotificationSubscription.DestinationNotAllowed The app creates the ntfy topic for you. Refresh and try again.
NotificationSubscription.InvalidFilter One of the alert filters is invalid.
NotificationSubscription.InvalidEventType One selected event type is not available for this alert.
NotificationSubscription.FilterTooLarge Too many filter values were added.
NotificationSubscription.FilterValueTooLong One filter value is too long.
NotificationSubscription.LimitExceeded Your account already has the maximum number of active alerts.
NotificationSubscription.NotFound This alert was not found.
NotificationSubscription.Inactive This alert is paused or deleted. Reactivate it before sending a test.
NotificationSubscription.TestDeliveryFailed The test notification could not be delivered.

Use standalone components and signal-first local state.

Recommended folders:

src/app/alerts/
data-access/
notification-subscription-api.ts
notification-subscription.models.ts
notification-subscription-errors.ts
state/
subscription-form.store.ts
subscription-manage.store.ts
pages/
alerts-entry.page.ts
create-subscription.page.ts
subscription-success.page.ts
manage-subscription.page.ts
alerts-help.page.ts
ui/
feed-picker.ts
location-keyword-editor.ts
event-type-picker.ts
filter-summary.ts
subscribe-ntfy-card.ts
manage-link-card.ts
subscription-status-banner.ts
api-error-alert.ts

Keep business rules on the backend. The Angular feature should validate for fast feedback, but the API remains the source of truth for allowed feeds, event types, topic generation, and subscription limits.

Use signals for form state:

  • selected feed,
  • location keywords,
  • event types,
  • advanced filters,
  • active status,
  • request state.

Use computed signals for derived UI:

  • whether the form can submit,
  • human-readable filter summary,
  • selected event labels,
  • whether advanced filters are active,
  • request payload.

Use Angular resource-style async state where it fits naturally:

  • feed metadata loading,
  • existing subscription loading,
  • test notification status.

Keep RxJS mostly inside the API service or HTTP boundary unless the application already has an established RxJS pattern.

Recommended signal boundaries:

  • private writable signals inside the store,
  • read-only signal accessors exposed to components,
  • computed request payloads instead of manual object rebuilding in templates,
  • explicit submit methods for create, update, delete, and test actions,
  • no async work hidden inside computed signals.

When an async action needs signal values, read the needed values before the await boundary and pass plain values to the API method.

Use the current Angular control flow syntax:

  • @if for loading, empty, and error states,
  • @for for lists of feeds, event types, and keyword chips,
  • @switch if different feed types need different copy.

Prefer ChangeDetectionStrategy.OnPush for page and UI components.

Use Spartan components to keep the UI accessible and consistent.

UX Need Spartan Component Direction
Main page sections Card only where framing helps a single task or result.
Primary actions Button.
Form layout Field, Label, Input, Textarea where needed.
Feed choice Radio Group for two choices; Select only if the list grows.
Event type choices Checkbox list.
Location keyword entry Input Group plus Badge chips; Autocomplete or Combobox later if suggestions exist.
Advanced filters Accordion, Sheet, or Drawer on mobile.
Status messages Alert.
Empty states Empty.
Loading Skeleton for page load; Spinner for button-local actions.
Copy/open actions Button with Tooltip for icon-only variants.
Delete confirmation Alert Dialog or Dialog.
Success/failure feedback Sonner Toast plus inline confirmation.
Summary chips Badge.
Pause/resume Switch plus plain status text.

Prefer Spartan Signal Forms for the create/edit form if it fits cleanly. Use the form root pattern so submit marks fields touched, runs validation, and reveals errors consistently. If it adds friction for dynamic chip lists, keep the first version with Angular signals and straightforward component inputs/outputs.

The UI should feel calm, direct, and trustworthy.

Recommended style:

  • Mobile-first single-column flow.
  • One primary action per step.
  • Clear spacing between decision groups.
  • Small summaries after each step so users know what they selected.
  • Plain icons only where they improve scanning.
  • Avoid decorative hero sections, abstract graphics, and overly large cards.

The first viewport should show the actual alert creation task.

  • Use a short stepper only if it reduces confusion. Do not make users click through empty ceremony.
  • On mobile, keep the current step title, summary, and primary action visible.
  • On desktop, use a two-column layout only if the right column is a live summary, not another card stack.
  • Preserve in-progress selections if the user goes back to a previous step.
  • Disable submit only for truly incomplete forms; otherwise let validation explain what is wrong.

Show a compact summary after each major selection:

Power outage alerts
Specific places: Bakakeng, Camp 7
Events: New outage, Power restored
Delivery: ntfy

This reduces anxiety before the final create action.

  • Show the ntfy subscribe URL after creation.
  • Add a copy button with visible success feedback.
  • Do not send subscription IDs, ntfy topics, or subscribe URLs to a third party analytics tool.

Required behaviors:

  • Every input has a visible label.
  • Error messages are tied to fields.
  • Keyboard users can complete the whole flow.
  • Tap targets are comfortable on mobile.
  • Copy buttons announce success.
  • Color is not the only indicator for active, inactive, success, or error states.
  • Loading states do not shift layout heavily.
  • Delete and pause actions require clear confirmation or recovery.
  • Icon-only buttons have accessible names.
  • Form errors are announced when submit fails.
  • Motion is subtle and not required to understand state.

Show:

Alert options could not be loaded. Please try again.

Action:

  • Retry.

Show:

This alert was not found.

Actions:

  • Create a new alert.
  • Check the link.

Show:

You already have the maximum number of active alerts from this network.

Actions:

  • Delete an alert no longer needed.

Show:

The test notification could not be sent.

Actions:

  • Retry.
  • Copy subscribe link.
  • Open help.

Show:

This alert is paused.

Actions:

  • Resume alert.
  • Send test after resuming.
  • Delete alert.

Show:

One of the alert filters needs attention.

Actions:

  • Highlight the exact field when possible.
  • Keep the user’s entered values so they can fix them.

Include:

  • Create one ntfy subscription for one notification feed.
  • List feed/event options from the backend.
  • Let users choose all areas or specific place keywords.
  • Location keyword filters.
  • Event type selection.
  • Success page with subscribe URL.
  • Test notification.
  • Manage page.
  • Pause/resume through active status.
  • Delete subscription.
  • Mobile-first responsive layout.

Do not include yet:

  • Email subscriptions.
  • SMS subscriptions.
  • Map selection.
  • QR codes.
  • Multiple feeds bundled into one wizard result.
  • Admin dashboards.
  • Historical analytics views.

Good follow-up improvements:

  • “Both power and scheduled outage alerts” as a bundled create flow.
  • QR code for the ntfy subscribe link.
  • Email delivery once verified addresses are supported.
  • Suggested locations from known outage data.
  • Map-assisted area selection.
  • Saved presets for common barangays or feeders.
  • User accounts for managing multiple alerts.
  • Delivery channel choices once more providers exist.
  • Lightweight analytics for create started, create completed, test sent, and manage updated.
  • Add typed frontend models for feeds, subscriptions, filters, and delivery results.
  • Add NotificationSubscriptionApi.
  • Wire feed metadata loading.
  • Add basic error handling.
  • Add error-code-to-message mapping.
  • Build the create page using signal state.
  • Add feed selection.
  • Add all areas vs specific places selection.
  • Add location keyword editor.
  • Add event type picker.
  • Add review summary.
  • Submit to the create endpoint.
  • Build the success page.
  • Show subscribe URL.
  • Add copy and open actions.
  • Add send test action.
  • Show the ntfy subscribe URL clearly.
  • Load the user’s owned subscriptions.
  • Edit filters.
  • Save changes.
  • Pause/resume.
  • Delete with confirmation.
  • Send test notification.
  • Add loading skeletons.
  • Improve empty/error states.
  • Verify mobile layout.
  • Verify keyboard navigation.
  • Verify copy buttons and screen reader labels.
  • Add basic analytics events if the app already has an analytics pattern.
  • A signed-in user can create a power outage alert from a mobile viewport.
  • A signed-in user can create a scheduled outage alert from a mobile viewport.
  • A user can create an all-areas alert with an empty filter.
  • A user can create a specific-places alert with location keyword chips.
  • A user can copy and open the ntfy subscribe URL from the success page.
  • A user can see their subscriptions in the alert list.
  • A user can load an owned subscription from the alert list.
  • A user can update filters and event types.
  • A user can pause and resume an alert.
  • A user can send a test notification only when the alert is active.
  • A user can delete an alert, which deactivates it.
  • API errors show plain user-facing text.
  • Keyboard-only users can complete create, manage, test, and delete flows.
  • The UI never asks the user to type an ntfy topic.
  • The UI never sends a client-provided destination for public ntfy subscriptions.
  • Should “Both alert types” be exposed immediately, creating two subscriptions, or deferred?
  • Should feeder targeting be visible by default or advanced-only?
  • Should the user see the raw ntfy topic, or only the subscribe URL?
  • Should paused subscriptions count toward the per-user maximum?
  • Should digest and reminder event types be selected by default for scheduled outage alerts?
  • Should the success page offer QR codes in MVP or keep them as a later enhancement?

The UI should make the system feel like this:

Outage data changes
-> Obaki checks what changed
-> Obaki matches the change against my alert choices
-> Obaki sends a notification to my generated ntfy link
-> I can update or delete the alert later from my account

The UI does not need to explain deduplication, event persistence, renderer classes, delivery attempts, or internal subscription records unless this becomes an admin experience.