Toast after a server action

Wrap the server action in toast.promise: a spinner while it runs, a check when it returns, the error message if it throws. Free.

Get it freeOpen the demoReact · Tailwind · TypeScript

Use it in Next.js

app/settings/SaveButton.tsx

"use client";
import { toast } from "@/components/toast-stack/ToastStack";
import { saveSettings } from "./actions";

export function SaveButton({ name }: { name: string }) {
  return (
    <button
      onClick={() =>
        toast.promise(saveSettings(name), {
          loading: { title: "Saving…" },
          success: (r) => ({ title: "Saved", description: `Updated ${r.updatedAt}` }),
          error: (e) => ({ title: "Couldn't save", description: e instanceof Error ? e.message : undefined }),
        })
      }
    >
      Save
    </button>
  );
}

app/settings/actions.ts

"use server";

export async function saveSettings(name: string) {
  if (!name.trim()) throw new Error("Name can't be empty");
  // write to your database here
  return { updatedAt: new Date().toLocaleTimeString() };
}

app/layout.tsx

import { Toaster } from "@/components/toast-stack/ToastStack";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Toaster />
      </body>
    </html>
  );
}

Good to know

  • Mount one Toaster in the root layout. toast() then works from any client component.
  • The spinner stays up for at least 600 ms so fast actions don't flash.
  • In production Next.js hides the text of errors thrown in server actions. To show a specific message, return { error } from the action instead of throwing.
  • Toasts can't be called from server components. Call them in the client code that runs the action.

Install

  1. One commandnpx shadcn@latest add https://teodoravadani.github.io/qodesign-free/r/toast-stack.json
  2. Or ask your AIPaste PROMPT.md into Cursor, Lovable or v0.

Props

toast.promise
(promise, { loading, success, error })
toast.success / error
one-off toasts
Toaster duration
auto-dismiss in ms
visibleToasts
cards in the collapsed stack

How qodesign compares

  • qodesign vs UiverseUiverse is best for: single small elements: buttons, loaders, toggles, checkboxes, inputs.
  • qodesign vs AnimataAnimata is best for: free animated building blocks you copy and adapt.

All comparisons, with prices read on each library's own site.

Questions

Is it a sonner replacement?

It covers the same everyday calls (toast, success, error, promise) with a stacked deck look. Check that it has the options you use before swapping.

Is it free?

Yes. MIT licence.

Can Cursor or v0 add it for me?

Yes. The folder has a PROMPT.md. Paste it into Cursor, Lovable, v0 or Claude Code.

Does the toaster work in Next.js?

Yes, as a client component. Keep "use client" at the top of the file that renders it, as in the snippet above. App Router and Pages Router both work.

Toast after a server action in Next.js (loading → success, free) · qodesign