Skip to content

feat(docs): add "Report a Bug" feedback widget to documentation site #145

@polaz

Description

@polaz

Summary

Add a persistent, user-friendly "Report a Bug" widget to the VitePress documentation site that lets users quickly report issues without leaving the page and without needing a GitHub account. Uses a Cloudflare Pages Function as backend proxy to create issues via GitHub App.

UX Goals

  • Zero friction: User never leaves the docs site
  • No GitHub account required: Issues created by bot on user's behalf
  • Minimal fields: One required field ("What happened?"), everything else optional/auto-filled
  • Instant feedback: "Thanks! We'll look into it" — no redirects, no loading pages
  • Always accessible: Side tab visible on every page

Architecture

User (docs site) ---> Cloudflare Pages Function (/api/report-bug)
                          |
                          | (GitHub App installation token)
                          v
                      GitHub API (POST /repos/.../issues)
                          |
                          v
                      Issue created by "bug-reporter[bot]"

Why This Architecture?

Approach Pros Cons
Redirect to GitHub Simple Requires GitHub account, leaves site, form is complex
Personal Access Token Simple Token tied to person, security risk if leaked
GitHub App Secure, bot identity, no user auth needed Slightly more setup
OAuth flow User identity Over-engineered for bug reports, requires GitHub account

Part 1: GitHub App Setup

Create a GitHub App named gitlab-mcp-bug-reporter (or similar):

Permissions:

  • Repository > Issues: Read & Write
  • Nothing else needed

Installation:

  • Install on structured-world/gitlab-mcp repository only

Credentials stored in Cloudflare:

  • GITHUB_APP_ID — App ID
  • GITHUB_APP_PRIVATE_KEY — PEM private key (for JWT signing)
  • GITHUB_APP_INSTALLATION_ID — Installation ID for the repo

Reference: Authenticating as a GitHub App installation

Part 2: Cloudflare Pages Function

File: docs/functions/api/report-bug.ts

Cloudflare Pages automatically deploys functions/ directory as serverless endpoints.
Reference: Pages Functions

// POST /api/report-bug
interface BugReport {
  page: string;          // Auto-filled from current docs path
  description: string;   // Required: "What happened?"
  expected?: string;     // Optional: "What did you expect?"
  category?: string;     // Optional: dropdown selection
  honeypot?: string;     // Anti-spam: must be empty
}

export const onRequestPost: PagesFunction<Env> = async (context) => {
  // 1. Rate limit check (Cloudflare KV or simple in-memory)
  // 2. Validate input (honeypot empty, description min 10 chars)
  // 3. Generate GitHub App JWT
  // 4. Exchange JWT for installation access token
  // 5. Create issue via GitHub API
  // 6. Return success/error to client
};

Issue format created by bot:

## Bug Report from Documentation

**Page:** /guide/quick-start
**Category:** Tool not working as described

### What happened?
The example code on the page didn't work...

### What did you expect? (optional)
I expected the command to return a list of projects...

---
*Reported via docs feedback widget*

Anti-spam measures:

  • Honeypot field (hidden, must be empty)
  • Rate limit: max 5 reports per IP per hour (Cloudflare KV)
  • Minimum description length: 10 characters
  • Cloudflare Turnstile (invisible CAPTCHA) — optional, add if spam becomes a problem

Part 3: VitePress Side Tab Widget

File: docs/.vitepress/theme/components/BugReportWidget.vue

Visual States

State 1: Collapsed (default)

+------------------------------------------+
|  docs content...                         |
|                                    [Bug?]|  <- small side tab
|  more content...                         |
+------------------------------------------+

State 2: Expanded (on click)

+------------------------------------------+
|  docs content...          +-------------+|
|                           | Found a bug?||
|                           |             ||
|                           | What        ||
|                           | happened?   ||
|                           | [________]  ||
|                           |             ||
|                           | [Send]      ||
|                           +-------------+|
+------------------------------------------+

State 3: Success

                            +-------------+
                            |  Thanks!    |
                            |  We'll look |
                            |  into it.   |
                            +-------------+

Inline Form Fields

