npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ngx-signal-toast

v1.1.4

Published

Angular 21 Signals-based toast — zero animation dependency

Readme

 ███╗   ██╗ ██████╗ ██╗  ██╗      ███████╗██╗ ██████╗ ███╗  ██╗ █████╗ ██╗
 ████╗  ██║██╔════╝ ╚██╗██╔╝      ██╔════╝██║██╔════╝ ████╗ ██║██╔══██╗██║
 ██╔██╗ ██║██║  ███╗ ╚███╔╝ █████╗███████╗██║██║  ███╗██╔██╗██║███████║██║
 ██║╚██╗██║██║   ██║ ██╔██╗ ╚════╝╚════██║██║██║   ██║██║╚████║██╔══██║██║
 ██║ ╚████║╚██████╔╝██╔╝ ██╗      ███████║██║╚██████╔╝██║ ╚███║██║  ██║███████╗
 ╚═╝  ╚═══╝ ╚═════╝ ╚═╝  ╚═╝      ╚══════╝╚═╝ ╚═════╝ ╚═╝  ╚══╝╚═╝  ╚═╝╚══════╝

 ████████╗ ██████╗  █████╗ ███████╗████████╗
    ██║   ██╔═══██╗██╔══██╗██╔════╝╚══██╔══╝
    ██║   ██║   ██║███████║███████╗   ██║
    ██║   ██║   ██║██╔══██║╚════██║   ██║
    ██║   ╚██████╔╝██║  ██║███████║   ██║
    ╚═╝    ╚═════╝ ╚═╝  ╚═╝╚══════╝   ╚═╝

The most powerful Angular 21 toast library — built entirely on Signals

Zero @angular/animations · Zero Zone.js dependency · Zero HTML tags to add

🚀 Quick Start · 📖 API Reference · 🎨 Themes · 💡 Examples · ⚙️ Configuration


📋 Table of Contents


🤔 Why ngx-signal-toast?

🆚 Comparison with Other Toast Libraries

| Feature | ngx-signal-toast | ngx-toastr | hot-toast | |---|:---:|:---:|:---:| | Angular 21 native | ✅ | ❌ | ❌ | | Signals-first (no RxJS) | ✅ | ❌ | ❌ | | Zoneless compatible | ✅ | ❌ | ❌ | | @angular/animations free | ✅ | ❌ | ❌ | | Auto-inject container | ✅ | ❌ | ❌ | | 8 built-in themes | ✅ | ❌ | ❌ | | 6 layout styles | ✅ | ❌ | ❌ | | 9 positions | ✅ | ❌ | ❌ | | Native CSS animations | ✅ | ❌ | ❌ | | SSR safe | ✅ | ⚠️ | ⚠️ | | Zero dependencies | ✅ | ❌ | ❌ | | Promise API | ✅ | ❌ | ✅ | | TypeScript 5.5+ | ✅ | ⚠️ | ⚠️ |


✨ Features

  • 🎯 100% Signals — built with signal(), computed(), effect() — no RxJS at all
  • Zoneless Ready — works perfectly with Angular's new zoneless change detection
  • 🎨 8 Beautiful Themes — Default, Glassmorphism, Neumorphism, Aurora, Neon, Luxury, Material, Brutalist
  • 📐 6 Layout Styles — Default, Compact, Card, Pill, Sidebar, Banner
  • 📍 9 Positions — all corners, edges, and center
  • 🎬 5 Animation Presets — Slide, Fade, Bounce, Zoom, Flip — all via native CSS (no @angular/animations)
  • 🔄 Promise API — loading → success/error in one call
  • ⏸️ Pause on Hover — progress bar pauses when user hovers
  • 🎯 Action Buttons — add interactive buttons inside any toast
  • 📝 Update in Flight — update message/type/duration of an active toast
  • 🌍 RTL Support — full right-to-left text support
  • ARIA compliantrole="alert", aria-live, aria-label built-in
  • 🖥️ SSR SafeisPlatformBrowser guards throughout
  • 🎭 Custom Icons — emoji, component, or template ref
  • 🎨 Custom Body — inject your own component as toast body
  • 🔗 Auto-inject — no <nst-toast-container> HTML tag needed
  • 📦 ~0 extra dependencies — only @angular/core and @angular/common

