JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 7
  • Score
    100M100P100Q39302F

React widget for bug reporting and feedback with Linear integration

Package Exports

  • @kamyarme/ticketing-widget
  • @kamyarme/ticketing-widget/dist/index.esm.js
  • @kamyarme/ticketing-widget/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@kamyarme/ticketing-widget) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

@kamyarme/ticketing-widget

npm version npm downloads license

A beautiful, production-ready bug reporting and feedback widget for React applications

Capture bugs, feature requests, and user feedback with automatic console log capture and Linear integration.

DemoInstallationDocumentationExamples


✨ Features

  • 🎯 Zero Configuration - Works out of the box with minimal setup
  • 📝 Smart Console Capture - Automatically captures console logs, warnings, and errors (last 100 messages)
  • 🔐 Secure & Licensed - License-based activation with backend validation
  • 📸 File Attachments - Upload screenshots, images, and documents (up to 10MB)
  • 🔗 Linear Integration - Automatically creates issues in your Linear workspace
  • 💾 MongoDB Storage - All tickets stored securely in your database
  • 🌐 Rich Context - Captures URL, user token, browser info, screen size, and timestamp
  • 🎨 Fully Customizable - Light/dark themes, custom positioning, and custom styles
  • 🌍 Internationalization - Built-in support for English and Persian (Farsi)
  • Lightweight - Small bundle size with tree-shaking support
  • 📱 Responsive - Works perfectly on desktop, tablet, and mobile
  • Accessible - Keyboard navigation and screen reader support
  • 🔲 Host-modal compatible - Ticket modal works on top of your app’s own modals (portaled, focus-trapped, high z-index); see MODAL_PORTAL.md

📦 Installation

npm install @kamyarme/ticketing-widget
# or
yarn add @kamyarme/ticketing-widget
# or
pnpm add @kamyarme/ticketing-widget

Requirements:

  • React 17.0.0 or higher
  • React DOM 17.0.0 or higher

🚀 Quick Start

1. Add the Widget to Your App

import React from 'react';
import { TicketingWidget } from '@kamyarme/ticketing-widget';

function App() {
  return (
    <div>
      <h1>Your Application</h1>
      
      <TicketingWidget
        apiUrl="https://your-api.example.com"
        licenseKey="your-license-key-here"
      />
    </div>
  );
}

export default App;

2. Set Up the Backend

You'll need a backend server to handle tickets. See Backend Setup section below.


🎯 Demo

📹 Coming soon: Live demo and screenshots


📚 API Reference

Props

Prop Type Required Default Description
apiUrl string ✅ Yes - URL of your ticketing API server
licenseKey string ✅ Yes - Your license key (get one from backend)
getUserToken () => string | null ⬜ No undefined Function to retrieve user's auth token for user identification
position 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left' ⬜ No 'bottom-right' Position of the floating widget button
theme 'light' | 'dark' ⬜ No 'light' Color theme for the widget
customStyles React.CSSProperties ⬜ No {} Custom CSS styles for the floating button

Type Definitions

interface TicketingWidgetProps {
  apiUrl: string;
  licenseKey: string;
  getUserToken?: () => string | null;
  position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
  theme?: 'light' | 'dark';
  customStyles?: React.CSSProperties;
}

💡 Examples

Basic Usage

import { TicketingWidget } from '@kamyarme/ticketing-widget';

function App() {
  return (
    <>
      <YourApp />
      <TicketingWidget
        apiUrl="https://api.example.com"
        licenseKey="lic_1234567890abcdef"
      />
    </>
  );
}

With User Authentication

Track which users report issues by providing their auth token:

import { TicketingWidget } from '@kamyarme/ticketing-widget';

function App() {
  return (
    <TicketingWidget
      apiUrl="https://api.example.com"
      licenseKey="lic_1234567890abcdef"
      getUserToken={() => {
        // Return the user's authentication token
        return localStorage.getItem('authToken');
        // or from your auth context/state
        // return user?.token;
      }}
    />
  );
}

