Add comprehensive bug reporting to Nuxt apps with Linear integration. Captures screenshots, browser info, console logs, and user journey tracking.
Add comprehensive bug reporting functionality to Nuxt 4 applications with automatic Linear issue creation, screenshot capture, browser diagnostics, and user journey tracking.
This skill guides you through implementing the Bug LT module - a production-ready bug reporting system that:
Read the following files to understand the current implementation:
```
src/module.ts
src/runtime/composables/useBugReport.ts
src/runtime/components/BugReportModal.vue
src/runtime/components/BugReportForm.vue
server/api/bug-report.post.ts
```
**Core Components:**
**Key Configuration Pattern:**
```typescript
export default defineNuxtConfig({
bug: {
linear: {
teamName: 'Entwicklung',
projectName: 'Website' // optional
}
},
runtimeConfig: {
linear: {
apiKey: process.env.LINEAR_API_KEY
}
}
})
```
**Critical: Use client-side library only**
The screenshot feature uses `modern-screenshot` for DOM-to-PNG conversion:
**Implementation pattern:**
```typescript
import { domToPng } from 'modern-screenshot'
const screenshot = await domToPng(document.body, {
features: {
restoreScrollPosition: true
}
})
```
Implement event listeners for:
**Data structure:**
```typescript
interface UserJourneyEvent {
type: string
timestamp: number
target?: string
details?: Record<string, any>
}
```
Limit events to `maxJourneyEvents` (configurable, default 50).
Intercept Fetch and XMLHttpRequest:
```typescript
// Override fetch
const originalFetch = window.fetch
window.fetch = async (...args) => {
const startTime = Date.now()
try {
const response = await originalFetch(...args)
// Log success
return response
} catch (error) {
// Log failure
throw error
}
}
```
Capture: URL, method, status code, duration, error details. Limit to `maxNetworkRequests`.
Override console methods and clean CSS styling:
```typescript
const cleanConsoleMessage = (args: any[]): string => {
return args.map(arg => {
if (typeof arg === 'string') {
return arg.replace(/%c/g, '').trim()
}
return String(arg)
}).join(' ')
}
```
Capture all console levels: log, info, warn, error, debug.
**Critical: Use team/project names, not UUIDs**
**Team/Project Resolution:**
```graphql
query {
teams {
nodes {
id
name
projects {
nodes {
id
name
}
}
}
}
}
```
**Issue Creation:**
```graphql
mutation IssueCreate($input: IssueCreateInput!) {
issueCreate(input: $input) {
success
issue {
id
identifier
url
}
}
}
```
**File Upload (Two-Step Process):**
1. Get signed upload URL from Linear:
```graphql
mutation FileUpload($contentType: String!, $filename: String!, $size: Int!) {
fileUpload(contentType: $contentType, filename: $filename, size: $size) {
success
uploadUrl
assetUrl
}
}
```
2. Upload to Google Cloud Storage with exact headers:
```typescript
await fetch(uploadUrl, {
method: 'PUT',
headers: {
'Content-Type': contentType,
'Cache-Control': 'public, max-age=31536000'
},
body: file
})
```
3. Create attachment record AFTER issue creation:
```graphql
mutation AttachmentCreate($input: AttachmentCreateInput!) {
attachmentCreate(input: $input) {
success
attachment {
id
url
}
}
}
```
**Label Management:**
Auto-create labels with color mapping:
Query existing labels by team, create if missing, then assign to issue.
**Defensive approach:**
Use global composable with cleanup:
```typescript
export const useBugReport = () => {
const isOpen = useState('bugReportOpen', () => false)
const modalInstance = useState<any>('bugReportModal', () => null)
const cleanup = () => {
if (modalInstance.value) {
modalInstance.value = null
}
}
return { isOpen, modalInstance, cleanup }
}
```
**Required commands after code changes:**
```bash
npm run dev:prepare # Regenerates types and module setup
npm run dev # Starts playground with hot reload
```
**Testing Linear integration:**
```bash
export LINEAR_API_KEY=lin_api_...
export LINEAR_TEAM_NAME=Entwicklung
npm run dev
```
**Type checking:**
```bash
npm run test:types # Checks both module and playground
```
**Screenshot blank or missing elements:**
**Modal won't close:**
**Linear API 400 errors:**
**Console logs have CSS artifacts:**
**Labels not created:**
**Component hierarchy:**
```
BugReportButton (trigger)
└─ BugReportModal (overlay)
└─ ErrorBoundary
└─ BugReportForm
├─ UserJourneyTimeline
└─ Screenshot preview
```
All components use `@nuxt/ui` for consistent styling (UButton, UModal, UForm, UTextarea, USelect, UBadge).
All UI text is in German for target customer base:
**Automated via GitHub Actions:**
1. Update version: `npm version patch|minor|major`
2. Push tags: `git push origin --tags`
3. CI automatically: runs tests → builds → publishes to NPM → creates GitHub release
**Requirements:**
Before considering implementation complete:
Core dependencies for this module:
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/bug-reporting-with-linear-integration/raw