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.
Use it in Next.js
"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>
);
}"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() };
}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
- One command
npx shadcn@latest add https://teodoravadani.github.io/qodesign-free/r/toast-stack.json - 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.