@goodcraft/feedback-widget-core
v1.2.0
Published
Core JavaScript/TypeScript module for the feedback widget
Downloads
410
Maintainers
Readme
@goodcraft/feedback-widget-core
Framework-agnostic feedback widget. Renders a modal UI for bug reports and feature requests with automatic screenshot capture, console error collection, and system info gathering.
Install
pnpm add @goodcraft/feedback-widget-coreFeedbackWidget Class
The main entry point for non-React usage.
import { FeedbackWidget } from '@goodcraft/feedback-widget-core';
const widget = new FeedbackWidget({
endpoint: '/api/feedback',
projectSlug: 'my-app',
position: 'bottom-right',
});
widget.init();Constructor
new FeedbackWidget(config: FeedbackWidgetConfig)FeedbackWidgetConfig
| Property | Type | Default | Description |
|----------|------|---------|-------------|
| endpoint | string | required | API endpoint URL that handles submissions |
| projectSlug | string | required | Project identifier for routing to the correct Linear project |
| sessionId | string | — | Session ID for BetterStack log correlation |
| betterStackTeamId | string | — | BetterStack team ID for deep link generation |
| position | 'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left' | 'bottom-right' | Position of the trigger button |
| zIndex | number | 999999 | z-index for the widget |
| onSuccess | (response: SubmissionResponse) => void | — | Called after successful submission |
| onError | (error: Error) => void | — | Called when submission fails |
| customTrigger | boolean | false | When true, the built-in floating button is not rendered |
Methods
| Method | Description |
|--------|-------------|
| init() | Initializes the widget, starts error collection, renders the trigger button |
| open(type?: 'bug' \| 'feature') | Opens the feedback modal. Optionally pre-selects a submission type |
| close() | Closes the modal |
| destroy() | Removes all DOM elements and stops error collection |
| submitDirect(data) | Submits feedback programmatically without showing the modal UI |
submitDirect
const response = await widget.submitDirect({
type: 'bug',
title: 'Page crashes on save',
description: 'Steps to reproduce...',
email: '[email protected]',
includeScreenshot: true, // default: true
});Exported Utilities
captureScreenshot(options?)
Captures a screenshot of the current viewport using html2canvas. Returns a base64-encoded PNG string (without the data: prefix).
import { captureScreenshot } from '@goodcraft/feedback-widget-core';
const base64 = await captureScreenshot({
fullPage: false, // default
quality: 0.8, // default
scale: 1, // default
});base64ToBlob(base64, mimeType?)
Converts a base64 string to a Blob.
initErrorCollection()
Starts collecting console.error calls and unhandled errors/rejections. Keeps the last 10 errors.
getConsoleErrors()
Returns collected ConsoleError[].
clearConsoleErrors()
Clears all collected errors.
destroyErrorCollection()
Restores the original console.error and stops collection.
getSystemInfo()
Returns a SystemInfo object with URL, browser, OS, viewport, screen resolution, timezone, and language.
generateBetterStackLink(teamId, sessionId?, minutesBack?)
Generates a BetterStack Logs deep link filtered by session ID or current path.
Script Tag Auto-Initialization
The core module can auto-initialize from a <script> tag:
<script
type="module"
src="https://unpkg.com/@goodcraft/feedback-widget-core"
data-endpoint="/api/feedback"
data-project="my-app"
data-position="bottom-right"
></script>The widget instance is available at window.feedbackWidget.
Types
type SubmissionType = 'bug' | 'feature';
interface FeedbackSubmission {
type: SubmissionType;
title: string;
description?: string;
email?: string;
screenshot?: string;
systemInfo: SystemInfo;
consoleErrors: ConsoleError[];
projectSlug: string;
sessionId?: string;
betterStackLink?: string;
}
interface SubmissionResponse {
success: boolean;
issueId?: string;
issueIdentifier?: string;
issueUrl?: string;
message?: string;
}
interface SystemInfo {
url: string;
userAgent: string;
browser: string;
browserVersion: string;
os: string;
osVersion: string;
viewport: { width: number; height: number };
screenResolution: { width: number; height: number };
timestamp: string;
timezone: string;
language: string;
}
interface ConsoleError {
message: string;
stack?: string;
timestamp: string;
type: 'error' | 'unhandledrejection';
}License
MIT