Custom Positioning

Place the widget button wherever you want:

<TicketingWidget
  apiUrl="https://api.example.com"
  licenseKey="lic_1234567890abcdef"
  position="top-left"  // Options: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'
/>

Dark Theme

Perfect for dark-mode applications:

<TicketingWidget
  apiUrl="https://api.example.com"
  licenseKey="lic_1234567890abcdef"
  theme="dark"
/>

Custom Button Styles

Customize the floating button to match your brand:

<TicketingWidget
  apiUrl="https://api.example.com"
  licenseKey="lic_1234567890abcdef"
  customStyles={{
    backgroundColor: '#ff6b6b',
    width: '70px',
    height: '70px',
    borderRadius: '35px',
    boxShadow: '0 4px 12px rgba(0,0,0,0.15)',
  }}
/>

Complete Example with Next.js

// app/layout.tsx or pages/_app.tsx
import { TicketingWidget } from '@kamyarme/ticketing-widget';
import { useAuth } from '@/hooks/useAuth';

export default function RootLayout({ children }) {
  const { user } = useAuth();
  
  return (
    <html>
      <body>
        {children}
        
        <TicketingWidget
          apiUrl={process.env.NEXT_PUBLIC_API_URL}
          licenseKey={process.env.NEXT_PUBLIC_TICKETING_LICENSE}
          getUserToken={() => user?.accessToken || null}
          theme="dark"
          position="bottom-right"
        />
      </body>
    </html>
  );
}

📊 What Gets Captured?

When a user submits a ticket, the widget automatically captures comprehensive debugging information:

Data Description
📝 Console Logs Last 100 console messages (log, warn, error, info) with timestamps
🌐 Current URL The exact page where the issue occurred
👤 User Token User authentication token (if getUserToken is provided)
💻 User Agent Browser, OS, and device information
📱 Screen Size Current viewport dimensions (width × height)
Timestamp Exact date and time of submission
⚠️ Error Stack Traces Full stack traces for JavaScript errors
📄 Description User-provided title and detailed description
🖼️ Files User-uploaded screenshots and attachments

All data is sent securely to your backend and stored in MongoDB.


🔧 Backend Setup

This widget requires a backend server to process tickets. Here's how to set it up:

Option 1: Using the Official Backend Package

We provide a ready-to-use backend built with Hono.js and MongoDB:

# Clone or download the backend
git clone https://github.com/yourusername/ticketing.git
cd ticketing/packages/api

# Install dependencies
npm install

# Set up environment variables
cp .env.example .env
# Edit .env with your configuration

# Run the server
npm start

Required Environment Variables:

# MongoDB
MONGODB_URI=mongodb://localhost:27017/ticketing

# JWT Secret
JWT_SECRET=your-super-secret-key

# Linear Integration (optional)
LINEAR_API_KEY=lin_api_xxxxxxxxxxxxx

# Server
PORT=3000

Option 2: Custom Backend

The widget makes a POST request to /api/tickets endpoint. Here's the expected request format:

Endpoint: POST /api/tickets

Headers:

Content-Type: multipart/form-data

Body:

{
  licenseKey: string;           // License key for validation
  subject: string;              // Ticket title
  description: string;          // Detailed description
  url: string;                  // Current page URL
  userToken?: string;           // Optional user auth token
  userAgent: string;            // Browser info
  screenSize: {
    width: number;
    height: number;
  };
  consoleLogs: Array<{
    level: 'log' | 'warn' | 'error' | 'info';
    message: string;
    timestamp: string;
  }>;
  files?: File[];               // Optional file attachments
}

Response: 200 OK

{
  "success": true,
  "ticketId": "ticket-id-here",
  "linearIssueId": "optional-linear-issue-id"
}

🔑 Getting a License Key

