A lightweight, configurable browser-side error reporter. When triggered, it captures a screenshot, console logs, network requests/responses, and system info, then packages everything into a ZIP — either downloaded directly to the user's computer or uploaded to your own endpoint.
npm install @safagayret/error-reporterAfter installing, generate the configuration file in your project root:
npx error-reporter initThis creates error-reporter.config.js in your working directory. Open it and adjust the settings as described below.
Import and call init() as early as possible in your application's entry point (before any network requests or console output you want to capture):
import { init } from '@safagayret/error-reporter'
init({
language: 'en',
uploadEndpoint: 'https://api.yourcompany.com/error-reports', // optional
shortcut: { ctrl: true, shift: true, key: 'H' },
})Or load your config file and pass it in:
import { init } from '@safagayret/error-reporter'
import config from './error-reporter.config.js'
init(config)Once initialised, press CTRL+SHIFT+H (default shortcut) to open the error reporter modal.
All options are set in error-reporter.config.js (generated by npx error-reporter init).
| Option | Type | Default | Description |
|---|---|---|---|
language |
string |
'en' |
UI language for the modal. See Supported Languages. |
shortcut |
object |
See below | Keyboard shortcut to open the modal. |
shortcut.ctrl |
boolean |
true |
Require the Ctrl key. |
shortcut.shift |
boolean |
true |
Require the Shift key. |
shortcut.alt |
boolean |
false |
Require the Alt / Option key. |
shortcut.meta |
boolean |
false |
Require the Meta (⌘ / ⊞) key. |
shortcut.key |
string |
'H' |
The key to press (matches KeyboardEvent.key). |
uploadEndpoint |
string | null |
null |
URL to upload the ZIP. If null, the ZIP is downloaded instead. |
module.exports = {
language: 'tr',
shortcut: { ctrl: true, shift: false, alt: true, key: 'E' },
uploadEndpoint: null,
}module.exports = {
language: 'en',
shortcut: { ctrl: true, shift: true, key: 'H' },
uploadEndpoint: 'https://api.yourcompany.com/error-reports',
}When uploadEndpoint is set, the reporter sends a multipart/form-data POST request to that URL with the ZIP file under the field name file.
Your endpoint should accept a multipart/form-data POST with a file field and return a 2xx HTTP status code on success. Any non-2xx response is treated as a failure — the modal will display an error message.
| Code | Language |
|---|---|
en |
English (default) |
tr |
Turkish |
de |
German |
fr |
French |
es |
Spanish |
it |
Italian |
pt |
Portuguese |
ru |
Russian |
zh |
Chinese (Simplified) |
ja |
Japanese |
ar |
Arabic |
If an unsupported language code is provided, the modal falls back to English and logs a warning to the console.
| File | Contents |
|---|---|
screenshot.png |
Full-page screenshot at the moment the report is submitted |
console-logs.txt |
Human-readable console log entries |
console-logs.json |
Structured console log entries |
system-info.json |
Browser, viewport, language, timezone, and counts |
user-note.txt |
Free-text note entered by the user (only if filled in) |
network-requests/_summary.txt |
One-line summary of every captured request |
network-requests/_full.json |
Full structured data for all requests |
network-requests/<n>_<METHOD>_<url>/details.txt |
Per-request detail: headers, request body, response body |
network-requests/<n>_<METHOD>_<url>/response.json |
JSON response body (if applicable) |
network-requests/<n>_<METHOD>_<url>/response.txt |
Text response body (if applicable) |
Initialises the reporter. Returns a { destroy } handle.
const reporter = init({ language: 'de' })
// Later — removes all event listeners and restores patched globals:
reporter.destroy()Calling destroy() removes the keyboard listener and reverts all patched browser globals (console, fetch, XMLHttpRequest):
const reporter = init(config)
// ... at some point later ...
reporter.destroy()This package ships as ES modules (import/export). You should be able to use it with any modern bundler (Vite, webpack, Rollup, esbuild, Parcel, etc.).
The html2canvas and jszip packages are listed as dependencies and are imported at runtime — your bundler will include them automatically.
Screenshots are captured using html2canvas. Cross-origin iframes and images served without CORS headers may not appear in the screenshot. This is a browser security constraint and cannot be worked around by the reporter.
The data collected by this reporter is sent to the endpoint you configure in
uploadEndpoint.@safagayret/error-reporter does not transmit any data to its own servers. All captured information — including console logs, network request payloads, and screenshots — goes exclusively to the URL you supply.
The responsibility for data privacy, GDPR/CCPA compliance, and secure handling of the collected data rests entirely with you as the developer. Ensure that your endpoint is adequately secured, that you have a lawful basis for processing any personal data that may appear in the reports, and that you communicate this clearly to your users.
MIT © Safa Gayret — github.com/gayret/error-reporter