v0.1.0-beta · open beta

QA tracking that lives
inside your app

A draggable floating panel for logging bugs, features, and notes — without leaving the browser. Zero database, zero config. Issues save to a JSON file.

Get it in two minutes

Install directly from GitHub — no npm publish required during beta.

1

Install the package

Pin to a specific release tag:

npm install github:Jgequipaje/qa-center#v0.1.0-beta
2

Add the component

Drop <QACenter /> anywhere in your React tree. It renders a floating button that won't affect your layout.

import { QACenter } from '@purr/qa-center'

export default function App() {
  return (
    <>
      <YourApp />
      <QACenter port={3333} />
    </>
  )
}
3

Start the backend

The Express server handles reads and writes to qa-issues.json. Run it in a separate terminal.

npx qa-center --port 3333

That's it. Click the floating button in the corner of your app to open the drawer.

💡 Requires React 19 as a peer dependency. The backend and frontend must use the same port — use the port prop to keep them in sync.

Local dev workflow

QA Center runs alongside your existing dev server. Two terminals, that's all.

# Terminal 1 — your app (as usual)
npm run dev

# Terminal 2 — QA Center backend
npx qa-center --port 3333

Issues are saved to qa-issues.json in the directory where you run the command. Human-readable and git-friendly.

Share with your team

Commit qa-issues.json to share issue state, or add it to .gitignore to keep it personal.

# Share issues via git
git add qa-issues.json
git commit -m "chore: update qa issues"

# Or keep it local
echo "qa-issues.json" >> .gitignore

Everything you need, nothing you don't

Built for QA engineers and developers who want a lightweight tracker that lives in the browser.

🐛

Issue Tracking

Log bugs with title, description, severity, area, repro steps, expected vs actual, and notes.

Feature Requests

Track feature ideas and enhancements separately from bugs in their own tab.

📝

Notes

Capture QA notes, checklists, and observations that don't fit as issues.

🔍

Search & Filter

Live search across title, area, and description. Filter by status and severity.

🎭

Playwright Linking

Link a Playwright test to any issue. Run it directly from the detail panel and see pass/fail.

📑

Pagination

Issue lists paginate at 10 per page so large backlogs stay manageable.

🌗

Dark / Light Theme

Toggle between dark and light mode. Preference is persisted to localStorage.

🖱️

Draggable Button

The floating button snaps to the left or right edge. Position saved per browser.

🐱

Neko Cat

An animated cat sits on the floating button. Enable with the neko prop. Sprite based on oneko.js by adryd325, originally from Neko (1989) by Naoshi Watanabe.

Issue lifecycle

Issues follow a structured workflow with valid transitions enforced in the UI.

open in progress ready for QA verified closed

Closed issues can always be re-opened back to open.

Verification gating — an issue cannot be marked verified unless its linked Playwright test exists and has passed.

Features & Notes

Features use a simplified workflow: open → in progress → verified (done) → closed.

Notes use: open → closed (archived).

Component props

All props are optional. The component works out of the box with just <QACenter />.

Prop Type Default Description
port number 3333 Port the Express backend is running on
apiBaseUrl string Full base URL if not using localhost — overrides port
name string "QA Center" Label shown in the drawer header
buttonColor string | { dark, light } #7c3aed Floating button color. Pass an object for per-theme values
buttonSize number 52 Button diameter in px
shape "circle" | "rounded" | "square" "circle" Shape of the floating button
logo ReactNode Custom icon rendered inside the button
ownTheme boolean true Set to false if your app already has a ThemeProvider
neko boolean false Show an animated cat sitting on the button

Examples

// Custom color per theme
<QACenter
  buttonColor={{ dark: "#7c3aed", light: "#6d28d9" }}
  name="Bug Tracker"
  shape="rounded"
/>

// Already have a ThemeProvider?
<QACenter ownTheme={false} port={4000} />

// With the neko cat
<QACenter neko />

Next.js & React Router v7

QA Center uses window, localStorage, and requestAnimationFrame which don't exist on the server. The component handles this with a built-in SSR guard, but placement matters.

React Router v7 (framework mode)

Place it in your root layout inside <body>. The SSR guard handles the rest.

// app/root.tsx
import { QACenter } from "@purr/qa-center";

export function Layout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <head>...</head>
      <body>
        {children}
        <QACenter port={3333} />
        <ScrollRestoration />
        <Scripts />
      </body>
    </html>
  );
}

Next.js (App Router)

Wrap it in a client component first.

// components/QACenterWrapper.tsx
"use client";
import { QACenter } from "@purr/qa-center";
export default function QACenterWrapper() {
  return <QACenter port={3333} />;
}

// app/layout.tsx
import QACenterWrapper from "@/components/QACenterWrapper";
export default function RootLayout({ children }) {
  return (
    <html><body>
      {children}
      <QACenterWrapper />
    </body></html>
  );
}
💡 The component returns null on the server and mounts only after hydration — no dynamic imports or lazy loading needed on your end.

Backend server options

The CLI starts the Express server that handles all reads and writes to qa-issues.json.

npx qa-center                           # default port 3333, opens browser
npx qa-center --port 4000               # custom port
npx qa-center --no-open                 # skip auto-opening browser
npx qa-center --data-dir ./qa-data      # store data outside Vite watch scope
⚠️ Using Vite + React Router v7? Updating issues may trigger HMR reloads because Vite watches qa-issues.json. Fix: run with --data-dir ../qa-data to store the file outside your project root.

API Endpoints

All endpoints are served at http://localhost:3333 (or your configured port).

Issues

Method Route Description
GET /api/qa-issues Return all issues, newest first
POST /api/qa-issues Create a new issue
PATCH /api/qa-issues/:id Update issue fields or status
DELETE /api/qa-issues/:id Delete an issue
POST /api/qa-issues/:id/run-test Run the linked Playwright test

Tests

Method Route Description
GET /api/qa-tests Return cached Playwright test list
POST /api/qa-tests Force rescan of test directories

Status

Method Route Description
GET /api/status Server health, issue summary, test cache info

POST /api/qa-issues — body

{
  "title": "Bug title",          // required
  "origin": "manual",            // manual | feature | note | imported_markdown
  "status": "open",              // open | in_progress | ready_for_qa | verified | closed
  "severity": "high",            // critical | high | medium | low | info
  "area": "Auth",
  "description": "What is the bug?",
  "reproSteps": "1. Go to...",
  "expected": "Should work",
  "actual": "Doesn't work",
  "notes": "Additional notes"
}

PATCH /api/qa-issues/:id — body

{
  "status": "in_progress",
  "notes": "Updated notes"
}