Interactive Playground
Customize your notification in real-time
Content
Customization
Style Customization
Live Preview
Get Started in Seconds
Choose your preferred installation method and start building amazing user experiences.
📦 NPM
Perfect for modern build tools and bundlers
🌐 CDN
Quick setup for prototypes and simple projects
Simple & Powerful API
Get up and running with just a few lines of code. No complex configuration needed.
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/notify-zh"></script>
</head>
<body>
<script>
// window.notify is ready to use
notify.success({ message: 'Operation successful!' });
notify.error({ message: 'Something went wrong' });
notify.warning({ message: 'Be careful' });
notify.info({ message: 'Important information' });
// With custom options
notify.success({
message: 'Custom message',
time: 5000,
position: 'top-right',
closable: true
});
</script>
</body>
</html>---
// src/pages/index.astro
---
<html>
<head>
<title>Astro + notify-zh</title>
</head>
<body>
<button id="notify-btn">Show Notification</button>
<script>
import notify from 'notify-zh';
document.getElementById('notify-btn').addEventListener('click', () => {
notify.success({
message: 'Hello from Astro!',
position: 'top-right',
time: 3000
});
});
</script>
</body>
</html>import React from 'react';
import notify from 'notify-zh';
function App() {
const handleClick = () => {
notify.success({ message: 'Hello from React!' });
};
const showError = () => {
notify.error({
message: 'Something went wrong!',
time: 5000,
position: 'bottom-right'
});
};
// notify.promise(): loading → success/error automatically
const saveData = () => {
notify.promise(fetch('/api/save'), {
loading: 'Saving…',
success: 'Saved!',
error: 'Failed to save'
});
};
return (
<div>
<button onClick={handleClick}>Success</button>
<button onClick={showError}>Error</button>
<button onClick={saveData}>Save (promise)</button>
</div>
);
}
export default App;<template>
<div>
<button @click="showSuccess">Success</button>
<button @click="showError">Error</button>
<button @click="showWarning">Warning</button>
<button @click="showInfo">Info</button>
</div>
</template>
<script>
import notify from 'notify-zh';
export default {
name: 'NotificationDemo',
methods: {
showSuccess() {
notify.success({ message: 'Operation completed successfully!' });
},
showError() {
notify.error({ message: 'An error occurred!' });
},
showWarning() {
notify.warning({ message: 'Please be careful!' });
},
showInfo() {
notify.info({
message: 'Here is some information',
position: 'top-left',
time: 4000
});
}
}
};
</script>// app/page.js (App Router)
'use client';
import notify from 'notify-zh';
export default function Home() {
// SSR-safe: calls are no-ops on the server, no window guards needed
const handleSubmit = (e) => {
e.preventDefault();
notify.promise(fetch('/api/submit'), {
loading: 'Submitting…',
success: 'Form submitted successfully!',
error: 'Failed to submit form'
});
};
return (
<div>
<h1>Next.js + notify-zh</h1>
<form onSubmit={handleSubmit}>
<button type="submit">Submit</button>
</form>
</div>
);
}// app.component.ts
import { Component } from '@angular/core';
import notify from 'notify-zh';
@Component({
selector: 'app-root',
template: `
<div>
<h1>Angular + notify-zh</h1>
<button (click)="showSuccess()">Success</button>
<button (click)="showError()">Error</button>
<button (click)="showWarning()">Warning</button>
<button (click)="showInfo()">Info</button>
</div>
`
})
export class AppComponent {
title = 'angular-notify-zh';
showSuccess() {
notify.success({ message: 'Task completed successfully!' });
}
showError() {
notify.error({ message: 'An error has occurred!' });
}
showWarning() {
notify.warning({ message: 'Warning: Please check your input!' });
}
showInfo() {
notify.info({
message: 'Information: Process started',
time: 6000,
position: 'center-bottom'
});
}
}Why Choose notify-zh?
See how we stack up against the most popular notification libraries
🚀 Performance
At just ~2.7KB, notify-zh is one of the lightest libraries on the market without sacrificing functionality.
🎨 Flexibility
Native Tailwind CSS support and 7 different positions for maximum customization.
⚡ Simplicity
Intuitive and easy-to-use API, perfect for projects of any size.
Frequently asked questions
Straight answers about SSR, styling, security and CSP — the same FAQ that ships in the README.
The toast doesn't appear in Next.js/Nuxt — why?
Since v1.1.0 all calls are SSR-safe no-ops on the server, so nothing crashes — but a toast fired during server render never shows. Fire notifications from client-side events (clicks, effects), and in the App Router use 'use client' components.
Can a notification stay until the user closes it?
Yes: notify.warning({ message: '…', time: Infinity, closable: true }).
How do I use Tailwind or Bootstrap classes?
Set disableDefaultStyles: true and map your classes via classNames in notify.config(). When a per-type class is set, the library skips its inline background so your class always wins.
Is icon.el safe?
message and title are always rendered as plain text (XSS-safe). Only icon.el is injected as HTML so you can pass inline SVG — never pass user-generated content to it.
Does it work with a strict CSP (no inline styles)?
The default styles are injected as a <style> tag, which requires style-src to allow it. With a strict CSP, set disableDefaultStyles: true and style toasts with your own stylesheet classes via classNames.
Why doesn't the toast auto-close while I hover it?
That's pauseOnHover (on by default) — the timer resumes when the pointer leaves. Disable with notify.config({ pauseOnHover: false }).
Support the project
notify-zh is free and MIT-licensed. If it saved you a dependency, a star or a coffee keeps it moving.
You can also contribute code — issues and PRs welcome onGitHub.