A drop-in React Error Boundary with the iconic red-on-black blink of the Amiga Guru Meditation. Same contract as
react-error-boundary(fallback,fallbackRender,onError,onReset,resetKeys), themeable via CSS variables, zero runtime dependencies, ~2 KB gzipped.
- 🛡️ Real Error Boundary — catches errors during rendering, lifecycle, and constructors.
- ♿ Accessible —
role="alert",aria-live="assertive",prefers-reduced-motionaware. - 🎨 Themeable via CSS variables — no provider, scope themes with any selector.
- 📦 Zero runtime dependencies — only React as a peer dependency.
- 🪶 Tiny — ~2 KB ESM gzipped, tree-shakeable, dual ESM + CJS.
- ⌨️ TypeScript-first — full type declarations included.
- 🖥️ Inline or fullscreen — render inline by default, opt into a portal-mounted Amiga takeover with one prop.
npm install react-amiga-guru-meditation
# or
pnpm add react-amiga-guru-meditation
# or
yarn add react-amiga-guru-meditationRequires React 18 or newer.
import { AmigaErrorBoundary } from "react-amiga-guru-meditation";
import "react-amiga-guru-meditation/styles.css";
export function App() {
return (
<AmigaErrorBoundary>
<Dashboard />
</AmigaErrorBoundary>
);
}The stylesheet must be imported once in your app (root layout, entry file, or wherever you prefer).
<AmigaErrorBoundary
onError={(err, info) => report(err, info)}
resetKeys={[userId]}
onReset={() => refetch()}
>
<Dashboard />
</AmigaErrorBoundary><AmigaErrorBoundary
fallbackRender={({ error, resetErrorBoundary }) => (
<div role="alert">
<p>{error.message}</p>
<button onClick={resetErrorBoundary}>Try again</button>
</div>
)}
>
<Dashboard />
</AmigaErrorBoundary><AmigaErrorBoundary portal>
<App />
</AmigaErrorBoundary>portal accepts boolean | string | HTMLElement — a string is used as the container element id; an element is used as the portal target directly.
For triggering errors from function components (useful in async handlers):
import { useAmigaGuru } from "react-amiga-guru-meditation";
function SaveButton() {
const guru = useAmigaGuru();
return (
<button
onClick={async () => {
try {
await save();
} catch (e) {
guru(e); // re-thrown during render so the nearest boundary catches it
}
}}
>
Save
</button>
);
}For previews, storybooks, or marketing pages, force the error UI without a real error:
<AmigaErrorBoundary show error={new Error("preview")}>
<App />
</AmigaErrorBoundary>All visual properties are exposed as CSS custom properties. Override them on any selector to theme one boundary, a section, or the whole app:
.guru-theme {
--ragm-fg: #33ff66;
--ragm-bg: #001a06;
--ragm-border-width: 4px;
--ragm-blink-duration: 1.4s;
--ragm-font-family: "JetBrains Mono", monospace;
}Or pass them inline via style:
<AmigaErrorBoundary
style={{
"--ragm-fg": "#0f0",
"--ragm-bg": "#001a06",
} as React.CSSProperties}
>
<App />
</AmigaErrorBoundary>| Variable | Default | Notes |
|---|---|---|
--ragm-fg |
#ff2222 |
Foreground (text + border + blink color). |
--ragm-bg |
#000000 |
Background. |
--ragm-border-width |
6px |
|
--ragm-border-style |
solid |
|
--ragm-blink-duration |
1s |
Set 0s to stop the blink (or use the noBlink prop). |
--ragm-font-family |
"Times New Roman", Times, serif |
|
--ragm-font-size |
18px |
|
--ragm-font-weight |
400 |
|
--ragm-line-height |
1.4 |
|
--ragm-padding |
24px |
|
--ragm-z-index |
9999 |
|
--ragm-mono-family |
system mono stack | Used for the error code and component stack. |
| Prop | Type | Description |
|---|---|---|
children |
ReactNode |
What to render when there's no error. |
fallback |
ReactNode |
Static fallback UI rendered on error. |
fallbackRender |
(props) => ReactNode |
Render-prop fallback. Receives { error, errorInfo, resetErrorBoundary }. Takes priority over fallback. |
onError |
(err, info) => void |
Called once per caught error. Useful for logging / Sentry / etc. |
onReset |
({ reason }) => void |
Called when the boundary resets. reason is "imperative" or "keys". |
resetKeys |
readonly unknown[] |
When any value changes (shallow), the boundary auto-resets. |
show |
boolean |
Force the error UI to render even without a real error. |
error |
Error |
A pre-built error to display when show is true (or to override the caught one). |
portal |
boolean | string | HTMLElement |
Render the fallback through a portal. true mounts a <div id="amiga-guru"> on body; a string is used as the container id; an element is used as the explicit target. |
title |
ReactNode |
Title text. Default: "Software Failure. Press left mouse button to continue." |
formatGuru |
(error) => ReactNode |
Override the message line. Default: error.message. |
showDetails |
boolean |
Show the collapsible component stack. Default: true. |
noBlink |
boolean |
Disable the blink animation. |
className, style |
— | Applied to the fallback root element. |
The exported alias GuruMeditation is the same component under a shorter, more retro name.
backgroundColor / color props are gone (use CSS variables), the rendering is now inline by default (pass portal for the v3 takeover behavior), and a full react-error-boundary-style API has been added. See the v3 → v4 guide for a step-by-step migration walkthrough.
Small, accessible React components — same philosophy, same toolchain, zero runtime dependencies:
- react-toggle-component — an accessible toggle/switch with CSS-variable theming. (npm · GitHub)
- @gfazioli/react-flip — wrap any two faces and animate a 3D rotation between them. (npm · GitHub)
- @gfazioli/react-tilt — interactive 3D tilt cards with parallax, glare, light, shadow, gyroscope, and spring physics. (npm · GitHub)
MIT — © Giovambattista Fazioli
If this project saves you time (or made you laugh in production), consider sponsoring on GitHub — it directly supports continued maintenance and new releases.
If this project is useful to you, help spread the word: