.agents/skills/code-quality-review/SKILL.md
Tech-lead-level code quality review for the Tastik codebase. Performs systematic audits targeting SOLID principles, DRY, clean code, testability, and framework best practices (TanStack Query, TanStack Start SSR, Convex, React memoization). Use when asked to: - "Review this component/hook/file for quality" - "Refactor this to be more maintainable" - "Do a code quality pass on [folder/feature]" - "Find code smells in [area]" - "Audit the codebase for best practices" - Running automated quality sweeps on the full codebase
npx skillsauth add FabioFiorita/tastik code-quality-reviewInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
A systematic audit framework for the Tastik codebase. Approach every review as a tech lead who owns long-term maintainability — not as a feature developer shipping fast.
bun typecheck && bun check:write after each batch| Level | Meaning | |-------|---------| | P0 | Bug risk, data loss, security issue — fix immediately | | P1 | Maintainability blocker, violates project conventions — fix in this session | | P2 | Refactor opportunity, DRY violation, premature complexity — prioritize | | P3 | Style/naming/minor consistency — fix opportunistically |
src/hooks/.src/hooks/actions/: wrap useMutation with loading state, error handling, toast. Never return the raw mutation result.src/hooks/queries/: return only the data shape the UI needs; expose queryOptions for loader preloading.src/lib/utils/ pure functionsrc/lib/validation/ schemasrc/lib/constants/convex/schema.ts validators → use Infer<typeof validator> and place in src/lib/types/Correct pattern (always prefer):
// hooks/queries/use-list-items.ts
export function listItemsQueryOptions(listId, includeCompleted, tagId?) {
return convexQuery(api.items.getListItems, { listId, includeCompleted, tagId });
}
export function useListItems(listId, includeCompleted, tagId?, opts?) {
const { data } = useQuery({
...listItemsQueryOptions(listId, includeCompleted, tagId),
enabled: opts?.enabled !== false,
});
return data; // never return the full useQuery result
}
Anti-patterns to find and fix:
useState + useEffect for fetching — replace with useQuery(convexQuery(...))useQuery calls in components — move to a hook in src/hooks/queries/useQuery result from a hook — return only .datauseSuspenseQuery inside non-Suspense boundary without an error boundaryqueryOptions export (needed for route loaders and SSR prefetch)context.queryClient.prefetchQuery(...) for secondary dataensureQueryData in the loader (blocks navigation, shows pendingComponent)prefetchQuery (non-blocking)await non-critical prefetches in loaders — it blocks navigation unnecessarilyparseConvexId before hitting the databasethrow redirect({ to: "/" }) immediately in the loaderloader: async ({ context, params }) => {
const listId = parseConvexId<"lists">(params.listId);
if (!listId) throw redirect({ to: "/" });
const entity = await context.queryClient.ensureQueryData(entityQueryOptions(listId));
if (!entity) throw redirect({ to: "/" });
// fire-and-forget secondary data
context.queryClient.prefetchQuery(secondaryQueryOptions(listId));
return { listId };
},
Apply the react-memoization-guide skill rules. Key rules for Tastik:
useCallback for stable references passed to child components with React.memouseMemo for expensive computations (sorting large arrays, complex filtering) — benchmark firstuseMemo wrapping simple object literals or array mapsasync/await logic directly — delegate to hooksReact.FC<{...}> inline objectsdata-testid on all interactive elements and key UI landmarks (required)cn() from @/lib/utils/cn for conditional classes; never string concatenationprimary, muted, muted-foreground, foreground, background. No arbitrary Tailwind values.Untestable code smells:
import of singletons without injection pointsFor every non-trivial hook or util, check:
vi.fn() returned from the hook file's __mocks export?useNavigate, useCurrentUser, and other framework hooks mocked via src/lib/helpers/mocks?See testing-setup skill for test infrastructure details.
Apply convex-guidelines skill. Key checks:
requireAuth / requireListAccess called at the top of every authenticated functionctx.db.query without an index (full table scans forbidden in production)internalMutation / internalQuery for functions not meant to be called from clientConvexError for user-facing errors, not generic throwsconvex/tests/ for all non-trivial mutations and queriesany — use unknown and narrow, or use the correct generated Convex typesas casts without a comment explaining why it's safe// @ts-ignore without justificationInfer<typeof validator> — no manual duplicationtype over interface for local types (consistency with project style)| Smell | Fix |
|-------|-----|
| useState(false) + useEffect fetching | Replace with useQuery(convexQuery(...)) |
| Long component (>200 lines) | Extract sub-components or move logic to hooks |
| Deeply nested ternaries in JSX | Extract to a variable or helper function |
| Magic numbers/strings inline | Move to src/lib/constants/ |
| console.log left in code | Remove or replace with proper error tracking |
| Repeated try/catch blocks with same pattern | Extract to useHandleMutationError or useManagedAction |
| window.location.href for navigation | Replace with useNavigate() from TanStack Router |
| Promise ignored without error handling | Use useManagedAction or proper .catch() |
| Mutation called directly in component | Move to an action hook in src/hooks/actions/ |
| Unused imports/variables | Remove |
| Optional chaining on things that can't be null | Remove unnecessary ?. |
When asked to do a full sweep (automation-friendly):
Map the surface area
Glob src/components/**/*.tsx → list all components
Glob src/hooks/**/*.ts → list all hooks
Glob convex/*.ts → list all Convex functions
Prioritize by risk — start with hooks/actions (most business logic), then routes (SSR/loader), then components
Per-file audit loop:
After each batch of changes: bun typecheck && bun check:write
Test coverage check:
Glob src/hooks/actions/*.ts → check each has a matching *.test.ts
Glob convex/tests/*.test.ts → verify coverage of backend mutations
Summarize findings in a structured report:
| Concern | Where |
|---------|-------|
| Convex data types | Infer<typeof ...Validator> from convex/schema.ts |
| Query hooks | src/hooks/queries/ — export hook + queryOptions |
| Action hooks | src/hooks/actions/ — wrap mutation, return { action, isPending } |
| UI state hooks | src/hooks/ui/ |
| Pure utils | src/lib/utils/ (no React, no side effects) |
| Constants & static data | src/lib/constants/ |
| Form validation schemas | src/lib/validation/ |
| Domain types | src/lib/types/ |
| Route loaders | src/routes/ — use ensureQueryData for critical, prefetchQuery for secondary |
| Backend logic | convex/ — lib helpers in convex/lib/ |
| Tests (frontend) | Co-located *.test.ts(x) or in src/hooks/.../*.test.ts |
| Tests (Convex) | convex/tests/ |
references/anti-patterns.md — extended examples of each anti-pattern with before/after codeconvex-guidelines skill when auditing Convex backend filestesting-setup skill when writing missing testsreact-memoization-guide skill for memoization decisionstools
Cloudflare Workers CLI for deploying, developing, and managing Workers, KV, R2, D1, Vectorize, Hyperdrive, Workers AI, Containers, Queues, Workflows, Pipelines, and Secrets Store. Load before running wrangler commands to ensure correct syntax and best practices.
development
Reviews and authors Cloudflare Workers code against production best practices. Load when writing new Workers, reviewing Worker code, configuring wrangler.jsonc, or checking for common Workers anti-patterns (streaming, floating promises, global state, secrets, bindings, observability). Biases towards retrieval from Cloudflare docs over pre-trained knowledge.
tools
Analyzes web performance using Chrome DevTools MCP. Measures Core Web Vitals (FCP, LCP, TBT, CLS, Speed Index), identifies render-blocking resources, network dependency chains, layout shifts, caching issues, and accessibility gaps. Use when asked to audit, profile, debug, or optimize page load performance, Lighthouse scores, or site speed.
development
React composition patterns that scale. Use when refactoring components with boolean prop proliferation, building flexible component libraries, or designing reusable APIs. Triggers on tasks involving compound components, render props, context providers, or component architecture. Includes React 19 API changes.