# Push Notification

> Web/mobile push notification with title, body, actions, and data payload.

- Name: `push-notification`
- Categories: notification
- Detail page: https://open-types.dev/types/push-notification

## Install

```bash
# Types only
npx shadcn add @open-types/push-notification

# Types + Zod v4 validators
npx shadcn add @open-types/push-notification-zod

# Types + real-world examples
npx shadcn add @open-types/push-notification-examples
```

## Types

```typescript
export interface PushNotificationAction {
  action: string;
  title: string;
  icon?: string;
}

export interface PushNotification {
  title: string;
  body?: string;
  icon?: string;
  badge?: string;
  image?: string;
  tag?: string;
  data?: Record<string, unknown>;
  actions?: PushNotificationAction[];
  url?: string;
}
```

## Zod validator

```typescript
import * as z from "zod";
import type {
  PushNotification,
  PushNotificationAction,
} from "../types/push-notification";

export const pushNotificationActionSchema = z.object({
  action: z.string().min(1, { error: "Action is required" }),
  title: z.string().min(1, { error: "Action title is required" }),
  icon: z.url({ error: "Action icon must be a valid URL" }).optional(),
}) satisfies z.ZodType<PushNotificationAction>;

export const pushNotificationSchema = z.object({
  title: z.string().min(1, { error: "Title is required" }),
  body: z.string().optional(),
  icon: z.url({ error: "Icon must be a valid URL" }).optional(),
  badge: z.url({ error: "Badge must be a valid URL" }).optional(),
  image: z.url({ error: "Image must be a valid URL" }).optional(),
  tag: z.string().optional(),
  data: z.record(z.string(), z.unknown()).optional(),
  actions: z.array(pushNotificationActionSchema).optional(),
  url: z.url({ error: "URL must be a valid URL" }).optional(),
}) satisfies z.ZodType<PushNotification>;

export type {
  PushNotification,
  PushNotificationAction,
} from "../types/push-notification";
```

## Examples

```typescript
// Source: https://developer.mozilla.org/en-US/docs/Web/API/Notification
// Captured: 2026-05
import type {
  PushNotificationAction,
  PushNotification,
} from "../types/push-notification";

const replyAction = {
  action: "reply",
  title: "Reply",
  icon: "https://cdn.example.com/icons/reply.png",
} as const satisfies PushNotificationAction;

const dismissAction = {
  action: "dismiss",
  title: "Dismiss",
} as const satisfies PushNotificationAction;

export const pushNotificationActionExamples = {
  reply: replyAction,
  dismiss: dismissAction,
  view: {
    action: "view",
    title: "View",
    icon: "https://cdn.example.com/icons/view.png",
  } satisfies PushNotificationAction,
} as const;

const message = {
  title: "New message from Jenny",
  body: "Hey, can you take a look at the PR when you get a chance?",
  icon: "https://cdn.example.com/icons/message.png",
  badge: "https://cdn.example.com/icons/badge.png",
  image: "https://cdn.example.com/images/preview.png",
  tag: "message-thread-123",
  data: { thread_id: "thread_123", sender_id: "user_321" },
  actions: [replyAction, dismissAction],
  url: "https://app.example.com/threads/thread_123",
} as const satisfies PushNotification;

export const pushNotificationExamples = {
  message,
  alertOnly: {
    title: "Production alert",
    body: "Service X is degraded.",
    tag: "ops-alert",
    url: "https://status.example.com",
  } satisfies PushNotification,
  silentDataMessage: {
    title: "Sync",
    data: { sync_id: "sync_001" },
  } satisfies PushNotification,
  minimal: { title: "Hello" } satisfies PushNotification,
  promotional: {
    title: "20% off this week",
    body: "Limited-time sale on all widgets.",
    image: "https://cdn.example.com/images/sale-banner.png",
    url: "https://shop.example.com/sale",
  } satisfies PushNotification,
} as const;
```
