# How to Configure the Notification Provider with Sonner in refine-shadcn

> Easily configure Sonner notifications in refine-shadcn. Learn how to import notificationProvider, pass it to Refine, and render the Toaster component for seamless alerts.

- Repository: [Ferdi ÜNAL/refine-shadcn](https://github.com/ferdiunal/refine-shadcn)
- Tags: how-to-guide
- Published: 2026-03-01

---

**To configure Sonner notifications in refine-shadcn, import the `notificationProvider` from `@ferdiunal/refine-shadcn`, pass it to the `<Refine>` component's `notificationProvider` prop, and ensure the `<Toaster />` component is rendered in your component tree.**

The `ferdiunal/refine-shadcn` repository ships with a complete, ready-made notification system that integrates the Sonner toast library with Refine's core notification API. This implementation eliminates boilerplate by mapping Refine's `NotificationProvider` contract directly to Sonner's `toast` methods, providing immediate support for success, error, and loading states.

## Setting Up the Notification Provider

The notification provider is implemented in [`packages/theme/src/providers/notificationProvider.ts`](https://github.com/ferdiunal/refine-shadcn/blob/main/packages/theme/src/providers/notificationProvider.ts). It exports a concrete implementation of Refine's `NotificationProvider` interface that translates Refine notification calls into Sonner toast invocations.

```typescript
// packages/theme/src/providers/notificationProvider.ts
import { NotificationProvider } from "@refinedev/core";
import { toast } from "sonner";

export const notificationProvider: NotificationProvider = {
    open: ({ key, message, description, type }) => {
        if (type === "success") {
            toast.success(message, { description, id: key });
        }
        if (type === "error") {
            toast.error(message, { description, id: key });
        }
        if (type === "progress") {
            toast.loading(message, { description, id: key });
        }
    },
    close: (key) => toast.dismiss(key),
};

export const useNotificationProvider = (): NotificationProvider => notificationProvider;

```

The provider handles three notification types:
- **success**: Maps to `toast.success()`
- **error**: Maps to `toast.error()`
- **progress**: Maps to `toast.loading()` for asynchronous operations

Each call passes a unique `key` as the toast ID, enabling programmatic closing via the `close` method using `toast.dismiss()`.

## Rendering the Sonner Toaster Component

To display notifications, you must render the Sonner `<Toaster>` component somewhere in your application hierarchy. The refine-shadcn theme provides a wrapped version in [`packages/theme/src/ui/sonner.tsx`](https://github.com/ferdiunal/refine-shadcn/blob/main/packages/theme/src/ui/sonner.tsx) that integrates with `next-themes` for automatic dark mode support.

```tsx
// packages/theme/src/ui/sonner.tsx
"use client";

import { useTheme } from "next-themes";
import { Toaster as Sonner, ToasterProps } from "sonner";

const Toaster = ({ ...props }: ToasterProps) => {
  const { theme = "system" } = useTheme();

  return (
    <Sonner
      theme={theme as ToasterProps["theme"]}
      className="toaster group"
      style={{
        "--normal-bg": "var(--popover)",
        "--normal-text": "var(--popover-foreground)",
        "--normal-border": "var(--border)",
      } as React.CSSProperties}
      {...props}
    />
  );
};

export { Toaster };

```

If you use the `BaseLayout` component from refine-shadcn, the `<Toaster />` is already included at the layout root in [`packages/theme/src/layouts/base.tsx`](https://github.com/ferdiunal/refine-shadcn/blob/main/packages/theme/src/layouts/base.tsx):

```tsx
// packages/theme/src/layouts/base.tsx
import { Toaster, TooltipProvider } from "@/ui";

<TooltipProvider>
  {children}
  <Toaster />
</TooltipProvider>

```

**Note:** If you implement a custom layout instead of `BaseLayout`, you must manually import and render `<Toaster />` from `@ferdiunal/refine-shadcn` (or from `@/ui/sonner` in internal packages) to ensure notifications appear.

## Wiring the Provider into Your Refine Application

Connect the notification provider to your Refine application by passing it to the `<Refine>` component's `notificationProvider` prop. The Vite-React template in the repository demonstrates this pattern in [`templates/vite-react/src/App.tsx`](https://github.com/ferdiunal/refine-shadcn/blob/main/templates/vite-react/src/App.tsx):

```tsx
// templates/vite-react/src/App.tsx
import { DefaultLayout, notificationProvider } from "@ferdiunal/refine-shadcn";
import { Refine } from "@refinedev/core";

function App() {
  return (
    <Refine
      routerProvider={routerProvider}
      dataProvider={dataProvider(API_URL)}
      resources={resources}
      i18nProvider={i18nProvider}
      notificationProvider={notificationProvider}
    >
      <DefaultLayout>
        {/* Your routes */}
      </DefaultLayout>
    </Refine>
  );
}

```

Once wired, any notification triggered through Refine's API will automatically render as a Sonner toast with the styling and positioning configured in the `<Toaster />` component.

## Triggering Notifications in Your Components

With the provider configured, use the `useNotification` hook from `@refinedev/core` to display notifications in your components. The hook provides an `open` method that accepts the same parameters mapped in the provider implementation.

```tsx
import { useNotification } from "@refinedev/core";

export const MyComponent = () => {
  const { open, close } = useNotification();

  const handleSave = async () => {
    const key = open?.({ 
      type: "progress", 
      message: "Saving changes…" 
    });
    
    try {
      await saveData();
      open?.({ 
        key, 
        type: "success", 
        message: "Changes saved successfully!" 
      });
    } catch (error) {
      open?.({ 
        key, 
        type: "error", 
        message: "Failed to save", 
        description: String(error) 
      });
    }
  };

  return <button onClick={handleSave}>Save</button>;
};

```

The `key` parameter ensures that progress notifications are replaced by success or error states rather than stacking multiple toasts. If you need to manually dismiss a notification, call `close(key)` or use the `toast.dismiss()` method directly from Sonner.

## Summary

- **Import** the `notificationProvider` from `@ferdiunal/refine-shadcn` (located at [`packages/theme/src/providers/notificationProvider.ts`](https://github.com/ferdiunal/refine-shadcn/blob/main/packages/theme/src/providers/notificationProvider.ts))
- **Pass** the provider to the `<Refine>` component via the `notificationProvider` prop to enable Sonner integration
- **Render** the `<Toaster />` component in your layout (automatically included in `BaseLayout`, manual placement required for custom layouts)
- **Use** the `useNotification` hook from `@refinedev/core` to trigger Sonner toasts with success, error, and progress types

## Frequently Asked Questions

### Where is the notification provider implemented in refine-shadcn?

The provider is implemented in [`packages/theme/src/providers/notificationProvider.ts`](https://github.com/ferdiunal/refine-shadcn/blob/main/packages/theme/src/providers/notificationProvider.ts) according to the `ferdiunal/refine-shadcn` source code. It exports a `notificationProvider` object that implements Refine's `NotificationProvider` interface by mapping notification types to Sonner's `toast.success()`, `toast.error()`, and `toast.loading()` methods.

### Do I need to manually render the Sonner Toaster component?

If you use the `BaseLayout` or `DefaultLayout` from refine-shadcn, the `<Toaster />` is already rendered internally at [`packages/theme/src/layouts/base.tsx`](https://github.com/ferdiunal/refine-shadcn/blob/main/packages/theme/src/layouts/base.tsx). If you use a custom layout, you must manually import and render the `Toaster` component from `@ferdiunal/refine-shadcn` (or `@/ui/sonner` in monorepo setups) to ensure notifications are visible.

### How does the Sonner integration handle dark mode themes?

The `Toaster` wrapper in [`packages/theme/src/ui/sonner.tsx`](https://github.com/ferdiunal/refine-shadcn/blob/main/packages/theme/src/ui/sonner.tsx) uses the `useTheme` hook from `next-themes` to detect the current theme mode. It passes this theme value to Sonner's `theme` prop and injects CSS variables (`--normal-bg`, `--normal-text`, `--normal-border`) that reference the shadcn/ui design tokens, ensuring toasts match your application's color scheme automatically.

### Can I customize the notification duration or styling?

Yes. While the default provider uses Sonner's default durations, you can customize the `<Toaster />` component by passing props like `duration`, `position`, or `toastOptions` when rendering it in your layout. For per-notification customization, you would need to extend the `notificationProvider` implementation to pass additional options through the `open` method's payload.