# 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
`