📌 Version & Requirements

| Package | Version | |---|---| | ngx-signal-toast | 1.1.0 | | @angular/core | >= 21.0.0 | | @angular/common | >= 21.0.0 | | TypeScript | >= 5.5 | | Node.js | >= 20.0.0 |

⚠️ Angular 21 only. This library uses APIs introduced in Angular 21 (provideAppInitializer, signals-first DI). It will not work on older versions.


📦 Installation

# npm
npm install ngx-signal-toast

# yarn
yarn add ngx-signal-toast

# pnpm
pnpm add ngx-signal-toast

Using ng-add (recommended)

ng add ngx-signal-toast

The schematic will automatically:

  • Add provideNgxSignalToast() to your app.config.ts
  • Ask you to choose a default theme and position

🚀 Quick Start

Step 1 — Register the provider

Open app.config.ts and add provideNgxSignalToast():

// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideNgxSignalToast } from 'ngx-signal-toast';

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    provideNgxSignalToast({
      position: 'top-right',
      duration: 4000,
      theme: 'default',
    }),
  ],
};

✅ That's it. No <nst-toast-container> tag needed anywhere. The container is automatically injected into document.body.

Step 2 — Inject and use

// any.component.ts
import { Component, inject } from '@angular/core';
import { ToastService } from 'ngx-signal-toast';

@Component({
  selector: 'app-root',
  standalone: true,
  template: `<button (click)="showToast()">Show Toast</button>`,
})
export class AppComponent {
  private toast = inject(ToastService);

  showToast() {
    this.toast.success('Operation completed successfully!');
  }
}

🔧 Basic Usage

import { Component, inject } from '@angular/core';
import { ToastService } from 'ngx-signal-toast';

@Component({ ... })
export class MyComponent {
  private toast = inject(ToastService);

  // Basic types
  showSuccess() { this.toast.success('Saved successfully!'); }
  showError()   { this.toast.error('Something went wrong.'); }
  showWarning() { this.toast.warning('Please review your input.'); }
  showInfo()    { this.toast.info('Update available.'); }
  showLoading() { this.toast.loading('Loading your data...'); }

  // With a title
  showWithTitle() {
    this.toast.success('Your file has been uploaded.', {
      title: 'Upload Complete',
    });
  }

  // Custom duration (milliseconds)
  showLong() {
    this.toast.info('This stays for 10 seconds.', { duration: 10000 });
  }

  // Permanent (never auto-dismiss)
  showPermanent() {
    this.toast.warning('Action required.', { duration: 0 });
  }
}

🎯 Toast Types

| Method | Icon | Default Color | Use Case | |---|---|---|---| | toast.success(msg) | ✓ checkmark | Green #22c55e | Operation completed | | toast.error(msg) | ✗ cross | Red #f43f5e | Something failed | | toast.warning(msg) | ⚠ triangle | Amber #f59e0b | Needs attention | | toast.info(msg) | ℹ circle | Blue #3b82f6 | Informational | | toast.loading(msg) | ⟳ spinner | Purple #8b5cf6 | Async operation | | toast.show(msg, opts) | ★ star | Pink #ec4899 | Custom / flexible |


⚙️ Configuration

Pass options to provideNgxSignalToast() to set global defaults. Every option can be overridden per-toast.

provideNgxSignalToast({
  position:     'top-right',      // where toasts appear
  duration:     4000,             // auto-dismiss in ms (0 = never)
  theme:        'default',        // visual theme
  layout:       'default',        // layout style
  animation:    'slide',          // enter/leave animation
  maxToasts:    5,                // max visible at once
  showProgress: true,             // show countdown bar
  pauseOnHover: true,             // pause timer on hover
  closeOnClick: false,            // dismiss on toast click
  closable:     true,             // show close button
  dedupe:       false,            // prevent duplicate messages
  rtl:          false,            // right-to-left mode
  zIndex:       9999,             // CSS z-index of container
})

