# Announcement banner

> The newest live announcement for the user and organization, with a dismiss button.

- Block: [announcements](https://bettersupabase.com/blocks/announcements.md)
- Kind: component
- Hook: `useAnnouncements` from `better-supabase/blocks/announcements/react`
- Page: https://bettersupabase.com/recipes/announcement-banner

## Install the block

```bash
npx better-supabase add announcements
```

## Web (Next.js)

Add the shadcn components:

```bash
npx shadcn add alert button
```

From `apps/examples/nextjs/src/features/announcements/components/announcement-banner.tsx` (https://github.com/ScaleDockHQ/better-supabase/blob/main/apps/examples/nextjs/src/features/announcements/components/announcement-banner.tsx):

```tsx
"use client";

import { useAnnouncements } from "better-supabase/blocks/announcements/react";
import { MegaphoneIcon, XIcon } from "lucide-react";
import { useExtracted } from "next-intl";

import {
  Alert,
  AlertAction,
  AlertDescription,
  AlertTitle,
} from "@/components/ui/alert";
import { Button } from "@/components/ui/button";

/**
 * The newest live announcement for this user and organization. Loads in
 * the browser and reloads on the module's broadcast, so it adds nothing to
 * the server render.
 */
export function AnnouncementBanner({
  organizationId,
}: {
  organizationId: string | null;
}) {
  const t = useExtracted("announcements");

  const { items, dismiss } = useAnnouncements({
    organizationId,
    schema: "api",
  });

  const announcement = items?.[0];

  if (!announcement) {
    return null;
  }

  return (
    <Alert
      variant={announcement.severity === "critical" ? "destructive" : "default"}
      data-testid="announcement"
    >
      <MegaphoneIcon />
      <AlertTitle>{announcement.title}</AlertTitle>
      {announcement.body ? (
        <AlertDescription>{announcement.body}</AlertDescription>
      ) : null}
      {announcement.dismissible ? (
        <AlertAction>
          <Button
            variant="ghost"
            size="icon-sm"
            aria-label={t("Dismiss")}
            onClick={() => void dismiss(announcement.id)}
          >
            <XIcon />
          </Button>
        </AlertAction>
      ) : null}
    </Alert>
  );
}
```

## Prompt

Paste this into a coding agent to build the recipe in your app.

### Web

```text
Build "Announcement banner" in a React web app that uses shadcn/ui components. The newest live announcement for the user and organization, with a dismiss button.

It uses the better-supabase `announcements` block (Announcements). It calls the hook `useAnnouncements` from `better-supabase/blocks/announcements/react`.

Steps:

1. If the app doesn't have the block yet, add the SQL with `npx better-supabase add announcements` and apply the migration.
2. Add the shadcn components the recipe uses: `npx shadcn add alert button`.
3. The recipe needs no glue: the hook calls the block from the client.
4. Write the component. Call `useAnnouncements` from `better-supabase/blocks/announcements/react`, starting from the recipe's snippet (`apps/examples/nextjs/src/features/announcements/components/announcement-banner.tsx`). Adapt it to the app's existing components, styling and data loading instead of copying it as is.
5. Check the result against the recipe and the block's docs: it typechecks, it calls the same hook, and it handles the loading and empty states the snippet handles.

Read the full code first:

- Recipe: https://bettersupabase.com/recipes/announcement-banner.md
- Block docs: https://bettersupabase.com/docs/blocks/announcements
```
