
Threejs Qa Release
- 1.1k installs
- 1.2k repo stars
- Updated July 16, 2026
- majidmanzarpour/threejs-game-skills
Helps with ai & agent building tasks.
About
threejs-qa-release is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- threejs-qa-release
- AI & Agent Building
- AI-coding skill
Threejs Qa Release by the numbers
- 1,080 all-time installs (skills.sh)
- +114 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #981 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/majidmanzarpour/threejs-game-skills --skill threejs-qa-releaseAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.1k |
|---|---|
| repo stars | ★ 1.2k |
| Last updated | July 16, 2026 |
| Repository | majidmanzarpour/threejs-game-skills ↗ |
What it does
Helps with ai & agent building tasks.
Files
Three.js QA Release
Purpose
Prove the game works as a player encounters it, then prepare a shippable browser build with known risks.
QA Workflow
Load references/qa-release-checklists.md as the first action before broad QA, mobile verification, bug reporting, production preview, static-hosting checks, or release preparation. Track it in a reference ledger with yes/no, path, and failure reason. Do not mark QA/release complete while this reference is skipped for QA or release work.
Load references/checklists/visual-verification.md for screenshot/canvas verification, references/checklists/playtest-qa.md for player-loop QA, and references/checklists/release.md for production release checks. Load references/prompt-templates.md only when the user asks for reusable QA/release prompts or a task template.
1. Install dependencies if needed. 2. Run build/typecheck. 3. Start dev or preview server. 4. Open browser target. 5. Capture console/page/network errors. 6. Verify nonblank canvas pixels. 7. Capture desktop and mobile screenshots. 8. Trigger main input, objective progression, fail/retry, and recent risky paths. 9. Check HUD text fit, safe areas, touch targets, responsive layout. 10. If audio changed, verify user-gesture unlock, SFX triggers, ambience loop start/stop, pause/restart cleanup, mute/volume behavior, and decode/load errors. 11. Record artifacts and issues.
Packaged Canvas Inspector
Use the bundled inspector when the target project does not already include one:
node <this-skill-dir>/scripts/inspect-threejs-canvas.mjs --url http://127.0.0.1:5188For mobile emulation, add --mobile. Generated games from the packaged scaffold also include their own scripts/inspect-threejs-canvas.mjs and npm run inspect:canvas.
Release Workflow
1. Inspect package scripts, Vite config, base path, public/assets. 2. Gate debug UI/logging/test helpers. 3. Run production build and preview/static server. 4. Verify built output desktop/mobile. 5. Review bundle and large assets. 6. Document deploy command, host assumptions, and residual risks.
Final Response
Lead with pass/fail. Include the reference ledger, QA matrix/checklist result, commands, URL, controls, screenshots/artifacts, issues found/fixed, deployment notes, and risks.
interface:
display_name: "Three.js QA Release"
short_description: "Verify and release Three.js games"
default_prompt: "Verify this Three.js game with browser QA, screenshots, canvas checks, responsive/mobile checks, production build, and release risk notes. First load the QA/release checklist reference, report the reference ledger, and include a pass/fail QA matrix."
Playtest QA Checklist
- Start from a clean load.
- Play through the main loop for at least 2 minutes.
- Verify controls, camera, objective feedback, failure/retry, and progression.
- Try rapid input changes and edge movement against arena boundaries.
- Trigger collisions from multiple angles.
- Pause, restart, resize, and refocus the tab if supported.
- Check audio unlock and volume behavior after the first gesture.
- Watch for unreadable moments, camera occlusion, jitter, and missed feedback.
- Capture screenshots for desktop and mobile.
- Record bugs as reproduction steps with expected and actual behavior.
Release Checklist
npm run buildpasses.npm run previewor equivalent static server runs the built files.- Asset URLs work with the intended Vite
basepath. - No local-only files, debug panels, or test overlays are visible unless intentionally gated.
- Console is clean in production preview.
- Desktop and mobile visual checks pass.
- Main interaction works in production preview.
- Bundle size and large assets are reviewed.
- License/source notes for third-party assets are present.
- Final report includes commands, screenshots/artifacts, known risks, and deployment notes.
Visual Verification Checklist
- Open the local dev or preview URL in a browser.
- Check browser console errors and page errors.
- Confirm the canvas has nonzero display size and drawing-buffer size.
- Capture a screenshot.
- Sample canvas pixels for nonblank output and color variance.
- Test at desktop, laptop, and mobile viewport sizes.
- Confirm camera aspect updates after resize.
- Confirm UI/HUD text does not overlap or clip.
- Interact for at least one core action and observe visible state change.
- If using snapshots, make dynamic effects deterministic or mask them.
- If HUD/menu layout changed, also use
threejs-game-ui-designer/references/checklists/game-ui-quality.md,threejs-game-ui-designer/references/checklists/hud-readability.md, andthreejs-game-ui-designer/references/checklists/responsive-ui-fit.md. - If procedural models/materials changed, also use
threejs-aaa-graphics-builder/references/checklists/procedural-model-quality.md,threejs-aaa-graphics-builder/references/checklists/material-lighting-quality.md, andthreejs-aaa-graphics-builder/references/checklists/performance-safe-visual-detail.md. - If the target is premium, AAA, complete, release-ready, or showcase quality, also use
threejs-aaa-graphics-builder/references/checklists/aaa-game-quality-gate.md. - If screenshots still look basic, also use
threejs-aaa-graphics-builder/references/checklists/aaa-visual-scorecard.md. - If the game is an endless runner, also use
threejs-gameplay-systems/references/checklists/endless-runner-premium-quality.md.
Three.js QA/Release Prompt Templates
Reusable prompt templates packaged with this skill. Use only templates relevant to the current request, and adapt placeholders to the game/project context.
---
Release Pass Prompt
Use threejs-qa-release to prepare this Three.js game for release.
Release target:
- static host, GitHub Pages, Netlify, Vercel, itch.io, or other:
Requirements:
- Run production build and preview.
- Verify asset paths under the intended base path.
- Check bundle size and large assets.
- Run desktop and mobile visual QA.
- Confirm no debug-only UI leaks unless intentionally enabled.
- Produce final report with commands, artifacts, screenshots, and residual risks.
QA And Release Checklists
Use this before calling a Three.js browser game complete, premium, release-ready, or fixed.
Browser QA Matrix
Minimum meaningful QA:
- Dependencies installed or known.
- Build/typecheck passes.
- Dev or preview server opened at the correct URL.
- Console/page/network errors captured.
- Canvas nonblank and visually varied through pixel sampling.
- Desktop active-play screenshot.
- Mobile active-play screenshot when mobile is in scope.
- Main input path changes game state.
- Objective/progress path works.
- Fail/retry or pause/resume path works when relevant.
- Recent or risky code paths triggered.
- Physics-heavy games: engine choice, fixed timestep, body/collider count, collision/trigger path, high-speed tunneling check, and restart body cleanup verified.
- HUD text fit, overlap, safe areas, and touch targets checked when UI changed.
- Renderer diagnostics captured when graphics complexity changed.
- Imported/generated asset paths, file sizes, and runtime load behavior checked when external assets changed.
- Audio unlock, decode/load, loop cleanup, mute/volume, and main SFX triggers checked when audio changed.
Interaction QA
Test what a player actually does:
- Start or resume.
- Move/aim/steer/jump/attack/boost as appropriate.
- Collect or score.
- Avoid or hit a hazard.
- Trigger a state change: combo, wave, checkpoint, damage, shield, fail, win.
- Pause and resume.
- Restart after fail.
- For physics games, verify bodies reset cleanly after restart and no stale bodies keep simulating.
- For audio, verify user-gesture unlock, main SFX triggers, ambience loop start/stop, pause/resume, restart cleanup, and mute/volume controls.
- Resize or rotate when responsive/mobile is in scope.
Do not rely only on screenshots for gameplay changes.
Visual QA
For premium/AAA/showcase or "less basic" requests:
- Capture active-play screenshot before and after when possible.
- Use the visual scorecard.
- Check for automatic failures:
- primitive-dominant active screenshot
- flat plane/box skyline world
- generic stat-card HUD
- one repeated obstacle/reward silhouette
- fog/glow/darkness hiding missing geometry
- no renderer diagnostics
- Confirm UI and VFX do not obscure threats, rewards, player, or next decision.
- Confirm desktop and mobile framing both show the playable path.
- For generated 3D assets, confirm imported models have correct scale, orientation, material readability, collision proxies, and animation clips in active gameplay.
Mobile QA
- Touch controls emit game intents.
- Pointer release/cancel/blur cannot leave controls stuck.
- Safe areas respected.
- Touch targets reachable and separated.
- Page scroll does not steal gameplay input.
- Orientation/resize preserves canvas and HUD.
- DPR/performance acceptable.
- Desktop input still works unless intentionally removed.
- UI remains readable on narrow screens.
Performance QA
When draw calls, asset counts, shaders, shadows, or post-processing changed:
- Record renderer calls, triangles, geometries, textures.
- Record FPS/frame time if available.
- Record physics engine, timestep, body count, collider count, active sensors, CCD bodies, and known expensive colliders when physics changed.
- Note DPR cap and post/shadow settings.
- Check active gameplay, not only idle view.
- Compare before/after if performance work was requested.
- Report any unmeasured risk honestly.
Release Checks
Before release-ready:
- Production build passes.
- Production preview/static server tested.
- Vite
baseand asset URLs match target host. - Debug GUI, diagnostics overlays, verbose logs, and test shortcuts are gated or removed from player-facing release.
- Bundle and large assets reviewed.
- API keys are not present in client-side code, checked-in files, built assets, or browser-visible environment.
- Public assets load under static hosting assumptions.
- Browser support assumptions documented.
- Deployment command or static artifact location reported.
- Residual risks listed.
Evidence Format
QA result: pass/fail
Commands:
URL:
Controls tested:
Screenshots/artifacts:
Console/page/network errors:
Canvas pixel check:
Desktop/mobile viewports:
Renderer/performance diagnostics:
Physics diagnostics:
External asset evidence:
Audio evidence:
Issues found/fixed:
Residual risks:Bug Report Format
Title:
Severity:
Reproduction steps:
Expected:
Actual:
Browser/viewport/device:
Console/page errors:
Screenshot/artifact:
Likely owner:
Suggested fix:Common Release Failures
- Testing dev server but shipping untested production build.
- Static host base path breaks assets.
- Debug UI visible to players.
- Mobile UI passes screenshot but controls do not work.
- Canvas is nonblank but wrong app is running on the port.
- Physics gameplay looks right visually but collision proxies, sensors, or restart cleanup were not tested.
- Screenshots are title/idle views instead of active play.
- Premium claim has no visual scorecard or renderer diagnostics.
- 3D/image/audio generation API key or generated temporary URLs accidentally exposed in client code.
#!/usr/bin/env node
import { chromium, devices } from '@playwright/test';
import { mkdir, writeFile } from 'node:fs/promises';
import path from 'node:path';
import { PNG } from 'pngjs';
function parseArgs(argv) {
const args = {
url: 'http://127.0.0.1:5188',
out: 'artifacts/canvas-inspection',
mobile: false,
wait: 750,
};
for (let i = 0; i < argv.length; i += 1) {
const value = argv[i];
if (value === '--url') args.url = argv[++i];
else if (value === '--out') args.out = argv[++i];
else if (value === '--mobile') args.mobile = true;
else if (value === '--wait') args.wait = Number(argv[++i]);
else if (value === '-h' || value === '--help') {
console.log('Usage: inspect-threejs-canvas.mjs [--url URL] [--out DIR] [--mobile] [--wait MS]');
process.exit(0);
} else {
throw new Error(`Unknown argument: ${value}`);
}
}
return args;
}
async function sampleCanvas(page) {
const locator = page.locator('canvas').first();
const rect = await locator.boundingBox();
if (!rect || rect.width < 32 || rect.height < 32) {
return { ok: false, reason: 'canvas-too-small', rect };
}
const buffer = await locator.screenshot();
const png = PNG.sync.read(buffer);
let min = 255;
let max = 0;
let alphaPixels = 0;
const colors = new Set();
const stride = Math.max(1, Math.floor((png.width * png.height) / 4096));
for (let pixel = 0; pixel < png.width * png.height; pixel += stride) {
const offset = pixel * 4;
const r = png.data[offset];
const g = png.data[offset + 1];
const b = png.data[offset + 2];
const a = png.data[offset + 3];
min = Math.min(min, r, g, b);
max = Math.max(max, r, g, b);
if (a > 0) alphaPixels += 1;
colors.add(`${r >> 4},${g >> 4},${b >> 4},${a >> 6}`);
}
const variance = max - min;
const diagnostics = await page.evaluate(() => {
const canvas = document.querySelector('canvas');
return {
drawingBuffer: canvas
? { width: canvas.width, height: canvas.height }
: null,
game: window.__THREE_GAME_DIAGNOSTICS__ ?? null,
};
});
const ok = alphaPixels > 256 && (variance > 8 || colors.size > 3);
return {
ok,
reason: ok ? 'nonblank' : 'low-variance',
rect,
drawingBuffer: diagnostics.drawingBuffer,
alphaPixels,
variance,
colorBuckets: colors.size,
diagnostics: diagnostics.game,
};
}
async function main() {
const args = parseArgs(process.argv.slice(2));
await mkdir(args.out, { recursive: true });
const browser = await chromium.launch();
const context = await browser.newContext(args.mobile
? { ...devices['iPhone 13'], userAgent: undefined }
: { viewport: { width: 1280, height: 720 }, deviceScaleFactor: 1 });
const page = await context.newPage();
const consoleErrors = [];
const pageErrors = [];
page.on('console', (message) => {
if (message.type() === 'error') consoleErrors.push(message.text());
});
page.on('pageerror', (error) => pageErrors.push(error.message));
await page.goto(args.url, { waitUntil: 'networkidle' });
await page.waitForSelector('canvas', { state: 'visible', timeout: 10_000 });
await page.waitForTimeout(args.wait);
const result = await sampleCanvas(page);
const screenshotPath = path.join(args.out, args.mobile ? 'mobile.png' : 'desktop.png');
await page.screenshot({ path: screenshotPath, fullPage: true });
const report = {
url: args.url,
mode: args.mobile ? 'mobile' : 'desktop',
screenshotPath,
result,
consoleErrors,
pageErrors,
};
await writeFile(path.join(args.out, args.mobile ? 'mobile.json' : 'desktop.json'), `${JSON.stringify(report, null, 2)}\n`);
await browser.close();
console.log(JSON.stringify(report, null, 2));
if (!result.ok || consoleErrors.length > 0 || pageErrors.length > 0) {
process.exit(1);
}
}
main().catch((error) => {
console.error(error);
process.exit(1);
});