@triagly/sdk
Version:
JavaScript SDK for Triagly - Turn user feedback into GitHub issues instantly
452 lines (341 loc) • 11.6 kB
Markdown
# @triagly/sdk
> JavaScript SDK for Triagly - Turn user feedback into GitHub issues instantly.
Lightweight (<10KB gzipped) browser widget that captures user feedback with screenshots and automatically creates GitHub issues.
## Features
- 🎨 **Beautiful UI Widget** - Clean, customizable feedback form
- 📸 **Screenshot Capture** - Automatic page screenshots (with html2canvas)
- 🐛 **Console Log Capture** - Automatically captures browser console errors and warnings for debugging
- 🤖 **Bot Protection** - Cloudflare Turnstile integration to prevent spam
- 🔒 **Secure Authentication** - Uses publishable keys with optional hardened mode
- 📊 **Metadata Collection** - Browser, URL, viewport info automatically captured
- 🔐 **Privacy & Security** - Auto-sanitizes sensitive data (tokens, passwords, emails)
- ⚡ **Lightweight** - Minimal bundle size, no heavy dependencies
- 🎯 **TypeScript** - Full type definitions included
## Installation
### NPM
```bash
npm install @triagly/sdk
# or
pnpm add @triagly/sdk
# or
yarn add @triagly/sdk
```
### CDN
```html
<!-- Include Cloudflare Turnstile for bot protection -->
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<!-- Include html2canvas for screenshot support (optional) -->
<script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"></script>
<!-- Include Triagly SDK -->
<script src="https://unpkg.com/@triagly/sdk/dist/index.min.js"></script>
```
## Quick Start
### Method 1: Simple Mode (Recommended for most users)
```typescript
import Triagly from '@triagly/sdk';
const triagly = new Triagly({
publishableKey: 'pub_live_abc123',
turnstileSiteKey: 'your-turnstile-site-key',
});
```
### Method 2: Hardened Mode (For sensitive applications)
```typescript
import Triagly from '@triagly/sdk';
const triagly = new Triagly({
publishableKey: 'pub_live_abc123',
turnstileSiteKey: 'your-turnstile-site-key',
getToken: async () => {
// Call your backend to get a hardened token
const res = await fetch('/api/triagly-token', {
method: 'POST',
headers: { Authorization: `Bearer ${userSessionToken}` }
});
const { token } = await res.json();
return token;
}
});
```
### Method 3: Auto-initialization (CDN)
```html
<script>
window.TriaglyConfig = {
publishableKey: 'pub_live_abc123',
turnstileSiteKey: 'your-turnstile-site-key',
};
</script>
<script src="https://unpkg.com/@triagly/sdk/dist/index.min.js"></script>
```
### Method 4: React Example
```tsx
import { useEffect, useRef } from 'react';
import Triagly from '@triagly/sdk';
function App() {
const triaglyRef = useRef<Triagly | null>(null);
useEffect(() => {
triaglyRef.current = new Triagly({
publishableKey: 'pub_live_abc123',
turnstileSiteKey: 'your-turnstile-site-key',
onSuccess: (feedbackId) => {
console.log('Feedback submitted:', feedbackId);
},
onError: (error) => {
console.error('Feedback error:', error);
},
onOpen: () => {
console.log('Widget opened');
},
onClose: () => {
console.log('Widget closed');
},
});
return () => {
triaglyRef.current?.destroy();
};
}, []);
return <div>Your App</div>;
}
```
## Configuration
```typescript
interface TriaglyConfig {
// Required
publishableKey: string; // Your Triagly publishable key
// Optional - Authentication
getToken?: () => Promise<string>; // Callback for hardened mode
turnstileSiteKey?: string; // Cloudflare Turnstile site key (required for bot protection)
// Optional - API Configuration
apiUrl?: string; // Custom API URL (defaults to production)
// Optional - UI Customization
theme?: 'light' | 'dark' | 'auto';
position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
buttonShape?: 'rounded' | 'circular' | 'square' | 'pill'; // Default: "rounded"
buttonText?: string; // Default: "🐛 Feedback"
placeholderText?: string; // Default: "Describe what happened..."
successMessage?: string;
errorMessage?: string;
// Optional - Callbacks
onSuccess?: (feedbackId: string) => void; // Called after successful submission
onError?: (error: Error) => void; // Called on submission error
onOpen?: () => void; // Called when widget opens
onClose?: () => void; // Called when widget closes
// Optional - Console Log Capture
captureConsole?: boolean; // Enable console log capture (default: true)
consoleLogLimit?: number; // Max logs to keep (default: 50)
consoleLogLevels?: ('error' | 'warn' | 'log')[]; // Which levels to capture (default: ['error', 'warn'])
// Optional - Custom Metadata
metadata?: Record<string, any>; // Additional metadata to include
}
```
## API
### Constructor
```typescript
const triagly = new Triagly(config: TriaglyConfig);
```
### Methods
#### `open()`
Programmatically open the feedback widget.
```typescript
triagly.open();
```
#### `close()`
Programmatically close the feedback widget.
```typescript
triagly.close();
```
#### `submit(data)`
Submit feedback programmatically without UI.
```typescript
await triagly.submit({
title: 'Bug: Login button not working',
description: 'When I click the login button, nothing happens.',
reporterEmail: 'user@example.com',
tags: ['bug', 'login'],
});
```
#### `destroy()`
Remove the widget and clean up event listeners.
```typescript
triagly.destroy();
```
## Examples
### Custom Button Trigger
```html
<button id="custom-feedback-btn">Report Issue</button>
<script>
const triagly = new Triagly({
publishableKey: 'pub_live_abc123',
turnstileSiteKey: 'your-turnstile-site-key',
});
document.getElementById('custom-feedback-btn').onclick = () => {
triagly.open();
};
</script>
```
### With Custom Metadata
```typescript
const triagly = new Triagly({
publishableKey: 'pub_live_abc123',
turnstileSiteKey: 'your-turnstile-site-key',
metadata: {
appVersion: '1.2.3',
environment: 'production',
userId: 'user-123',
},
});
```
### Programmatic Submission
```typescript
const triagly = new Triagly({
publishableKey: 'pub_live_abc123',
turnstileSiteKey: 'your-turnstile-site-key',
});
// Submit without opening widget
try {
await triagly.submit({
title: 'Feature Request',
description: 'It would be great to have dark mode.',
reporterEmail: 'user@example.com',
tags: ['feature-request'],
});
console.log('Feedback sent!');
} catch (error) {
console.error('Failed:', error);
}
```
### Using Pre-built Themes
```html
<!-- Dark theme -->
<link rel="stylesheet" href="https://unpkg.com/@triagly/sdk/themes/dark.css">
<!-- Minimal theme -->
<link rel="stylesheet" href="https://unpkg.com/@triagly/sdk/themes/minimal.css">
<!-- Gradient theme -->
<link rel="stylesheet" href="https://unpkg.com/@triagly/sdk/themes/gradient.css">
<!-- Ocean theme -->
<link rel="stylesheet" href="https://unpkg.com/@triagly/sdk/themes/ocean.css">
```
### Custom Styling with CSS Variables
```css
:root {
/* Customize colors easily */
--triagly-button-bg: #ff0066;
--triagly-button-bg-hover: #cc0052;
--triagly-modal-bg: #ffffff;
--triagly-modal-radius: 20px;
--triagly-btn-primary-bg: #ff0066;
}
```
See [Styling Guide](./docs/guides/STYLING.md) for all available variables and more examples.
## Screenshot Support
To enable screenshot capture, include html2canvas:
```html
<script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"></script>
```
Or install via NPM and import in your bundle:
```bash
npm install html2canvas
```
```typescript
import html2canvas from 'html2canvas';
(window as any).html2canvas = html2canvas;
```
## Console Log Capture
The SDK automatically captures browser console messages (errors and warnings by default) to help developers debug issues.
### How It Works
- Intercepts `console.error`, `console.warn`, and optionally `console.log`
- Stores the last 50 messages in a circular buffer
- Includes stack traces for errors
- Automatically sanitizes sensitive data (tokens, passwords, emails)
- Sends logs with feedback submissions
### Example Captured Logs
When a user reports "Login doesn't work", the SDK automatically includes:
```
[14:30:15] ❌ ERROR: TypeError: Cannot read property 'submit' of undefined
at LoginForm.handleSubmit (login.js:42:15)
[14:30:10] ⚠️ WARN: Deprecated API used: oldAuthMethod()
[14:30:08] ❌ ERROR: Network request failed: POST /api/auth/login
```
### Privacy & Sanitization
The SDK automatically sanitizes:
- API keys and tokens (e.g., `token=***`)
- Passwords (e.g., `password=***`)
- Email addresses (e.g., `***@***.com`)
- JWT tokens (e.g., `jwt.***`)
- Credit card numbers
- GitHub tokens
### Disable Console Capture
```typescript
const triagly = new Triagly({
projectId: 'your-project-id',
apiUrl: 'https://your-api.com',
captureConsole: false, // Disable console capture
});
```
### Customize Console Capture
```typescript
const triagly = new Triagly({
projectId: 'your-project-id',
apiUrl: 'https://your-api.com',
captureConsole: true,
consoleLogLimit: 100, // Keep last 100 logs
consoleLogLevels: ['error'], // Only capture errors
});
```
## Rate Limiting
The SDK automatically rate-limits submissions to 3 per 5 minutes per user (stored in localStorage).
## Migration Guide
### Upgrading from v0.0.x to v0.1.0
This release introduces **breaking changes** for improved security and bot protection.
#### What Changed
1. **`projectId` → `publishableKey`**
- Old: `projectId: 'uuid-here'`
- New: `publishableKey: 'pub_live_abc123'`
2. **`apiUrl` is now optional**
- The SDK now defaults to the production API
- Only set this if using a custom deployment
3. **Turnstile bot protection**
- Add `turnstileSiteKey` to your config
- Include the Turnstile script in your HTML
#### Migration Steps
**Before:**
```typescript
const triagly = new Triagly({
projectId: 'your-project-id',
apiUrl: 'https://your-project.supabase.co/functions/v1',
});
```
**After:**
```typescript
const triagly = new Triagly({
publishableKey: 'pub_live_abc123', // Get from dashboard
turnstileSiteKey: 'your-turnstile-site-key', // Get from Cloudflare
});
```
**Don't forget to add Turnstile:**
```html
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
```
#### Backward Compatibility
The SDK maintains backward compatibility with `projectId` for now, but will show a deprecation warning. Update to `publishableKey` as soon as possible.
## Browser Support
- Chrome/Edge (latest 2 versions)
- Firefox (latest 2 versions)
- Safari (latest 2 versions)
## Development
```bash
# Install dependencies
pnpm install
# Build
pnpm build
# Watch mode
pnpm dev
```
## Documentation
- [Accessibility Guide](./docs/guides/ACCESSIBILITY.md) - WCAG 2.1 AA compliance & keyboard navigation
- [Callbacks Guide](./docs/guides/CALLBACKS.md) - Complete callback documentation
- [Console Capture Guide](./docs/guides/CONSOLE_CAPTURE.md) - Automatic console log capture
- [Styling Guide](./docs/guides/STYLING.md) - Customize button and modal styles
- [Local Testing Guide](./docs/guides/TEST_LOCALLY.md) - Test the package locally
- [Contributing Guide](./docs/contributing/CONTRIBUTING.md) - Contribution guidelines
- [Release Guide](./docs/contributing/RELEASE_GUIDE.md) - How to create releases
## License
MIT