📚 All Options Reference

Global Config Options (provideNgxSignalToast)

| Option | Type | Default | Description | |---|---|---|---| | position | ToastPosition | 'top-right' | Where toasts appear on screen | | duration | number | 4000 | Auto-dismiss time in ms. 0 = never | | theme | ToastTheme | 'default' | Visual theme | | layout | ToastLayout | 'default' | Layout style | | animation | ToastAnimationPreset | 'slide' | Enter/leave animation | | maxToasts | number | 5 | Max toasts visible at once | | showProgress | boolean | true | Show countdown progress bar | | pauseOnHover | boolean | true | Pause timer when hovering | | closeOnClick | boolean | false | Dismiss when toast is clicked | | closable | boolean | true | Show the × close button | | dedupe | boolean | false | Suppress duplicate messages | | rtl | boolean | false | Right-to-left text direction | | zIndex | number | 9999 | CSS z-index of toast container |

Per-Toast Options (ToastOptions)

All global options above plus:

| Option | Type | Default | Description | |---|---|---|---| | id | string | auto | Custom ID for the toast | | title | string | '' | Bold title above the message | | type | ToastType | 'info' | Toast type (success/error/warning/info/loading/custom) | | group | string | '' | Group name for bulk dismiss | | hideIcon | boolean | false | Hide the type icon | | iconEmoji | string | — | Show an emoji as icon | | iconComponent | Type<any> | — | Angular component as icon | | iconTemplate | TemplateRef | — | Template ref as icon | | bodyComponent | Type<any> | — | Replace entire body with component | | ariaLabel | string | message | Accessibility label | | data | any | — | Attach any custom data | | styles | ToastCustomStyles | — | Per-toast style overrides | | actions | ToastAction[] | [] | Action buttons inside toast | | onOpen | () => void | — | Callback when toast appears | | onClose | () => void | — | Callback when toast dismisses |

ToastCustomStyles

| Property | Type | Description | |---|---|---| | accentColor | string | Icon and accent color (hex/rgb/hsl) | | background | string | Toast background color | | borderColor | string | Border color | | borderRadius | string \| number | Border radius (px or CSS string) | | titleColor | string | Title text color | | messageColor | string | Message text color | | iconBackground | string | Icon wrapper background |


🎨 Themes

Set globally or per-toast with theme: 'theme-name'.

| Theme | Description | |---|---| | default | Clean, modern dark card with subtle shadow | | glassmorphism | Frosted glass with blur and transparency | | neumorphism | Soft shadow depth, tactile feel | | aurora | Gradient border, northern-lights inspired | | neon | Glowing neon borders on dark background | | luxury | Gold accents, premium feel | | material | Google Material Design style | | brutalist | Raw, bold, high-contrast editorial style |

// Per-toast theme override
this.toast.success('Uploaded!', { theme: 'glassmorphism' });
this.toast.error('Failed!',     { theme: 'neon' });
this.toast.info('Note',         { theme: 'luxury' });

📐 Layouts

| Layout | Description | |---|---| | default | Standard card with icon, title, message | | compact | Slim single-line with small icon | | card | Colored top border accent bar | | pill | Rounded pill shape, centered content | | sidebar | Left colored stripe accent | | banner | Full-width banner style |

this.toast.info('Compact notification', { layout: 'compact' });
this.toast.success('Card style!',        { layout: 'card' });
this.toast.warning('Full width alert',   { layout: 'banner' });

📍 Positions

9 positions covering the entire viewport:

┌─────────────────────────────────────┐
│  top-left   top-center   top-right  │
│                                     │
│ center-left   center   center-right │
│                                     │
│ bottom-left bottom-center bot-right │
└─────────────────────────────────────┘

| Position | Value | |---|---| | Top Left | 'top-left' | | Top Center | 'top-center' | | Top Right | 'top-right' | | Center Left | 'center-left' | | Center | 'center' | | Center Right | 'center-right' | | Bottom Left | 'bottom-left' | | Bottom Center | 'bottom-center' | | Bottom Right | 'bottom-right' |

