A Next.js-style error overlay and animated loading badge for Bini.js projects. Shows your Bini.js logo during development — animates on load and HMR updates, morphs into a clickable error pill when something goes wrong, and opens a full error panel with stack trace and code frame.
- Features
- Installation
- Usage
- How It Works
- States
- HMR Events
- Error Panel
- Requirements
- Troubleshooting
- Contributing
- License
- Related
- ✨ Animated badge — SVG stroke-drawing animation on page load and every HMR update
- 🚨 Error panel — centered overlay with error type, message, code frame, and call stack
- 🔴 Error pill — badge morphs into a red
1 Issue/3 Issuespill — click to reopen the panel - 🔄 HMR integration — reacts to
vite:error,vite:beforeUpdate, andvite:afterUpdate - 🧭 Multi-error navigation — prev/next arrows when multiple errors are queued
- 🎨 Bini.js branding — official gradient logo and
Bini.jslabel in the toolbar - 🎨 Shiki syntax highlighting — code frames highlighted with the
dark-plustheme via Shiki, loaded as an ES module from CDN at runtime - 🔒 Dev only — never appears in production builds
- 🛡️ Same-origin protected debug endpoints — the code-frame and route-lookup APIs the overlay talks to reject cross-origin requests
- 🛡️ Suppresses default Vite overlay — replaces the built-in
vite-error-overlaycustom element - 🧹 Auto-clears — overlay automatically hides when errors are fixed (no manual refresh needed)
npm install bini-overlay --save-dev
# or
pnpm add bini-overlay -D
# or
yarn add bini-overlay -D// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { biniOverlay } from 'bini-overlay'
export default defineConfig({
plugins: [
react(),
...biniOverlay()
]
})biniOverlay() takes an optional config object for the loading badge — see Options below. Code-frame syntax highlighting itself isn't configurable; it always renders with the dark-plus Shiki theme.
The badge sits in the bottom-left corner and responds to your development workflow:
| State | Visual | Behavior |
|---|---|---|
| Loading | 🌀 Logo draws itself with a stroke animation | Triggers on page load and HMR updates |
| Idle | 🎨 Logo sits as a filled gradient icon | Default state when no errors are present |
| Error | 🔴 Red pill with 1 Issue / 3 Issues |
Click to open the error panel |
1. Error occurs → badge morphs into red pill → overlay opens automatically
2. Navigate errors → use prev/next arrows to cycle through multiple errors
3. Fix the error → HMR updates → badge animates → overlay auto-closes
4. Back to idle → logo returns to normal state
| Event | Action |
|---|---|
vite:error |
Shows error pill + auto-opens panel |
vite:beforeUpdate |
Clears resolved errors, shows loading animation |
vite:afterUpdate |
Returns to idle, auto-closes panel if no errors remain |
When an error occurs, a full-screen overlay opens showing:
| Section | Description |
|---|---|
| Error Type | Runtime Error / Parse Error / Build Error / Type Error / Unhandled Rejection |
| File Info | Detected file path with line number |
| Code Frame | Surrounding lines fetched from disk, Shiki-highlighted, with the error line called out |
| Call Stack | Collapsible stack trace with internal and node_modules frames filtered |
| Copy Button | Copies full error message, file, code context, and stack to clipboard |
| Navigation | Prev/Next arrows when multiple errors are queued |
>>> 12: const name = user.name
11: function Greeting() {
13: return <h1>Hello, {name}!</h1>
The error line is marked with a >>> prefix and a subtle red row highlight; all other lines sit flat with no per-line background.
interface BiniOverlayOptions {
/**
* App directory to scan for routes when resolving the current page's
* route type (static/dynamic) in the loading badge menu.
* Must match the `appDir` passed to `biniroute()` if you customized it.
* @default 'src/app'
*/
appDir?: string;
/**
* Base path prefix for routes, if you customized it on `biniroute()`.
* @default ''
*/
basePath?: string;
/**
* Disable the animated loading badge (menu) while keeping the error overlay.
* @default false
*/
disableBadge?: boolean;
}There's no theme option — code frames always render with Shiki's dark-plus theme.
| Version | |
|---|---|
| Node.js | >= 18.0.0 |
| Vite | >= 7.0.0 |
- Ensure you're in development mode (
npm run dev) - Check that
biniOverlay()is added to the plugins array invite.config.ts - Verify the plugin is installed as a dev dependency
- The overlay loads Shiki as an ES module from
esm.shat runtime - An internet connection is required for first load
- Syntax highlighting falls back to plain, unhighlighted text per line if Shiki fails to load — the overlay still works, just without colors
- The code-frame and route-lookup endpoints (
/__bini_code_context,/__bini_route_match) only accept same-origin requests, to stop other pages or scripts from reading files off your machine through the dev server - If you're proxying the dev server through a different origin, requests to these endpoints from the browser will be rejected — access the dev server directly instead
- This indicates an HMR update is in progress
- The badge should resolve to idle or error state automatically
- The overlay auto-closes on
vite:afterUpdate(fixed in v1.0.16+) - If you're on an older version, update to the latest
Issues and pull requests are welcome. If you're adding a new feature, please open an issue first to discuss it.
git clone https://github.com/Binidu01/bini-overlay
cd bini-overlay
pnpm install
pnpm buildMIT © Binidu Ranasinghe
- Bini.js — The React Framework for Cross-Platform
- bini-router — File-based routing for Bini.js
- bini-server — Production server for Bini.js
- bini-deploy — Zero-config deployment for Bini.js