# Introduction > What expo-hot-toast is, what it draws on each platform, and when to use it. expo-hot-toast shows toasts in Expo and React Native apps. You call `toast.success('Saved')` from anywhere, and one `` near the root of your app draws it. ```tsx toast.success('Changes saved'); toast.error('Could not reach the server'); toast.promise(upload(photo), { loading: 'Uploading photo…', success: 'Photo uploaded', error: 'Upload failed', }); ``` ## What it draws | Platform | Surface | |---|---| | iOS 26 and later | Apple's Liquid Glass, through `expo-glass-effect` | | iOS 26 with Reduce Transparency on | An opaque surface | | iOS before 26 | An opaque surface | | Android | A Material 3 snackbar at the bottom, in light and dark | | Web | Frosted glass: a backdrop blur under a translucent fill | The opaque surface is designed for its platform: a solid fill, border and shadow. It does not imitate glass. On Android it follows Material 3's snackbar, as Android apps' own messages do; `` uses the pill there too. See [Customising](https://vanitascaesar1.github.io/expo-hot-toast/docs/md/customizing.md#presets). On the web, where browsers can blur what is behind an element, toasts are frosted instead; anyone who prefers reduced transparency gets the opaque surface there too. ## The API The calls follow [react-hot-toast](https://react-hot-toast.com), the web library: `toast`, `toast.success`, `toast.promise`, ``, `` and `useToaster` work as they do there. react-hot-toast itself renders DOM elements, so it cannot run in a native app; this package rebuilds its API on native views. If you know it from the web, read [Coming from react-hot-toast](https://vanitascaesar1.github.io/expo-hot-toast/docs/md/coming-from-react-hot-toast.md) for the differences. Beyond that API, it adds what a phone needs: - **A queue.** Three toasts show per position; the rest wait their turn. - **Gestures.** Flick a toast away like a notification; press and hold to pause every timer. - **A collapsed stack**, if you want one: older toasts tuck behind the newest and fan out when pressed. - **Actions and a close button**, for Undo and for toasts people need to clear. - **A description line and rich colours** for outcomes that need more. - **Deduplication**, so twenty identical calls show one toast. - **Accessibility**: screen reader announcements, Reduce Motion, Reduce Transparency, capped font scaling and a haptic for success and error. ## Next - [Install it](https://vanitascaesar1.github.io/expo-hot-toast/docs/md/installation.md) - [Show your first toast](https://vanitascaesar1.github.io/expo-hot-toast/docs/md/quick-start.md) --- # Installation > Install the package and its peer dependencies, and set up the app root. ## Install the package > [!NOTE] > It is not on npm yet. Install it from GitHub; npm builds it after cloning, > which takes a minute or two. ```sh npm install github:VanitasCaesar1/expo-hot-toast ``` ## Install the peer dependencies > [!TIP] > Building a React web app without React Native (Next.js, Vite)? Skip this > step and follow [Web apps](https://vanitascaesar1.github.io/expo-hot-toast/docs/md/web.md) instead. ```sh npx expo install expo-glass-effect expo-haptics react-native-reanimated \ react-native-worklets react-native-gesture-handler \ react-native-safe-area-context react-native-svg ``` > [!TIP] > Use `npx expo install` rather than `npm install`, so you get the versions > that match your Expo SDK. ## Check the Babel plugin **Expo:** nothing to do. `babel-preset-expo` adds the Worklets plugin automatically when `react-native-worklets` is installed. **React Native without Expo's preset:** add the plugin last in `babel.config.js`: ```js title="babel.config.js" module.exports = { presets: ['module:@react-native/babel-preset'], plugins: ['react-native-worklets/plugin'], }; ``` ## Wrap the app root Gestures need a `GestureHandlerRootView` at the root, and the Toaster reads safe-area insets from a `SafeAreaProvider`. Expo Router already renders a `SafeAreaProvider`; add the other. ```tsx title="App.tsx" {3,10} import { GestureHandlerRootView } from 'react-native-gesture-handler'; import { SafeAreaProvider } from 'react-native-safe-area-context'; import { Toaster } from 'expo-hot-toast'; export default function App() { return ( ); } ``` Render `` once, after the rest of the app, so toasts draw on top. ## Requirements | | | |---|---| | Expo SDK | 55 or later (tested on 57) | | React Native | 0.80 or later (tested on 0.86) | | React | 19 | | Reanimated | 4 or later, with `react-native-worklets` | | Liquid Glass | An app built with the iOS 26 SDK (Xcode 26 or later), running on iOS 26 | Everything else falls back to the opaque surface, so the same build runs on older iOS and on Android. ## Next [Show your first toast](https://vanitascaesar1.github.io/expo-hot-toast/docs/md/quick-start.md). --- # Web apps > Use the same toasts in a plain React app (Next.js, Vite) with no React Native. `expo-hot-toast/web` is the library for React DOM apps: Next.js, Vite, Remix, or anything else that renders with `react-dom`. It is the same `toast()` API, store, queue, presets, rich toasts and theme tokens as the native build, drawn with DOM and CSS in the same frosted glass. It needs no React Native, React Native Web or Reanimated. > [!NOTE] > An Expo app that also runs on the web does not need this entry. The main > `expo-hot-toast` import already works there, through React Native Web. ## Install ```sh npm install github:VanitasCaesar1/expo-hot-toast ``` The React Native packages are optional peers, so a web app installs none of them. The only peers it needs are `react` and `react-dom` 19: the stylesheet is hoisted into the document head by React DOM 19, so with React DOM 18 the toasts render unstyled. ## Add the Toaster ```tsx title="app/layout.tsx (Next.js)" import { Toaster } from 'expo-hot-toast/web'; export default function RootLayout({ children }: { children: React.ReactNode }) { return ( {children} ); } ``` The bundle starts with `'use client'`, which the App Router needs for a client component. Its stylesheet comes with the Toaster as a React 19 hoisted `