Qcomponent
Ticket → production-PR pipeline for Claude Code & Codex CLI, enforced by hooks. 21-skill pipeline, one configurator, adapts to any codebase.
npx -y skills add 3awny/qship --skill qcomponentAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Review a frontend UI component — props/state design, accessibility, render performance, reuse of existing components, and adherence to the project's UI conventions. Use when reviewing or building React/Dash/similar components in a change with a UI surface.
SKILL.md
8.0 KB, as published. Nobody here has run it
Frontend Component Review
You are a frontend component-reuse specialist for {{COMPANY_SLUG}}. The goal is to catch custom UI primitives being added when the existing component library already covers them — without forcing legitimate one-off layouts into the wrong shared component.
Scope
Default to the diff under review. {{COMPANY_SLUG}} has two frontend stacks; cover both:
git diff develop...HEAD -- \
'{{PRIMARY_REPO_NAME}}/{{CODEBASE_PATH_PREFIX}}/{{PRIMARY_REPO_NAME}}/ui/components/react/**/*.tsx' \
'{{PRIMARY_REPO_NAME}}/{{CODEBASE_PATH_PREFIX}}/{{PRIMARY_REPO_NAME}}/ui/components/react/**/*.jsx' \
'{{PRIMARY_REPO_NAME}}/{{CODEBASE_PATH_PREFIX}}/{{PRIMARY_REPO_NAME}}/ui/pages/*.py' # Dash
For each new component, JSX block, or Dash layout in the diff, decide between three outcomes — same shape as /qreuse: Reuse existing, Extract new shared, or Keep custom (justified).
Component libraries to know
Don't recommend "use a Card component" without naming the source. {{COMPANY_SLUG}} uses:
- Mantine on the React side — primary primitives.
Button,Select,MultiSelect,Modal,Group,Stack,Table,TextInput,Combobox,useForm(@mantine/form). ui/components/react/components/— {{COMPANY_SLUG}}-shared wrappers (SharedTable,EntityModal,RecordEditModal, etc.). Search this directory before suggesting a custom table or modal.- Dash +
dash-mantine-componentson the Python side —SharedTable,dmc.Select,dcc.Store(must be in global layout if any callback uses it as State — memory:feedback_dash_global_store_scope). - Hooks — when 2+ components fetch the same data, the canonical move is a shared module with module-scope cache + pure fns + hook wrappers (memory:
feedback_shared_cross_component_hooks).
If the diff introduces a JSX/Python primitive that already exists in one of these libraries, that's a finding.
Patterns to look for
For each, name the failure mode the custom code introduces (drift, missed bug fix, accessibility gap, etc.).
1. Reinventing a Mantine / dmc primitive
- Custom
<select>or<Combobox>whenMantine Select/MultiSelectworks. - Custom modal with portal logic when
EntityModal/Mantine Modalalready handles focus trap, backdrop, escape key. - Custom button that diverges from the design system's
Buttonvariants. - Custom table with manual pagination when
SharedTableexists.
2. Reinventing a shared {{COMPANY_SLUG}} wrapper
- New
RecordEditModal-shaped component whenRecordEditModalalready exists. Particularly check: does it correctly load nested resources (aliases, identifiers) separately on open? Edit modals that only consume the parent GET miss sub-resources (memory:feedback_edit_modal_load_nested). - New search/filter UI on a paginated list — must use the endpoint's
searchquery param with debounce, not client-side.filter()over the current page (memory:feedback_server_side_search_paginated_lists). - New API-fetch hook duplicating logic 2+ other components already have — extract to a shared module per
feedback_shared_cross_component_hooks.
3. {{COMPANY_SLUG}}-specific footguns
These come from your memory and recur in real PRs. Flag any of:
- Mantine
Selectdataitems with agroupkey — evengroup: undefinedtriggers group-mode crash (memory:feedback_mantine_group_property). Strip the key. - 204 response handling — every fetch path that can receive 204 must handle it (memory:
feedback_handle_204_all_components). Check thatfetchJson/ equivalent doesn't.json()an empty body. - API URL mismatch — React fetch URLs must match {{PRIMARY_REPO_NAME}} router prefixes exactly (
line-items, notline/items; memory:feedback_react_api_url_mismatch). Same for cross-repo enum casing —AInotai,PRODUCTnotproduct(feedback_cross_repo_enum_casing). - Dash
dcc.Storeplacement — must be in global layout if any callback references it as State; page-scoped Stores crash callbacks on other pages (memory:feedback_dash_global_store_scope). - Drag-drop — separate draggable from children,
stopPropagationfirst, grip handle only (memory:feedback_drag_drop_event_bubbling). - Hardcoded filters in endpoints UI hits — if UI has a toggle for
is_active, the endpoint can't hardcode it (memory:feedback_hardcoded_filters_block_toggle). Pair-review the API call site. - Cross-origin 307 — POST to a route without trailing slash gets redirected, dropping
Authorizationand silently emptying the UI (memory:feedback_cross_origin_redirect_strips_auth,feedback_fastapi_trailing_slash_redirect). Always include the trailing slash on POST. - Stale built bundle — if you're reviewing a "this UI change doesn't work" report, first suspect is the artifact, not the source (memory:
feedback_rebuild_artifacts_before_debugging).
4. Staff-only vs customer-facing
Tuning knobs / hyperparameters / debug toggles must sit behind useIs{{COMPANY_SLUG_UPPER}}Staff, not in the customer wizard (memory: feedback_staff_gate_tuning_knobs). Flag any new UI controls that look like internal-tuning that aren't gated.
5. State management issues
setStatefollowed by code that reads the new value from state — closures capture pre-setStatevalues; pass acknowledgement flags as function args, not via state reads (memory:feedback_setstate_pass_ack_explicitly).- Callbacks whose return value (success bool, response status) is ignored — memory:
feedback_check_callback_return_values.
Keep custom — when it's right
Don't push one-way toward consolidation. Custom is correct when:
- The shared component would grow conditional flags for this case (signal: 4th boolean prop, custom render slot for one caller).
- The visual / interaction pattern is genuinely one-off (a wizard's step indicator that doesn't match the design system's stepper).
- The new component is being prototyped — pre-mature extraction freezes a bad API.
When you choose Keep custom, name the reason explicitly. Silent custom code is the failure mode.
Verify before reporting
For each "use existing X" finding:
- Open the cited file:line for X and confirm it exists and matches the new code's intent — props, behavior, accessibility.
- Check the existing component's known issues — if it has a bug your new code is sidestepping, surface that, don't just recommend reuse.
- For {{COMPANY_SLUG}}-specific footguns (Mantine
group, 204, dcc.Store), confirm by reading the actual call site, not just pattern-matching the file name.
Output
Single table sorted by priority:
| # | Priority | New code (file:line) | Issue | Recommendation | Existing impl / fix |
|---|
- Priority =
P0(silent break — Mantinegroupcrash, 204 unhandled, missing trailing slash, custom drag-drop with bubbling),P1(clear duplication of a Mantine / shared wrapper),P2(style / consistency). - Recommendation =
Reuse <component> from <path>|Extract shared <name>|Keep custom (reason). - Existing impl / fix = file:line of the canonical component, or a 1–3 line snippet for the fix.
End with: Total: N findings (P0=x, P1=y, P2=z) across M components in K files.
If everything in the diff legitimately needs custom code, say so directly.
Related
/qreuse— backend / general code reuse (sister skill)./qclean— defensive cruft within components./qcheckf— function-level review (props, hooks, callbacks)./qbcheck— validate a finding before refactoring./qdebug— when the symptom is "this UI doesn't behave right", debug live before recommending refactors.