Installation
Add Cloudlet from npm or the shadcn registry, check the peers, and import the CSS once.
Cloudlet installs as one package, @cloudlet/toast, or as a shadcn registry item that adds a small wrapper you own on top of the same package. Both end with a Toaster on screen and a controller you can call; pick the one that matches how your project manages components.
Until the release, the package installs from the archive that npm pack produces in the repository:
npm install /absolute/path/cloudlet-toast-1.0.0-rc.3.tgzInstall
Add the package. React 18 or 19, nothing else to configure.
npm install @cloudlet/toastImport the styles once, mount one Toaster per controller, call show from anywhere below it.
import '@cloudlet/toast/styles.css';
import { CloudletProvider, createCloudlet, Toaster, useCloudlet } from '@cloudlet/toast';
function SaveNotice() {
const cloudlet = useCloudlet();
return <button onClick={() => cloudlet.show({ title: 'Saved', kind: 'success' })}>Notify</button>;
}
// The browser application bootstrap creates and owns this controller.
export function Notifications({ controller }: { controller: ReturnType<typeof createCloudlet> }) {
return <CloudletProvider controller={controller}>
<SaveNotice />
<Toaster />
</CloudletProvider>;
}Requirements
- React and React DOM
^18.2.0 || ^19.0.0are peer dependencies. Use a matching pair: the same version ofreactandreact-dom. - ESM only. The package ships ES modules with TypeScript declarations; there is no CommonJS or UMD build. Deep imports into its internals are closed on purpose: everything public comes from
@cloudlet/toast. - No runtime dependencies. The springs and tweens that move the stack and the Island are Cloudlet's own.
- No Tailwind or shadcn/ui requirement. The npm package styles itself with plain CSS and custom properties; the shadcn item only bridges them to your tokens.
Import the styles
Cloudlet's CSS is one explicit file. Import it once, where your application imports its global CSS: the client entry of a single-page app, or the root layout of a Next.js App Router project.
import '@cloudlet/toast/styles.css';In the Next.js Pages Router, global CSS must come from the custom App, so the import goes into pages/_app.tsx. The stylesheet does not need a build plugin; under a strict Content Security Policy keep it external, as described in Styling & strict CSP.
The shadcn registry item
The toaster item copies two files into your project and adds @cloudlet/toast as a dependency:
components/ui/toaster.tsx: a thin"use client"adapter that renders the Provider and the Toaster for a controller you pass in. Every public Toaster option passes through unchanged.components/ui/toaster.css: a theme bridge that maps your shadcn tokens (--popover,--popover-foreground,--muted-foreground,--border,--ring,--accent,--font-sans) to Cloudlet's tokens.
Both files are yours to edit. The notification runtime itself stays in the package: the item copies no controller, renderer or animation code.
The wrapper deliberately does not create a controller. A client component owns it: an effect creates the instance and its cleanup disposes exactly that instance, which keeps React Strict Mode's replayed effects correct. That is the notification-owner.tsx example in the shadcn tab above. A controller is not serializable, so it never crosses from a Server Component into the client.
A few details of the bridge:
- The wrapper imports
@cloudlet/toast/styles.cssand then./toaster.css; keep that order. In the Pages Router, move both imports intopages/_app.tsxin the same order and remove them from the wrapper. - Define light tokens on
:rootand dark tokens on your.darkroot, then pass the matchingtheme="light"ortheme="dark"to the Toaster so the nativecolor-schemeagrees. - The tokens must be inherited by the portal container. A wrapper element around your React tree does not theme the default portal on
document.body.
Next steps
- Quick start: create the controller, mount the Toaster and show the first notification.
- Playground: every kind of notification on a button, with the exact call to copy.