License keys are required to use this widget and are validated on your backend.

For Development

Generate a test license key from your backend admin panel or using the CLI tool.

For Production

  1. Set up the backend server
  2. Access the admin panel (typically at https://your-api.com/admin)
  3. Create a new license:
    • Enter project name
    • Set expiration date (optional)
    • Configure Linear integration (optional)
    • Generate license key

The license key format: lic_ followed by 20 random characters

Example: lic_a1b2c3d4e5f6g7h8i9j0


🎨 Styling & Customization

Using Tailwind CSS

The widget works great with Tailwind CSS:

<div className="relative">
  <TicketingWidget
    apiUrl={apiUrl}
    licenseKey={licenseKey}
    customStyles={{
      backgroundColor: 'rgb(59 130 246)', // Tailwind blue-500
    }}
  />
</div>

CSS Variables

You can also customize using CSS variables (not yet implemented, but coming soon):

:root {
  --ticketing-widget-primary: #3b82f6;
  --ticketing-widget-radius: 12px;
}

🌍 Internationalization

The widget automatically detects the user's language and displays text accordingly.

Supported Languages:

  • 🇬🇧 English (default)
  • 🇮🇷 Persian (Farsi)

The widget detects browser language automatically. You can contribute more languages by submitting a PR!


🐛 Troubleshooting

Widget not showing up?

  1. Make sure you've added the component to your app
  2. Check browser console for errors
  3. Verify your apiUrl and licenseKey are correct
  4. Ensure your backend server is running

License validation failed?

  1. Verify the license key is correct
  2. Check that your backend server is accessible
  3. Make sure the license hasn't expired
  4. Check backend logs for validation errors

Files not uploading?

  1. Check file size (max 10MB per file)
  2. Verify backend has proper file upload configuration
  3. Check backend storage permissions
  4. Review network tab in browser DevTools

Console logs not capturing?

Console capture is automatic and requires no configuration. If logs aren't appearing:

  1. Make sure errors actually occurred
  2. Check browser console for the widget's own errors
  3. Verify the widget loaded before the logs you want to capture

📖 Advanced Topics

TypeScript Support

This package includes full TypeScript definitions:

import { TicketingWidget, TicketingWidgetProps } from '@kamyarme/ticketing-widget';

const config: TicketingWidgetProps = {
  apiUrl: 'https://api.example.com',
  licenseKey: 'lic_xxx',
  theme: 'dark',
  position: 'bottom-left',
};

<TicketingWidget {...config} />

SSR (Server-Side Rendering)

The widget is designed to work with SSR frameworks like Next.js:

'use client'; // Next.js 13+ app directory

import { TicketingWidget } from '@kamyarme/ticketing-widget';

export default function TicketingWrapper() {
  return <TicketingWidget {...props} />;
}

Performance Optimization

The widget is lazy-loaded and won't impact your initial page load:

  • Bundle size: ~50KB gzipped
  • No external dependencies (except React & Axios)
  • Console capture has minimal performance impact
  • Tree-shakable ES modules

🤝 Contributing

We welcome contributions! Here's how you can help:

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/amazing-feature
  3. Commit your changes: git commit -m 'Add amazing feature'
  4. Push to the branch: git push origin feature/amazing-feature
  5. Open a Pull Request

Development Setup:

git clone https://github.com/yourusername/ticketing.git
cd ticketing/packages/react-widget
npm install
npm run dev

📄 License

Copyright © 2025 Kamyar Pouretesam

This software is provided under a commercial license. See LICENSE file for details.

Key Points:

  • ✅ Free to use with a valid license key
  • ✅ Can be used in commercial projects
  • ❌ Cannot redistribute or resell this package
  • ❌ Cannot remove license validation

💬 Support

Need help? We're here for you:


🙏 Acknowledgments

  • Built with React
  • Powered by Axios
  • Integrated with Linear
  • UI inspired by modern design principles