// Different positions per toast
this.toast.success('Top right',     { position: 'top-right' });
this.toast.error('Bottom center',   { position: 'bottom-center' });
this.toast.info('Center screen',    { position: 'center' });

🎬 Animations

All animations use native CSS — no @angular/animations package required.

| Preset | Enter | Leave | |---|---|---| | slide | Slides down from top + fade in | Slides up + fade out | | fade | Fade in + slight scale | Fade out + scale down | | bounce | Spring overshoot effect | Shrink + fade | | zoom | Scale from 50% | Scale to 50% + fade | | flip | 3D perspective rotate | Rotate back + fade |

this.toast.success('Bouncy!', { animation: 'bounce' });
this.toast.info('Flipping in', { animation: 'flip' });
this.toast.error('Zoomed', { animation: 'zoom' });

Accessibility: All animations are automatically disabled when the user has prefers-reduced-motion: reduce set in their OS settings.


🔘 Toast Actions

Add interactive buttons directly inside a toast:

this.toast.warning('Unsaved changes detected.', {
  title: 'Confirm Action',
  duration: 0,
  actions: [
    {
      label: 'Save',
      onClick: (id) => {
        this.saveData();
        // Toast auto-dismisses after action by default
      },
    },
    {
      label: 'Discard',
      style: 'danger',   // red danger style
      onClick: (id) => {
        this.discardChanges();
      },
      closeOnClick: true,
    },
  ],
});

ToastAction Options

| Property | Type | Default | Description | |---|---|---|---| | label | string | required | Button text | | onClick | (id: string) => void | required | Click handler | | style | 'default' \| 'danger' | 'default' | Button style | | closeOnClick | boolean | true | Auto-dismiss on click |


🔄 Promise Toast

Show loading → automatically switch to success or error when the promise resolves:

// Basic promise
await this.toast.promise(
  this.apiService.saveData(payload),
  {
    loading: 'Saving your data...',
    success: 'Saved successfully!',
    error:   'Failed to save. Please try again.',
  }
);

// With dynamic messages based on result
await this.toast.promise(
  this.userService.createUser(form),
  {
    loading: 'Creating account...',
    success: (user) => `Welcome, ${user.name}!`,
    error:   (err)  => `Error: ${err.message}`,
  },
  {
    position: 'top-center',
    theme: 'glassmorphism',
  }
);

⏳ Loading Toast

For long-running async operations you control manually:

// Show loading toast — returns a ToastRef
const ref = this.toast.loading('Uploading file...');

try {
  await this.uploadService.upload(file, (progress) => {
    // Update the message dynamically
    ref.update({ message: `Uploading... ${progress}%` });
  });

  // Switch to success when done
  ref.update({
    type: 'success',
    message: 'File uploaded successfully!',
    duration: 4000,  // now auto-dismiss
  });

} catch (error) {
  // Switch to error on failure
  ref.update({
    type: 'error',
    message: 'Upload failed. Please try again.',
    duration: 5000,
  });
}

🎭 Custom Icons

Emoji Icon

this.toast.success('Great job!', {
  iconEmoji: '🎉',
});

this.toast.info('Check this out', {
  iconEmoji: '👀',
});

Angular Component as Icon

@Component({
  standalone: true,
  template: `<svg ...><!-- your SVG --></svg>`,
})
export class MyIconComponent {}

// Use it
this.toast.success('Custom icon!', {
  iconComponent: MyIconComponent,
});

Template Ref as Icon

<ng-template #starIcon>
  <span class="material-icons">star</span>
</ng-template>
@ViewChild('starIcon') starIcon!: TemplateRef<any>;

showToast() {
  this.toast.success('Starred!', {
    iconTemplate: this.starIcon,
  });
}

Hide Icon Entirely

this.toast.info('No icon here', { hideIcon: true });

🖌️ Custom Styles

Override appearance per-toast using the styles option:

// Custom brand colors
this.toast.show('Custom branded toast!', {
  type: 'custom',
  styles: {
    accentColor:    '#FF6B6B',
    background:     '#1A1A2E',
    borderColor:    '#FF6B6B',
    borderRadius:   20,
    titleColor:     '#FFFFFF',
    messageColor:   '#CCCCCC',
    iconBackground: 'rgba(255,107,107,0.15)',
  },
});

// Combine with emoji icon
this.toast.show('🚀 Deployment triggered!', {
  type: 'custom',
  title: 'CI/CD Pipeline',
  iconEmoji: '🚀',
  styles: {
    accentColor: '#6C63FF',
    background: '#0F0F23',
  },
});

🎯 ToastRef — Update & Dismiss

Every toast.*() method returns a ToastRef for programmatic control:

const ref = this.toast.info('Processing...', { duration: 0 });

// Update any property of the active toast
ref.update({
  message: 'Almost done...',
  type: 'success',
  duration: 3000,   // starts auto-dismiss countdown
});

// Dismiss programmatically
ref.dismiss();

// Check the ID
console.log(ref.id); // 'nst-1-1234567890'

ToastRef API

| Method | Description | |---|---| | ref.id | Unique string ID of this toast | | ref.update(patch) | Update any toast option on the fly | | ref.dismiss() | Dismiss this toast immediately |


🗂️ Service Methods

// Show methods
toast.success(message, options?)  // → ToastRef
toast.error(message, options?)    // → ToastRef
toast.warning(message, options?)  // → ToastRef
toast.info(message, options?)     // → ToastRef
toast.loading(message, options?)  // → ToastRef
toast.show(message, options?)     // → ToastRef

// Promise helper
toast.promise(promise, messages, options?)  // → Promise<T>

// Dismiss methods
toast.dismiss(id)           // dismiss one by ID
toast.dismissAll()          // dismiss all visible toasts
toast.dismissByType('error')  // dismiss all of a type
toast.dismissByGroup('auth')  // dismiss by group name

// State signals (read-only)
toast.toasts()     // Signal<Toast[]>
toast.count()      // Signal<number>
toast.isEmpty()    // Signal<boolean>

🎨 CSS Variables

Customize the look globally using CSS custom properties in your styles.css:

:root {
  /* Layout */
  --nst-gap:    10px;   /* gap between stacked toasts */

  /* Per-theme overrides */
  --nst-bg:     #1f2937;
  --nst-color:  #f9fafb;
  --nst-shadow: 0 20px 60px rgba(0, 0, 0, 0.4);
  --nst-radius: 14px;
  --nst-border: none;
  --nst-font:   'Your Font', system-ui, sans-serif;
}

🖥️ SSR Support

ngx-signal-toast is fully SSR-safe. All browser APIs are guarded with isPlatformBrowser. The container is only injected in browser environments. No extra configuration needed for Angular Universal or any SSR setup.

// Works in SSR — library handles this internally
provideNgxSignalToast({ theme: 'default' })

♿ Accessibility

| Feature | Implementation | |---|---| | ARIA roles | role="alert" for errors, role="status" for others | | Live regions | aria-live="assertive" for errors, aria-live="polite" for others | | Labels | aria-label on every toast (defaults to message text) | | Close button | aria-label="Close notification" | | Reduced motion | All animations disabled via @media (prefers-reduced-motion: reduce) | | RTL support | Full direction: rtl support via rtl: true option | | Focus management | Close button focusable with keyboard |


💡 Examples

E-commerce — Cart Notification

addToCart(product: Product) {
  this.cartService.add(product);
  this.toast.success(`${product.name} added to cart`, {
    title: 'Cart Updated',
    layout: 'card',
    theme: 'default',
    iconEmoji: '🛒',
    duration: 3000,
    actions: [{
      label: 'View Cart',
      onClick: () => this.router.navigate(['/cart']),
    }],
  });
}

Auth — Login Flow

async login(credentials: LoginForm) {
  await this.toast.promise(
    this.authService.login(credentials),
    {
      loading: 'Signing you in...',
      success: (user) => `Welcome back, ${user.firstName}!`,
      error: 'Invalid email or password.',
    },
    { position: 'top-center', theme: 'glassmorphism' }
  );
}

