npm package: @kamyarme/ticketing-widget
Description: React widget for bug reporting and feedback with Linear integration
Author: Kamyar Pouretesam
Latest version: 2.0.0

# @kamyarme/ticketing-widget

<div align="center">
  
  ![npm version](https://img.shields.io/npm/v/@kamyarme/ticketing-widget)
  ![npm downloads](https://img.shields.io/npm/dm/@kamyarme/ticketing-widget)
  ![license](https://img.shields.io/npm/l/@kamyarme/ticketing-widget)
  
  **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.
  
  [Demo](#demo) • [Installation](#installation) • [Documentation](#api-reference) • [Examples](#examples)
  
</div>

---

## ✨ 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](./MODAL_PORTAL.md)

---

## 📦 Installation

```bash
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

```jsx
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](#backend-setup) section below.

---

## 🎯 Demo

<!-- Add your demo GIF or images here when ready -->
> 📹 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

```typescript
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

```jsx
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:

```jsx
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:

```jsx
<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:

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

### Custom Button Styles

Customize the floating button to match your brand:

```jsx
<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

```jsx
// 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:

```bash
# 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:**

```env
# 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:**
```typescript
{
  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`
```json
{
  "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:

```jsx
<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):

```css
: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:

```typescript
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:

```jsx
'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:**

```bash
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](./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:

- 📧 **Email:** services@kamyar.me
- 🐛 **Issues:** [GitHub Issues](https://github.com/yourusername/ticketing/issues)
- 💬 **Discussions:** [GitHub Discussions](https://github.com/yourusername/ticketing/discussions)
- 📚 **Docs:** [Full Documentation](https://docs.example.com)

---

## 🙏 Acknowledgments

- Built with [React](https://react.dev/)
- Powered by [Axios](https://axios-http.com/)
- Integrated with [Linear](https://linear.app/)
- UI inspired by modern design principles

---

<div align="center">

**Made with ❤️ by [Kamyar Pouretesam](https://kamyar.me)**

[⭐ Star on GitHub](https://github.com/yourusername/ticketing) • [📦 View on npm](https://www.npmjs.com/package/@kamyarme/ticketing-widget) • [🐛 Report Bug](https://github.com/yourusername/ticketing/issues)

</div>