---
title: "Keep the app working when people say no · Agent Wranglers"
url: https://agentwranglers.se/playbook/notifications/push-notifications/works-without-push
updated: 2026-10-21
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Keep the app working when people say no

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Push notifications](https://agentwranglers.se/playbook/notifications/push-notifications.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers). Updated 2026-10-21.

- Level: Recommended
- Chapter: [Push notifications](https://agentwranglers.se/playbook/notifications/push-notifications)
- Rule: Every feature works when notification permission is denied or never asked. Nothing the person needs reaches them by push alone.
- How: Apple's App Review Guidelines (4.5.4) say push notifications must not be required for the app to function. Read the permission state, and never block a screen or a sign-up step on it. Every push has a copy in the server inbox, and critical types also use another channel, such as email. When permission is denied, show a short hint where the settings live, once, and never ask again in a loop. Build each feature on what works without extras first, as [Build on HTML that already works](https://agentwranglers.se/playbook/website/site-architecture/progressive-enhancement) says.
- Check: A browser test denies notification permission and runs sign-up, checkout and the inbox flows. Each one completes, and a new notification shows in the inbox. No permission prompt appears a second time.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### JavaScript example

```js
export function pushState() {
  if (!('Notification' in window) || !('PushManager' in window)) return 'unsupported';
  return Notification.permission; // 'granted', 'denied' or 'default'
}

// The order flow never waits on push. It only offers the button when asking still makes sense.
document.querySelector('#notify-shipping').hidden = pushState() !== 'default';
```

### Plain text example

```swift
import UserNotifications

func offerShippingAlerts() async {
    let settings = await UNUserNotificationCenter.current().notificationSettings()
    switch settings.authorizationStatus {
    case .notDetermined: showShippingAlertButton()
    case .denied: showSettingsHintOnce()
    default: break // Push is on. The inbox still gets every item either way.
    }
}
```

## Sources

- [Apple App Review Guideline 4.5.4](https://developer.apple.com/app-store/review/guidelines/#4.5.4)

## Related rules

- [Build on HTML that already works](https://agentwranglers.se/playbook/website/site-architecture/progressive-enhancement) in Website

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/notifications/push-notifications/works-without-push">Agent Wranglers notifications playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Open the exact page the push is about](https://agentwranglers.se/playbook/notifications/push-notifications/push-deep-links)
- Next: [Show a notification for every push](https://agentwranglers.se/playbook/notifications/push-notifications/visible-push-only)
- [Push notifications](https://agentwranglers.se/playbook/notifications/push-notifications)
