{"id":11935,"library":"remix-toast","title":"Server-Side Toast Notifications for Remix","description":"remix-toast provides utility functions to manage server-side toast notifications within Remix applications, leveraging web standards like `Set-Cookie` for flash messages. It seamlessly integrates with Remix's `loader` and `action` functions and supports React Router v7. The current stable version is 4.0.0, which includes an upgrade to Zod v4. The package appears to have an active release cadence, with frequent updates (minor and patch releases) to address bug fixes, introduce new features like `replaceWithFlash`, and maintain compatibility with new versions of Remix and React Router (e.g., v7.9+ for `react-router`). Key differentiators include its server-side first approach, middleware support for global toast management, and flexible session storage configuration, allowing custom utility creation with `createToastUtilsWithCustomSession`.","status":"active","version":"4.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/forge-42/remix-toast","tags":["javascript","Remix","Remix.run","toast","notifications","utilities","typescript"],"install":[{"cmd":"npm install remix-toast","lang":"bash","label":"npm"},{"cmd":"yarn add remix-toast","lang":"bash","label":"yarn"},{"cmd":"pnpm add remix-toast","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Peer dependency for routing context and utilities, specifically `>=7.9.0` for full compatibility with middleware API stabilization.","package":"react-router","optional":false}],"imports":[{"note":"Primary utility for creating toast messages in Remix actions/loaders. Package is ESM-first.","wrong":"const { createToast } = require('remix-toast');","symbol":"createToast","correct":"import { createToast } from 'remix-toast';"},{"note":"Used to extract the toast message from the request context, requires specific middleware path since v3.0.0.","wrong":"import { getToast } from 'remix-toast';","symbol":"getToast","correct":"import { getToast } from 'remix-toast/middleware';"},{"note":"Enables global toast management, allowing toasts to be set anywhere. Path is critical and the 'unstable' prefix indicates potential future API changes. Stabilized for RR v7.9+ in v3.3.0.","wrong":"import { unstable_toastMiddleware } from 'remix-toast';","symbol":"unstable_toastMiddleware","correct":"import { unstable_toastMiddleware } from 'remix-toast/middleware';"},{"note":"React hook for accessing toast data in client-side components. ESM import required.","wrong":"const useToast = require('remix-toast').useToast;","symbol":"useToast","correct":"import { useToast } from 'remix-toast';"}],"quickstart":{"code":"import { createCookieSessionStorage, redirect } from '@remix-run/node';\nimport { createToast, getToast, unstable_toastMiddleware } from 'remix-toast/middleware';\nimport { json } from '@remix-run/react';\nimport type { ActionFunctionArgs, LoaderFunctionArgs } from '@remix-run/node';\nimport { useLoaderData } from '@remix-run/react';\n\n// 1. Configure a session storage (replace with your actual session store)\nconst { getSession, commitSession } = createCookieSessionStorage({\n  cookie: {\n    name: '__session',\n    httpOnly: true,\n    maxAge: 60 * 60 * 24 * 7, // 1 week\n    secrets: [process.env.SESSION_SECRET ?? 'super-secret'],\n    secure: process.env.NODE_ENV === 'production',\n  },\n});\n\n// 2. Setup toast middleware\nexport const { toast, flash } = createToast(getSession, commitSession);\n\nexport const loader = async ({ request }: LoaderFunctionArgs) => {\n  const { toast, headers } = await getToast(request);\n  // Simulate fetching some data\n  const data = { message: 'Welcome back!' };\n  return json({ data, toast }, { headers });\n};\n\nexport const action = async ({ request }: ActionFunctionArgs) => {\n  const formData = await request.formData();\n  const email = formData.get('email');\n\n  if (email === 'error@example.com') {\n    return await toast.error(redirect('/'), { message: 'Invalid email address.' });\n  }\n\n  return await toast.success(redirect('/'), { message: 'Subscription successful!' });\n};\n\nexport default function Index() {\n  const { toast } = useLoaderData<typeof loader>();\n\n  return (\n    <div>\n      {toast && (\n        <div style={{ padding: '10px', background: toast.type === 'error' ? 'red' : 'green', color: 'white' }}>\n          {toast.message}\n        </div>\n      )}\n      <h1>Remix Toast Example</h1>\n      <form method=\"post\">\n        <input type=\"email\" name=\"email\" placeholder=\"Enter email\" />\n        <button type=\"submit\">Subscribe</button>\n      </form>\n    </div>\n  );\n}","lang":"typescript","description":"This quickstart demonstrates how to set up server-side toast notifications in a Remix application using `remix-toast`. It covers configuring a session storage, initializing the `toast` utility, extracting and displaying toasts in a `loader` and `action`, and rendering them on the client-side."},"warnings":[{"fix":"Update all instances of `jsonSuccess`, `jsonError`, etc., to `dataSuccess`, `dataError` respectively.","message":"The `json*` utilities (e.g., `jsonSuccess`) were renamed to `data*` (e.g., `dataSuccess`) to align with React Router v7 conventions.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Implement the middleware setup in your `root.tsx` as described in the v3.0.0 changelog, specifically importing from `remix-toast/middleware` and handling `getToast` in your root loader.","message":"Version 3.0.0 introduced a new 'Middleware mode' for global toast management. This requires changes to `root.tsx` to import `getToast` and `unstable_toastMiddleware` from `remix-toast/middleware` and pass the toast to the client side.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Ensure your `react-router` peer dependency is at least `7.9.0` (or higher if specified by `remix-toast`) to guarantee stable middleware functionality.","message":"The `unstable_toastMiddleware` API was stabilized for `react-router` v7.9+ in version 3.3.0. Using older versions of `react-router` might lead to unexpected behavior or API mismatches when relying on the middleware.","severity":"gotcha","affected_versions":"<3.3.0"},{"fix":"Review your project's direct `zod` dependencies and upgrade them to v4 if conflicts arise or if you encounter type mismatches related to `zod` schemas used in conjunction with `remix-toast`.","message":"Version 4.0.0 upgraded the internal dependency `zod` to v4. While this is primarily an internal change, if your application directly relies on `zod` and has specific version constraints, this upgrade might cause conflicts or require you to also upgrade your `zod` dependency.","severity":"breaking","affected_versions":">=4.0.0"},{"fix":"Update to `remix-toast` v3.4.0 or newer if you intend to use a `duration` of zero to control toast visibility programmatically without auto-hiding.","message":"When setting toasts, the `duration` parameter was made optional and can be set to zero. Older versions might not correctly handle a `duration` of zero or might require it to be a positive number.","severity":"gotcha","affected_versions":"<3.4.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure `getToast` and `unstable_toastMiddleware` are imported from `remix-toast/middleware` and not directly from `remix-toast`.","cause":"Incorrect import path for `getToast` or `unstable_toastMiddleware`.","error":"TypeError: (0 , remix_toast_middleware__WEBPACK_IMPORTED_MODULE_2__.getToast) is not a function"},{"fix":"Upgrade your `react-router` dependency to v7 or higher, or downgrade `remix-toast` to v1.x if you're stuck on an older `react-router` version.","cause":"Using `remix-toast` v2.0.0 or higher with an incompatible (older) version of `react-router`.","error":"Error: Your Remix application must be using React Router v7 to use remix-toast v2.0.0+"},{"fix":"Use ESM `import` statements for `remix-toast` as it's designed for modern Remix projects which are typically ESM. If forced to use CJS, configure your build system to transpile or adjust imports accordingly.","cause":"Attempting to use CommonJS `require()` syntax in an ESM-only environment, or vice-versa.","error":"ReferenceError: require is not defined in ES module scope"}],"ecosystem":"npm"}