File Upload with Progress

async uploadFile(file: File) {
  const ref = this.toast.loading(`Uploading ${file.name}...`, {
    duration: 0,
    closable: false,
  });

  try {
    await this.fileService.upload(file, (pct) => {
      ref.update({ message: `Uploading ${file.name}... ${pct}%` });
    });
    ref.update({ type: 'success', message: 'Upload complete!', duration: 3000 });
  } catch {
    ref.update({ type: 'error', message: 'Upload failed.', duration: 5000 });
  }
}

Bulk Dismiss by Group

// Show several related toasts with a group name
this.toast.info('Step 1 complete', { group: 'wizard' });
this.toast.info('Step 2 complete', { group: 'wizard' });
this.toast.info('Step 3 complete', { group: 'wizard' });

// Later dismiss them all at once
this.toast.dismissByGroup('wizard');

RTL Support (Arabic / Hebrew)

// Set globally
provideNgxSignalToast({ rtl: true })

// Or per toast
this.toast.success('تم الحفظ بنجاح', { rtl: true });

Custom Full Body Component

@Component({
  standalone: true,
  template: `
    <div style="padding: 16px; display: flex; gap: 12px; align-items: center">
      <img src="/avatar.png" width="40" height="40" style="border-radius: 50%" />
      <div>
        <strong>John sent you a message</strong>
        <p style="margin: 0; opacity: 0.8; font-size: 13px">Hey, are you free today?</p>
      </div>
    </div>
  `,
})
export class MessageToastComponent {}

// Use it
this.toast.show('', {
  bodyComponent: MessageToastComponent,
  duration: 6000,
  theme: 'glassmorphism',
});

Reading Toast State in Template

@Component({
  template: `
    @if (!toast.isEmpty()) {
      <span>{{ toast.count() }} active notifications</span>
    }
    <button (click)="toast.dismissAll()">Clear All</button>
  `
})
export class NotificationBarComponent {
  toast = inject(ToastService);
}

📦 TypeScript Types

import type {
  Toast,
  ToastRef,
  ToastOptions,
  ToastConfig,
  ToastAction,
  ToastCustomStyles,
  ToastType,           // 'success' | 'error' | 'warning' | 'info' | 'loading' | 'custom'
  ToastPosition,       // 'top-left' | 'top-center' | 'top-right' | ...
  ToastTheme,          // 'default' | 'glassmorphism' | 'neumorphism' | ...
  ToastLayout,         // 'default' | 'compact' | 'card' | 'pill' | 'sidebar' | 'banner'
  ToastAnimationPreset // 'slide' | 'fade' | 'bounce' | 'zoom' | 'flip'
} from 'ngx-signal-toast';

📝 Changelog

v1.1.0

  • 🎬 Migrated from @angular/animations to native CSS animations
  • ✅ Removed @angular/animations peer dependency entirely
  • 🔧 Auto-inject container via provideAppInitializer — no HTML tag needed
  • 🔁 Split ToastStateService to resolve circular dependency (NG0200)
  • 🌀 Fixed spinner animation interrupted by mouse interaction
  • ♿ Added prefers-reduced-motion support

v1.0.0

  • 🎉 Initial release
  • 8 themes, 6 layouts, 9 positions, 5 animations
  • Full Signals API, Promise helper, Toast actions
  • SSR support, RTL support

🤝 Contributing

Contributions are welcome! Please open an issue first to discuss what you would like to change.

# Clone and install
git clone https://github.com/your-org/ngx-signal-toast.git
cd ngx-signal-toast
npm install

# Build the library
ng build ngx-signal-toast --configuration production

# Run the demo
ng serve demo

# Run tests
ng test ngx-signal-toast

📄 License

MIT © 2025 ngx-signal-toast


Made with ❤️ for the Angular community

⭐ Support the Project

If you find this library useful:

⭐ Star the repository
🐛 Report issues
💡 Suggest features
🤝 Contribute improvements