Field Type Required Pre-filled
Page hidden Auto: current path via useRoute()
What happened? textarea Yes
What did you expect? textarea No
Category select No Options: Wrong docs, Tool broken, Missing info, Setup issue, Other
honeypot hidden input Must be empty (anti-bot)

Responsive Behavior

  • Desktop: Side tab (right edge, ~40% from top), expands into slide-out panel
  • Tablet: Same but slightly smaller
  • Mobile: Bottom-right floating circle (bug icon), expands into bottom sheet / modal

Animation

  • Expand/collapse: CSS transition (200ms ease)
  • Success: checkmark animation, auto-collapse after 3s
  • Respects prefers-reduced-motion

Part 4: GitHub Issue Template (Fallback)

For users who prefer GitHub directly, also create .github/ISSUE_TEMPLATE/bug.yml:

name: Bug Report
description: Something not working? Let us know!
labels: ["bug"]
body:
  - type: markdown
    attributes:
      value: |
        Thanks for reporting! Just tell us what happened — no formal structure needed.

  - type: input
    id: page
    attributes:
      label: Which page?
      placeholder: e.g., /guide/quick-start
    validations:
      required: false

  - type: textarea
    id: what-happened
    attributes:
      label: What happened?
      placeholder: Describe what went wrong or was confusing...
    validations:
      required: true

  - type: textarea
    id: expected
    attributes:
      label: What did you expect? (optional)
    validations:
      required: false

  - type: dropdown
    id: category
    attributes:
      label: Category (optional)
      options:
        - Documentation is wrong/outdated
        - Tool not working as described
        - Missing information
        - Installation/setup issue
        - Other
    validations:
      required: false

Implementation Checklist

GitHub App

  • Create GitHub App gitlab-mcp-bug-reporter with Issues:Write permission
  • Install on structured-world/gitlab-mcp
  • Store credentials in Cloudflare Pages env vars

Backend (Cloudflare Pages Function)

  • Create docs/functions/api/report-bug.ts
  • Implement JWT signing for GitHub App auth
  • Implement installation token exchange
  • Implement issue creation via GitHub REST API
  • Add honeypot validation
  • Add rate limiting (Cloudflare KV or IP-based)
  • Add CORS headers for docs domain only
  • Error handling: return user-friendly messages

Frontend (VitePress Widget)

  • Create docs/.vitepress/theme/index.ts — extend default theme
  • Create docs/.vitepress/theme/components/BugReportWidget.vue
  • Implement collapsed state (side tab)
  • Implement expanded state (inline form)
  • Implement success/error states
  • Add responsive styles (desktop: side panel, mobile: bottom sheet)
  • Add dark mode support
  • Add accessibility (aria-label, keyboard nav, focus trap in expanded)
  • Add prefers-reduced-motion support

Fallback

  • Create .github/ISSUE_TEMPLATE/bug.yml
  • Add "Or report on GitHub" link in expanded widget footer

Cloudflare Pages Environment Variables

Set via Cloudflare Dashboard > Pages > Settings > Environment Variables:

Variable Description
GITHUB_APP_ID GitHub App numeric ID
GITHUB_APP_PRIVATE_KEY PEM private key (base64 encoded)
GITHUB_APP_INSTALLATION_ID Installation ID for the repo
RATE_LIMIT_KV KV namespace binding (optional, for rate limiting)

Security Considerations

  • Private key NEVER exposed to client (only in Pages Function)
  • CORS restricted to docs domain only
  • Rate limiting prevents abuse
  • Honeypot catches simple bots
  • No user data collected beyond bug description
  • Issues created by bot — no user identity leaked
  • Input sanitized before creating issue (prevent markdown injection in title)

Dependencies

  • Cloudflare Pages (already used for docs hosting)
  • GitHub App (free for public repos)
  • No external services / no third-party widgets
  • No cookies / no tracking

Files to Create/Modify

File Action Purpose
.github/ISSUE_TEMPLATE/bug.yml Create Fallback issue form
docs/functions/api/report-bug.ts Create Serverless backend
docs/.vitepress/theme/index.ts Create Custom theme
docs/.vitepress/theme/components/BugReportWidget.vue Create Widget component
docs/.vitepress/config.mts Modify Add any needed config
docs/package.json Modify Add jose dep for JWT signing

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions