@mrciphersmith/keryx 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/dist/cli.js +13362 -7078
- package/dist/core.js +11706 -11330
- package/package.json +1 -1
- package/src/gdskills/bundled/agents/go-code-auditor.md +1 -1
- package/src/gdskills/bundled/agents/python-code-auditor.md +1 -1
- package/src/gdskills/bundled/install-manifest.json +271 -4
- package/src/gdskills/bundled/rules/core/model-selection.mdc +51 -0
- package/src/gdskills/bundled/skills/review/review-jev-comments/SKILL.md +184 -0
- package/src/gdskills/bundled/skills/review/review-jev-docs/SKILL.md +189 -0
- package/src/gdskills/bundled/skills/review/review-jev-risk/SKILL.md +190 -0
- package/src/gdskills/bundled/skills/review/review-jev-rules/SKILL.md +267 -0
- package/src/gdskills/bundled/skills/review/review-jev-scenarios/SKILL.md +187 -0
- package/src/gdskills/bundled/skills/review/review-orchestrator/SKILL.detail.md +39 -0
- package/src/gdskills/bundled/skills/review/review-orchestrator/SKILL.md +1 -1
- package/src/gdskills/bundled/stacks/angular/agent-refs.json +4 -0
- package/src/gdskills/bundled/stacks/angular/governance/eval.json +1751 -0
- package/src/gdskills/bundled/stacks/angular/governance/scout.json +32 -0
- package/src/gdskills/bundled/stacks/angular/pack.json +55 -0
- package/src/gdskills/bundled/stacks/angular/rules/coding-style.mdc +82 -0
- package/src/gdskills/bundled/stacks/angular/rules/patterns.mdc +84 -0
- package/src/gdskills/bundled/stacks/angular/rules/security.mdc +70 -0
- package/src/gdskills/bundled/stacks/angular/rules/testing.mdc +73 -0
- package/src/gdskills/bundled/stacks/angular/skills/angular-build-fix/SKILL.md +127 -0
- package/src/gdskills/bundled/stacks/angular/skills/angular-build-fix/evals.json +72 -0
- package/src/gdskills/bundled/stacks/angular/skills/angular-code-review/SKILL.md +98 -0
- package/src/gdskills/bundled/stacks/angular/skills/angular-code-review/evals.json +73 -0
- package/src/gdskills/bundled/stacks/angular/skills/angular-implementation/SKILL.md +112 -0
- package/src/gdskills/bundled/stacks/angular/skills/angular-implementation/evals.json +74 -0
- package/src/gdskills/bundled/stacks/angular/skills/angular-testing/SKILL.md +102 -0
- package/src/gdskills/bundled/stacks/angular/skills/angular-testing/evals.json +71 -0
- package/src/gdskills/bundled/stacks/mobx/agent-refs.json +4 -0
- package/src/gdskills/bundled/stacks/mobx/governance/eval.json +904 -0
- package/src/gdskills/bundled/stacks/mobx/governance/scout.json +18 -0
- package/src/gdskills/bundled/stacks/mobx/pack.json +28 -0
- package/src/gdskills/bundled/stacks/mobx/rules/coding-style.mdc +91 -0
- package/src/gdskills/bundled/stacks/mobx/rules/patterns.mdc +122 -0
- package/src/gdskills/bundled/stacks/mobx/rules/security.mdc +56 -0
- package/src/gdskills/bundled/stacks/mobx/rules/testing.mdc +63 -0
- package/src/gdskills/bundled/stacks/mobx/skills/mobx-observable-testing/SKILL.md +124 -0
- package/src/gdskills/bundled/stacks/mobx/skills/mobx-observable-testing/evals.json +73 -0
- package/src/gdskills/bundled/stacks/mobx/skills/mobx-store-implementation/SKILL.md +149 -0
- package/src/gdskills/bundled/stacks/mobx/skills/mobx-store-implementation/evals.json +74 -0
- package/src/gdskills/bundled/stacks/nestjs/agent-refs.json +4 -0
- package/src/gdskills/bundled/stacks/nestjs/governance/eval.json +1308 -0
- package/src/gdskills/bundled/stacks/nestjs/governance/scout.json +34 -0
- package/src/gdskills/bundled/stacks/nestjs/pack.json +53 -0
- package/src/gdskills/bundled/stacks/nestjs/rules/coding-style.mdc +70 -0
- package/src/gdskills/bundled/stacks/nestjs/rules/patterns.mdc +83 -0
- package/src/gdskills/bundled/stacks/nestjs/rules/security.mdc +73 -0
- package/src/gdskills/bundled/stacks/nestjs/rules/testing.mdc +69 -0
- package/src/gdskills/bundled/stacks/nestjs/skills/nestjs-build-fix/SKILL.md +157 -0
- package/src/gdskills/bundled/stacks/nestjs/skills/nestjs-build-fix/evals.json +70 -0
- package/src/gdskills/bundled/stacks/nestjs/skills/nestjs-implementation/SKILL.md +129 -0
- package/src/gdskills/bundled/stacks/nestjs/skills/nestjs-implementation/evals.json +71 -0
- package/src/gdskills/bundled/stacks/nestjs/skills/nestjs-testing/SKILL.md +143 -0
- package/src/gdskills/bundled/stacks/nestjs/skills/nestjs-testing/evals.json +69 -0
- package/src/gdskills/bundled/stacks/nextjs-nuxt/agent-refs.json +4 -0
- package/src/gdskills/bundled/stacks/nextjs-nuxt/governance/eval.json +2413 -0
- package/src/gdskills/bundled/stacks/nextjs-nuxt/governance/scout.json +42 -0
- package/src/gdskills/bundled/stacks/nextjs-nuxt/pack.json +42 -0
- package/src/gdskills/bundled/stacks/nextjs-nuxt/rules/coding-style.mdc +69 -0
- package/src/gdskills/bundled/stacks/nextjs-nuxt/rules/patterns.mdc +88 -0
- package/src/gdskills/bundled/stacks/nextjs-nuxt/rules/security.mdc +72 -0
- package/src/gdskills/bundled/stacks/nextjs-nuxt/rules/testing.mdc +64 -0
- package/src/gdskills/bundled/stacks/nextjs-nuxt/skills/nextjs-nuxt-build-fix/SKILL.md +147 -0
- package/src/gdskills/bundled/stacks/nextjs-nuxt/skills/nextjs-nuxt-build-fix/evals.json +75 -0
- package/src/gdskills/bundled/stacks/nextjs-nuxt/skills/nextjs-nuxt-code-review/SKILL.md +118 -0
- package/src/gdskills/bundled/stacks/nextjs-nuxt/skills/nextjs-nuxt-code-review/evals.json +76 -0
- package/src/gdskills/bundled/stacks/nextjs-nuxt/skills/nextjs-nuxt-implementation/SKILL.md +135 -0
- package/src/gdskills/bundled/stacks/nextjs-nuxt/skills/nextjs-nuxt-implementation/evals.json +78 -0
- package/src/gdskills/bundled/stacks/nextjs-nuxt/skills/nextjs-nuxt-testing/SKILL.md +116 -0
- package/src/gdskills/bundled/stacks/nextjs-nuxt/skills/nextjs-nuxt-testing/evals.json +75 -0
- package/src/gdskills/bundled/stacks/nextjs-nuxt/skills/nextjs-nuxt-upgrade-migration/SKILL.md +134 -0
- package/src/gdskills/bundled/stacks/nextjs-nuxt/skills/nextjs-nuxt-upgrade-migration/evals.json +76 -0
- package/src/gdskills/bundled/stacks/vue/agent-refs.json +4 -0
- package/src/gdskills/bundled/stacks/vue/governance/eval.json +2215 -0
- package/src/gdskills/bundled/stacks/vue/governance/scout.json +42 -0
- package/src/gdskills/bundled/stacks/vue/pack.json +42 -0
- package/src/gdskills/bundled/stacks/vue/rules/coding-style.mdc +73 -0
- package/src/gdskills/bundled/stacks/vue/rules/patterns.mdc +84 -0
- package/src/gdskills/bundled/stacks/vue/rules/security.mdc +60 -0
- package/src/gdskills/bundled/stacks/vue/rules/testing.mdc +69 -0
- package/src/gdskills/bundled/stacks/vue/skills/vue-build-fix/SKILL.md +137 -0
- package/src/gdskills/bundled/stacks/vue/skills/vue-build-fix/evals.json +72 -0
- package/src/gdskills/bundled/stacks/vue/skills/vue-code-review/SKILL.md +120 -0
- package/src/gdskills/bundled/stacks/vue/skills/vue-code-review/evals.json +71 -0
- package/src/gdskills/bundled/stacks/vue/skills/vue-implementation/SKILL.md +122 -0
- package/src/gdskills/bundled/stacks/vue/skills/vue-implementation/evals.json +72 -0
- package/src/gdskills/bundled/stacks/vue/skills/vue-testing/SKILL.md +115 -0
- package/src/gdskills/bundled/stacks/vue/skills/vue-testing/evals.json +72 -0
- package/src/gdskills/bundled/stacks/vue/skills/vue2-to-vue3-migration/SKILL.md +135 -0
- package/src/gdskills/bundled/stacks/vue/skills/vue2-to-vue3-migration/evals.json +71 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nextjs-nuxt-code-review
|
|
3
|
+
description: "Use when reviewing a diff that touches Next.js App Router files ('use client'/'use server' directives, Route Handlers, revalidatePath/revalidateTag) or Nuxt files (composables, server/api routes, nuxt.config.ts routeRules/runtimeConfig) for meta-framework-specific risk: a misplaced Server/Client boundary, a composable called outside setup context, a hydration-mismatch-prone render, a rendering-mode choice that doesn't match the data's actual freshness need, or an unauthenticated Server Action/server route. Does not edit code. Not for general React/Vue component review with no App Router/Nuxt-specific concern (use review-frontend or a react/vue pack review skill), and not for NestJS backend review (use review-backend)."
|
|
4
|
+
triggers:
|
|
5
|
+
- "review this Next.js server action for auth issues"
|
|
6
|
+
- "check this diff for use client boundary mistakes"
|
|
7
|
+
- "review this Nuxt server/api route"
|
|
8
|
+
- "does this Nuxt composable get called outside setup"
|
|
9
|
+
- "review the rendering mode choice on this Next.js route"
|
|
10
|
+
- "check for hydration mismatch risk in this component"
|
|
11
|
+
- "review this nuxt.config routeRules change"
|
|
12
|
+
metadata:
|
|
13
|
+
origin: authored
|
|
14
|
+
category: review
|
|
15
|
+
version: "1.0.0"
|
|
16
|
+
compatible_harnesses: "claude,codex,cursor,zed,opencode"
|
|
17
|
+
license: "MIT"
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
# Next.js / Nuxt code review
|
|
21
|
+
|
|
22
|
+
Review a diff touching Next.js App Router or Nuxt files for
|
|
23
|
+
meta-framework-specific risk. This skill reviews and reports; it does not
|
|
24
|
+
edit code. See `rules/patterns.mdc` and `rules/security.mdc` for the full
|
|
25
|
+
rationale behind each check below.
|
|
26
|
+
|
|
27
|
+
## Workflow
|
|
28
|
+
|
|
29
|
+
### Step 1: Scope the diff by framework
|
|
30
|
+
|
|
31
|
+
- Identify which files are Next.js (`app/**`, `'use client'`/`'use
|
|
32
|
+
server'` directives, `route.ts` handlers) vs. Nuxt (`pages/**`,
|
|
33
|
+
`composables/**`, `server/api/**`, `nuxt.config.ts`) — apply the
|
|
34
|
+
matching checklist below to each; a monorepo diff may need both.
|
|
35
|
+
|
|
36
|
+
### Step 2: Check the Server/Client boundary (Next.js)
|
|
37
|
+
|
|
38
|
+
- Every `'use client'` is on the smallest component that actually needs
|
|
39
|
+
browser state, an event handler, or a browser API — not on a shared
|
|
40
|
+
layout, a page, or an ancestor of the component that needs it.
|
|
41
|
+
- No Server Component reads `cookies()`/`headers()` and then passes the
|
|
42
|
+
raw session/auth data down as a prop to a Client Component
|
|
43
|
+
unnecessarily — pass only what the client actually needs to render.
|
|
44
|
+
- No server-only import (a DB client, an API key read, a `'use server'`
|
|
45
|
+
file) is reachable from a file that lacks its own server boundary and
|
|
46
|
+
could end up in a Client Component's import chain.
|
|
47
|
+
|
|
48
|
+
### Step 3: Check composable/context usage (Nuxt)
|
|
49
|
+
|
|
50
|
+
- Every composable (`useX`) call sits at the synchronous top level of
|
|
51
|
+
`<script setup>`, a plugin, or middleware — not inside an `async`
|
|
52
|
+
callback, after an `await`, or inside `setTimeout`/an event handler
|
|
53
|
+
where Nuxt's injection context is no longer available the same way.
|
|
54
|
+
- `runtimeConfig` secrets stay out of the `public` block; a component
|
|
55
|
+
never reads a value from `public` that should have been server-only.
|
|
56
|
+
|
|
57
|
+
### Step 4: Check rendering-mode and data-freshness fit
|
|
58
|
+
|
|
59
|
+
- A route/page marked static or ISR (Next's `revalidate`, Nuxt's
|
|
60
|
+
`prerender`/`isr` routeRule) doesn't actually need per-request data
|
|
61
|
+
(auth-gated content, a `searchParams`-dependent result) — that
|
|
62
|
+
combination silently serves stale or wrong data to different users.
|
|
63
|
+
- A mutation (Server Action, Nuxt server route) that changes displayed
|
|
64
|
+
data calls `revalidatePath()`/`revalidateTag()` (Next.js) or otherwise
|
|
65
|
+
invalidates the relevant cached data (Nuxt) — a missing revalidate
|
|
66
|
+
leaves the UI showing stale data after a successful write.
|
|
67
|
+
|
|
68
|
+
### Step 5: Check hydration-mismatch risk
|
|
69
|
+
|
|
70
|
+
- No component renders `Date.now()`, `Math.random()`, or
|
|
71
|
+
locale/timezone-dependent formatting directly in its render path
|
|
72
|
+
without a client-only guard or a stable server-computed value — flag it
|
|
73
|
+
even if the diff's own tests pass, since a mismatch often only shows up
|
|
74
|
+
as a console warning in a real browser, not in a unit test.
|
|
75
|
+
|
|
76
|
+
### Step 6: Check Server Action / server route auth
|
|
77
|
+
|
|
78
|
+
- Every `'use server'` action and `server/api/**` handler checks
|
|
79
|
+
auth/authorization and re-validates its own input inside the
|
|
80
|
+
action/handler — not only relying on a middleware check or the
|
|
81
|
+
client-side form validation that called it. See `rules/security.mdc`.
|
|
82
|
+
|
|
83
|
+
### Step 7: Report
|
|
84
|
+
|
|
85
|
+
List each finding with file:line, what's wrong, and the concrete fix
|
|
86
|
+
(quote `rules/patterns.mdc`/`rules/security.mdc` by name where relevant).
|
|
87
|
+
Do not modify the code under review.
|
|
88
|
+
|
|
89
|
+
## Rules
|
|
90
|
+
|
|
91
|
+
- This is a review skill: report findings, do not edit the reviewed
|
|
92
|
+
files.
|
|
93
|
+
- Follow `rules/patterns.mdc` for boundary/rendering-mode/data-fetching
|
|
94
|
+
checks and `rules/security.mdc` for auth/env-var checks.
|
|
95
|
+
- Flag a missing auth check on a Server Action/server route as a
|
|
96
|
+
correctness-blocking finding, not a style nit.
|
|
97
|
+
|
|
98
|
+
## Red Flags
|
|
99
|
+
|
|
100
|
+
| Rationalization | Why it is wrong |
|
|
101
|
+
|---|---|
|
|
102
|
+
| "'use client' is on the page, but that's fine, it's simpler to review as one unit" | A page-level 'use client' ships the whole subtree to the browser; it is exactly the finding this review exists to catch, not something to wave through for simplicity |
|
|
103
|
+
| "The server action's caller already validates the form, so the handler check can be skipped in review" | The handler is a directly reachable endpoint regardless of what called it; flag the missing server-side check |
|
|
104
|
+
| "The composable is called inside onMounted, that still runs after setup so it's probably fine" | onMounted callbacks run after Nuxt's synchronous setup-time context resolution window for some composable patterns; flag it for verification rather than assuming it's safe |
|
|
105
|
+
| "Date.now() in the render is just a display nicety, not worth flagging" | It is a concrete hydration-mismatch source (server render time vs. client render time differ); flag it regardless of how minor the visual impact looks |
|
|
106
|
+
|
|
107
|
+
## Verification
|
|
108
|
+
|
|
109
|
+
Before finishing the review, confirm:
|
|
110
|
+
|
|
111
|
+
- Every `'use client'`/`'use server'` directive in the diff was checked
|
|
112
|
+
against its actual placement, not assumed correct.
|
|
113
|
+
- Every new/changed Nuxt composable call site was checked for
|
|
114
|
+
synchronous setup-context placement.
|
|
115
|
+
- Every new/changed Server Action or `server/api/**` handler was checked
|
|
116
|
+
for its own auth/validation, independent of client-side checks.
|
|
117
|
+
- The report names file:line for each finding and the concrete fix, not
|
|
118
|
+
just "check the boundary here".
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{
|
|
2
|
+
"triggers": {
|
|
3
|
+
"positive": [
|
|
4
|
+
"Review this Next.js server action diff for missing auth checks before it merges",
|
|
5
|
+
"In the app router pages touched by this diff, can you check for any 'use client' boundary mistakes?",
|
|
6
|
+
"There's a new server/api/orders.ts route in this Nuxt app that needs review, can you check it for security issues?",
|
|
7
|
+
"One of the reviewers on my team flagged that a composable in this PR might be running too late in the component lifecycle -- can you take a look and confirm whether that's a real problem?",
|
|
8
|
+
"This product page is marked for static generation, but the data behind it changes every few minutes -- before I approve this PR, can you sanity-check that the caching story here actually makes sense?",
|
|
9
|
+
"Before this ships, can you check whether this component carries any hydration mismatch risk given how it renders?",
|
|
10
|
+
"Someone on the team tweaked the SPA-only flag for one of our nuxt.config.ts routes and opened a PR -- can you sanity-check the change before I approve it?"
|
|
11
|
+
],
|
|
12
|
+
"negative": [
|
|
13
|
+
"Implement a new Next.js server action for creating an order",
|
|
14
|
+
"Write a test for this Nuxt composable that calls useAsyncData",
|
|
15
|
+
"Fix this nuxi typecheck failure on an auto-imported composable",
|
|
16
|
+
"Migrate this Next.js pages router app to the app router",
|
|
17
|
+
"Review this plain React component for accessibility issues, no App Router concern",
|
|
18
|
+
"Review this Python data pipeline function for missing exception handling"
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
"scenarios": [
|
|
22
|
+
{
|
|
23
|
+
"id": "flag-missing-server-action-auth",
|
|
24
|
+
"prompt": "Here's a Next.js server action: it's marked 'use server', takes an orderId and a new status, and calls db.order.update({ where: { id: orderId }, data: { status } }) with no other logic. What should this review flag?",
|
|
25
|
+
"strictness": "high",
|
|
26
|
+
"expected_behavior": [
|
|
27
|
+
{ "grader": "regex", "value": "auth" },
|
|
28
|
+
{
|
|
29
|
+
"grader": "judge",
|
|
30
|
+
"rubric": "A correct review flags that the server action has no authentication/authorization check before performing the database write, explaining that a Server Action is a directly reachable endpoint and must check the caller's identity and permission on that specific order, not rely on the calling UI having already checked.",
|
|
31
|
+
"pass_criteria": [
|
|
32
|
+
"Explicitly flags the missing auth/authorization check as the finding, not a minor style note",
|
|
33
|
+
"States that a Server Action is directly callable/reachable regardless of which UI called it, so it must check auth itself",
|
|
34
|
+
"Names what the fix should verify: the caller is authenticated and is authorized to modify this specific order (not just any orderId)"
|
|
35
|
+
],
|
|
36
|
+
"fail_criteria": [
|
|
37
|
+
"Concludes the code is fine as-is because the form/UI that calls it already checks permissions -- mentioning that this is not sufficient is not itself a failure"
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
"calibration": {
|
|
42
|
+
"known_right": "This is missing an auth check and should not merge as-is. A 'use server' action is a directly reachable server endpoint -- anyone who can trigger a POST to it (not just users going through your UI) can call updateOrderStatus(orderId, status) with an arbitrary orderId. Before the db.order.update call, it needs to: get the current session/user, reject if there's no authenticated session, and confirm that user is actually authorized to modify the specific order identified by orderId (e.g. owns it, or has an admin role) -- not just that they're logged in. Right now nothing stops any authenticated (or even unauthenticated, depending on how it's wired) caller from updating any order's status.",
|
|
43
|
+
"known_wrong": "This looks fine -- the button that calls this action only shows up on the order owner's own order page, so by the time this action runs we already know it's the right user.",
|
|
44
|
+
"vague": "This action should probably have some kind of permission check before it modifies data.",
|
|
45
|
+
"subtle_wrong": "This needs an auth check, good catch -- I'd add a check that `session` exists and reject if not. That covers making sure the caller is logged in before the update runs, which is the main gap here."
|
|
46
|
+
},
|
|
47
|
+
"anti_patterns": []
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"id": "flag-page-level-use-client",
|
|
51
|
+
"prompt": "This Next.js diff adds 'use client' at the top of app/dashboard/page.tsx because one small stat card in the middle of the page needs a hover tooltip with local state. Everything else on the page is static server-rendered content. What should the review say?",
|
|
52
|
+
"strictness": "high",
|
|
53
|
+
"expected_behavior": [
|
|
54
|
+
{ "grader": "regex", "value": "'use client'" },
|
|
55
|
+
{
|
|
56
|
+
"grader": "judge",
|
|
57
|
+
"rubric": "A correct review flags that 'use client' on the whole page is too broad, and recommends extracting the stat card (or just its tooltip) into its own small client component, keeping the rest of the page as a Server Component.",
|
|
58
|
+
"pass_criteria": [
|
|
59
|
+
"States that putting 'use client' on the whole page.tsx is too broad given only one small element needs it",
|
|
60
|
+
"Recommends extracting the stat card/tooltip into its own separate component file marked 'use client', while the page itself stays a Server Component"
|
|
61
|
+
],
|
|
62
|
+
"fail_criteria": [
|
|
63
|
+
"Approves the page-level 'use client' as fine because it's simpler than splitting into two files -- mentioning that tradeoff only to reject it is not a failure"
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
],
|
|
67
|
+
"calibration": {
|
|
68
|
+
"known_right": "This is too broad -- putting 'use client' on the whole page.tsx ships the entire dashboard's JS to the browser and turns every other static element on the page into client-rendered content, purely for one stat card's hover tooltip. Instead, extract that stat card (or just the tooltip part of it) into its own component file, e.g. StatCardWithTooltip.tsx, and put 'use client' at the top of that file only. Keep app/dashboard/page.tsx itself with no directive so it stays a Server Component and the rest of the dashboard keeps being server-rendered. Pass whatever data the card needs down to it as props from the page.",
|
|
69
|
+
"known_wrong": "It's fine -- 'use client' on the whole page is simpler than splitting components apart, and the performance difference for one dashboard page probably doesn't matter much.",
|
|
70
|
+
"vague": "It might be better to scope the client directive more narrowly instead of putting it on the whole page.",
|
|
71
|
+
"subtle_wrong": "Agreed this should be narrowed -- I'd move 'use client' from page.tsx down to just wrapping the dashboard's main content section as its own client component, so it's not the very top-level page file anymore. That's still a lot of the page's content inside one client component, but it's an improvement over the top-level directive."
|
|
72
|
+
},
|
|
73
|
+
"anti_patterns": []
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nextjs-nuxt-implementation
|
|
3
|
+
description: "Use when implementing a new page, route, or data-fetching feature in a Next.js App Router or Nuxt 3+ project: choosing Server vs. Client Components ('use client' placement), a Nuxt composable/page fetching data with useFetch/useAsyncData, a Server Action ('use server') or Nuxt server/api route, or a route's rendering mode (static/ISR/revalidate vs. Nuxt's ssr/routeRules). Not for plain React component logic with no meta-framework routing/data concern (use react-implementation), plain Vue SFC logic outside Nuxt's routing/server layer (use vue-implementation), or fixing an existing build/type error (use nextjs-nuxt-build-fix)."
|
|
4
|
+
triggers:
|
|
5
|
+
- "add a new page to this Next.js app router project"
|
|
6
|
+
- "should this be a server component or a client component"
|
|
7
|
+
- "fetch this data with useFetch in my Nuxt page"
|
|
8
|
+
- "write a Next.js server action for this form"
|
|
9
|
+
- "add a Nuxt server API route under server/api"
|
|
10
|
+
- "set up ISR revalidation for this Next.js route"
|
|
11
|
+
- "this Nuxt composable needs to hit the API on page load"
|
|
12
|
+
- "configure routeRules for this Nuxt route to prerender it"
|
|
13
|
+
metadata:
|
|
14
|
+
origin: authored
|
|
15
|
+
category: implement
|
|
16
|
+
version: "1.0.0"
|
|
17
|
+
compatible_harnesses: "claude,codex,cursor,zed,opencode"
|
|
18
|
+
license: "MIT"
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
# Next.js / Nuxt implementation
|
|
22
|
+
|
|
23
|
+
Implement a new page, route, or data-fetching feature in a Next.js App
|
|
24
|
+
Router or Nuxt 3+ project. Covers both frameworks: use the Next.js
|
|
25
|
+
sections for `app/`-directory work, the Nuxt sections for `pages/`/
|
|
26
|
+
`server/` work, and the shared sections for the routing/rendering/
|
|
27
|
+
data-fetching decisions that apply to either. See `rules/patterns.mdc` for
|
|
28
|
+
the underlying idiom and `rules/coding-style.mdc` for naming/typing.
|
|
29
|
+
|
|
30
|
+
## Workflow
|
|
31
|
+
|
|
32
|
+
### Step 1: Identify the framework and the project's own conventions
|
|
33
|
+
|
|
34
|
+
- Detect which meta-framework the project uses (`next.config.*` +
|
|
35
|
+
`app/` directory, vs. `nuxt.config.ts` + `pages/`/`server/`) — a
|
|
36
|
+
monorepo may have both in different packages, so confirm which package
|
|
37
|
+
you are actually working in before writing anything.
|
|
38
|
+
- Read the nearest existing page/route/composable of the same kind
|
|
39
|
+
(another `page.tsx`, another `server/api/*.ts`, another composable) for
|
|
40
|
+
the project's own patterns: how it fetches data, where it puts types,
|
|
41
|
+
what error-handling shape it uses. Match that shape rather than
|
|
42
|
+
inventing a new one.
|
|
43
|
+
|
|
44
|
+
### Step 2: Choose the Server/Client boundary (Next.js) or composable context (Nuxt)
|
|
45
|
+
|
|
46
|
+
- Next.js: default to a Server Component (no directive). Add
|
|
47
|
+
`'use client'` only on the smallest leaf that needs `useState`,
|
|
48
|
+
`useEffect`, a browser API, or an event handler — never on a shared
|
|
49
|
+
layout or an ancestor of that leaf.
|
|
50
|
+
- Nuxt: call composables (`useFetch`, `useRoute`, a custom `useX`)
|
|
51
|
+
synchronously at the top level of `<script setup>`, a plugin, or
|
|
52
|
+
middleware — not inside an async callback or after an `await`, since
|
|
53
|
+
Nuxt resolves their injection context synchronously at call time.
|
|
54
|
+
|
|
55
|
+
### Step 3: Fetch data where the framework already renders
|
|
56
|
+
|
|
57
|
+
- Next.js: fetch inside the Server Component with `fetch()` (deduplicated
|
|
58
|
+
and cached per render pass) or the project's server-side data layer;
|
|
59
|
+
pass the result down as serializable props to any Client Component that
|
|
60
|
+
needs it. Do not re-fetch the same data client-side after mount unless
|
|
61
|
+
the requirement is genuinely post-interaction (a search box, a
|
|
62
|
+
paginated "load more").
|
|
63
|
+
- Nuxt: use `useFetch`/`useAsyncData` with an explicit, stable key for any
|
|
64
|
+
data the page needs during SSR — they dedupe across server and client
|
|
65
|
+
and hydrate without a second request. Reserve a plain `$fetch` call
|
|
66
|
+
inside `onMounted`/an event handler for genuinely client-only,
|
|
67
|
+
post-interaction calls.
|
|
68
|
+
|
|
69
|
+
### Step 4: Choose the rendering mode deliberately
|
|
70
|
+
|
|
71
|
+
- Next.js: leave the route static (default) unless it reads
|
|
72
|
+
`cookies()`/`headers()`/`searchParams` or needs fresh data every
|
|
73
|
+
request. When data can tolerate staleness, set
|
|
74
|
+
`export const revalidate = <seconds>` for ISR instead of forcing full
|
|
75
|
+
dynamic rendering.
|
|
76
|
+
- Nuxt: set per-route behavior in `nuxt.config.ts`'s `routeRules` (`isr`,
|
|
77
|
+
`prerender`, or `ssr: false` for one route) rather than flipping the
|
|
78
|
+
app-wide `ssr` flag for a need that is local to one route.
|
|
79
|
+
|
|
80
|
+
### Step 5: Write the mutation path (Server Action / server route)
|
|
81
|
+
|
|
82
|
+
- Next.js: a Server Action (`'use server'`, file-level or inline) is
|
|
83
|
+
called from a form's `action` prop or a Client Component's handler.
|
|
84
|
+
After the mutation, call `revalidatePath()`/`revalidateTag()` for the
|
|
85
|
+
routes that show the changed data, so the same request cycle serves
|
|
86
|
+
fresh data — don't hand-roll a client refetch when revalidate already
|
|
87
|
+
covers it.
|
|
88
|
+
- Nuxt: a `server/api/*.ts` handler reads the request via `defineEventHandler`,
|
|
89
|
+
validates/authorizes inside the handler itself (it is a public HTTP
|
|
90
|
+
endpoint), and returns the result; call it from the page via
|
|
91
|
+
`useFetch`/`$fetch`, not by importing server-only code into a component.
|
|
92
|
+
- Both: re-validate every input inside the action/handler server-side —
|
|
93
|
+
client-side form validation is UX, not a trust boundary. See
|
|
94
|
+
`rules/security.mdc`.
|
|
95
|
+
|
|
96
|
+
### Step 6: Verify
|
|
97
|
+
|
|
98
|
+
Run the commands in Verification below before reporting the feature done.
|
|
99
|
+
|
|
100
|
+
## Rules
|
|
101
|
+
|
|
102
|
+
- Follow `rules/patterns.mdc` for the Server/Client boundary, rendering
|
|
103
|
+
mode, and data-fetching idiom.
|
|
104
|
+
- Follow `rules/security.mdc` for env-var scoping and Server
|
|
105
|
+
Action/server-route auth.
|
|
106
|
+
- Follow `rules/coding-style.mdc` for naming, typing, and Nuxt
|
|
107
|
+
auto-import conventions.
|
|
108
|
+
- ALWAYS keep server-only code (secrets, DB clients, `'use server'`
|
|
109
|
+
files, `server/api/**`) out of any import chain a Client Component or
|
|
110
|
+
browser bundle can reach.
|
|
111
|
+
- NEVER widen a `'use client'` boundary or flip a route/page to `ssr:
|
|
112
|
+
false` just to make an implementation easier — fix the actual
|
|
113
|
+
server/client data flow instead.
|
|
114
|
+
|
|
115
|
+
## Red Flags
|
|
116
|
+
|
|
117
|
+
| Rationalization | Why it is wrong |
|
|
118
|
+
|---|---|
|
|
119
|
+
| "I'll just mark the whole page 'use client', then I don't have to think about the boundary" | Ships the entire subtree's JS to the browser and loses server rendering for content that never needed it; isolate the directive to the interactive leaf |
|
|
120
|
+
| "I'll call useFetch inside this onMounted callback so it definitely has the DOM ready" | Nuxt composables need synchronous setup-time invocation to resolve their context; moving it into an async callback breaks that, not fixes it |
|
|
121
|
+
| "I'll just refetch client-side after the Server Action instead of figuring out revalidatePath" | Server Actions + revalidate already deliver fresh data in one round trip; a manual refetch is an unnecessary second request and a source of stale-UI bugs |
|
|
122
|
+
| "The client already validates the form, so the server action doesn't need to check again" | A Server Action/server route is a directly reachable HTTP endpoint; client validation is UX only |
|
|
123
|
+
|
|
124
|
+
## Verification
|
|
125
|
+
|
|
126
|
+
Do not report the feature done until:
|
|
127
|
+
|
|
128
|
+
- The project's type-check passes (`tsc --noEmit`, or `nuxi typecheck`).
|
|
129
|
+
- `next build` or `nuxi build` completes without new warnings about a
|
|
130
|
+
missing `'use client'` boundary, an invalid composable call, or an
|
|
131
|
+
unresolved auto-import.
|
|
132
|
+
- Every new Server Action/server route validates and authorizes its own
|
|
133
|
+
input, independent of client-side checks.
|
|
134
|
+
- No secret was exposed by an incorrect `NEXT_PUBLIC_`/`runtimeConfig`
|
|
135
|
+
placement (`rules/security.mdc`).
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"triggers": {
|
|
3
|
+
"positive": [
|
|
4
|
+
"I need to add a new order-history page to my Next.js app router project, should the data fetching happen in a server component?",
|
|
5
|
+
"Write a Next.js server action that creates a post and revalidates the posts list",
|
|
6
|
+
"This Nuxt page needs to fetch orders on load, should I use useFetch or a plain fetch call?",
|
|
7
|
+
"I need an endpoint under server/api in my Nuxt app that hands back the logged-in user's profile data, can you build that?",
|
|
8
|
+
"Set up ISR on this Next.js product page so it revalidates every hour",
|
|
9
|
+
"Configure routeRules in nuxt.config.ts so this one Nuxt route renders as SPA-only",
|
|
10
|
+
"My Nuxt composable needs to call the API as soon as the page loads, how should I wire that up",
|
|
11
|
+
"I'm adding a new component to my Next.js app and I'm not sure which rendering boundary it belongs in, how do I decide?"
|
|
12
|
+
],
|
|
13
|
+
"negative": [
|
|
14
|
+
"Write a test for this Next.js page's server component",
|
|
15
|
+
"Review this Next.js server action diff for missing auth checks",
|
|
16
|
+
"Fix this Next.js build error about a Server Component importing useState",
|
|
17
|
+
"Migrate this Next.js app from the pages router to the app router",
|
|
18
|
+
"Add a plain React hook that debounces an input value, no routing involved",
|
|
19
|
+
"Fix this Go compile error about an unused import"
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
"scenarios": [
|
|
23
|
+
{
|
|
24
|
+
"id": "server-client-boundary-placement",
|
|
25
|
+
"prompt": "I have a Next.js app router page that shows an order summary with a 'mark as paid' button. Where should the client-side interactivity live, and how should the data get there?",
|
|
26
|
+
"strictness": "high",
|
|
27
|
+
"expected_behavior": [
|
|
28
|
+
{ "grader": "regex", "value": "'use client'" },
|
|
29
|
+
{
|
|
30
|
+
"grader": "judge",
|
|
31
|
+
"rubric": "A correct answer keeps the page/order-summary rendering as a Server Component that fetches the order data, and isolates 'use client' to only the small interactive button/form component that needs the click handler, passing the needed data down as a prop rather than marking the whole page a Client Component.",
|
|
32
|
+
"pass_criteria": [
|
|
33
|
+
"States that the page itself (or the bulk of the order summary) stays a Server Component with no 'use client' directive",
|
|
34
|
+
"Names 'use client' as belonging only on the small button/action component, not the page or a shared layout",
|
|
35
|
+
"Describes passing the necessary order data down as a prop from the server-rendered parent to that client leaf, rather than having the leaf re-fetch it itself"
|
|
36
|
+
],
|
|
37
|
+
"fail_criteria": [
|
|
38
|
+
"Recommends adding 'use client' to the whole page or a layout component to make the button work -- naming 'use client' only to warn against placing it there is not a failure",
|
|
39
|
+
"Has the client button component independently re-fetch the order data client-side instead of receiving it as a prop from the server-rendered parent"
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
"calibration": {
|
|
44
|
+
"known_right": "Keep the order-summary page itself a Server Component -- fetch the order data there with no 'use client' directive. Extract just the 'mark as paid' button into its own small component, e.g. MarkAsPaidButton.tsx, and put 'use client' at the top of that file only, since it's the piece that actually needs an onClick handler and client state (a pending/loading flag while the mutation runs). Pass the orderId (and any other data the button needs) down to it as a prop from the server-rendered page -- don't have the button component fetch the order itself. The button's onClick calls a Server Action ('use server') that performs the mutation and calls revalidatePath so the page reflects the new status afterward.",
|
|
45
|
+
"known_wrong": "Easiest way: put 'use client' at the top of the page.tsx file itself, then you can use useState for the button's pending state and onClick directly in the same component without worrying about the server/client split. It's one extra client-side render but it's much simpler than splitting into two files.",
|
|
46
|
+
"vague": "Keep most of it server-rendered and only make the interactive part a client component, that keeps things fast.",
|
|
47
|
+
"subtle_wrong": "I'd extract the button into its own component and mark it 'use client', which is the right idea -- but to keep things simple I'd have that client component call a route handler with fetch() on mount to pull the order data itself, rather than threading it down as a prop from the server page, since that way the button component is fully self-contained and doesn't need any props from its parent."
|
|
48
|
+
},
|
|
49
|
+
"anti_patterns": []
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"id": "nuxt-composable-setup-context",
|
|
53
|
+
"prompt": "In my Nuxt page, I want to fetch the current user's orders as soon as the page mounts, using a composable I wrote. Where should I call it?",
|
|
54
|
+
"strictness": "high",
|
|
55
|
+
"expected_behavior": [
|
|
56
|
+
{ "grader": "regex", "value": "setup" },
|
|
57
|
+
{
|
|
58
|
+
"grader": "judge",
|
|
59
|
+
"rubric": "A correct answer calls the composable synchronously at the top level of <script setup> (not inside an async callback, onMounted-with-await, or after an await), explaining that Nuxt resolves a composable's injection context synchronously at call time.",
|
|
60
|
+
"pass_criteria": [
|
|
61
|
+
"States the composable must be called at the top level of <script setup>, synchronously, not inside an async callback or after an await",
|
|
62
|
+
"Explains why: Nuxt resolves the composable's context (route/app/plugin injection) synchronously at call time, so a deferred call loses access to it"
|
|
63
|
+
],
|
|
64
|
+
"fail_criteria": [
|
|
65
|
+
"Recommends calling the composable inside an onMounted callback with an await before it, or inside a setTimeout, as the primary recommended placement -- mentioning that placement only to warn against it is not a failure"
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
],
|
|
69
|
+
"calibration": {
|
|
70
|
+
"known_right": "Call the composable directly at the top level of your <script setup> block, synchronously -- for example `const { data: orders } = await useOrdersComposable()` right in setup, not wrapped in onMounted or any async callback. Nuxt resolves a composable's access to its injection context (the current route, the app instance, plugin-provided services) synchronously when the composable function is first invoked; if you defer the call into an async callback or fire it after an earlier await inside setup, that context is no longer reliably available and the composable can throw or silently lose access to what it needs. If the composable itself does async work internally (like useFetch does), that's fine -- the call site just needs to be the synchronous top level of setup.",
|
|
71
|
+
"known_wrong": "Just call it inside onMounted(async () => { await useOrdersComposable() }) so you're sure the DOM is ready before fetching -- that's the safest place to put any data-fetching logic in a Vue/Nuxt component.",
|
|
72
|
+
"vague": "Nuxt composables need to be called at the right point in the component lifecycle for the context to work properly.",
|
|
73
|
+
"subtle_wrong": "Call it at the top of setup like usual, but if you need to fetch on mount specifically (not immediately on component creation), wrap just that call in onMounted so it only runs client-side after mount: onMounted(() => { useOrdersComposable() }) -- this still feels like it's 'in setup' since onMounted is registered during setup, so the composable should still have access to its context."
|
|
74
|
+
},
|
|
75
|
+
"anti_patterns": []
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nextjs-nuxt-testing
|
|
3
|
+
description: "Use when writing or fixing tests for a Next.js App Router page/Server Action or a Nuxt page/composable/server route: testing a Server Component's rendered output, a Client Component's interactivity with React Testing Library, a Nuxt composable that calls useFetch/useAsyncData with @nuxt/test-utils' mountSuspended, or a server/api handler's auth and validation paths. Not for plain React/Vue component unit tests with no meta-framework routing, SSR, or server-route concern (use react-testing/vue-testing), and not for implementing the feature under test (use nextjs-nuxt-implementation)."
|
|
4
|
+
triggers:
|
|
5
|
+
- "write a test for this Next.js server action"
|
|
6
|
+
- "test this Nuxt composable that uses useAsyncData"
|
|
7
|
+
- "mountSuspended test for this Nuxt component with auto-imports"
|
|
8
|
+
- "how do I test a Next.js server component's output"
|
|
9
|
+
- "write a test for this server/api route in Nuxt"
|
|
10
|
+
- "test this route handler's auth check in Next.js"
|
|
11
|
+
- "flaky test around Date.now in this Next.js page"
|
|
12
|
+
metadata:
|
|
13
|
+
origin: authored
|
|
14
|
+
category: test
|
|
15
|
+
version: "1.0.0"
|
|
16
|
+
compatible_harnesses: "claude,codex,cursor,zed,opencode"
|
|
17
|
+
license: "MIT"
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
# Next.js / Nuxt testing
|
|
21
|
+
|
|
22
|
+
Write or fix a test for a Next.js App Router page/Server Action or a Nuxt
|
|
23
|
+
page/composable/server route. Covers both frameworks' own test-runner
|
|
24
|
+
setup and mocking conventions. See `rules/testing.mdc` for the layout and
|
|
25
|
+
mocking rules this skill applies.
|
|
26
|
+
|
|
27
|
+
## Workflow
|
|
28
|
+
|
|
29
|
+
### Step 1: Identify what is actually under test
|
|
30
|
+
|
|
31
|
+
- A Server Component's rendered output (no interactivity) vs. a Client
|
|
32
|
+
Component's behavior (event handlers, state) vs. a Server
|
|
33
|
+
Action/route handler's logic (validation, auth, the mutation itself) —
|
|
34
|
+
each needs a different test shape; do not force all three through one
|
|
35
|
+
`render()` call.
|
|
36
|
+
- A Nuxt page/composable that calls `useFetch`/`useAsyncData`/another
|
|
37
|
+
Nuxt-context composable, vs. a plain presentational `.vue` component
|
|
38
|
+
with no Nuxt runtime dependency — the first needs Nuxt's test context,
|
|
39
|
+
the second does not.
|
|
40
|
+
|
|
41
|
+
### Step 2: Pick the right harness
|
|
42
|
+
|
|
43
|
+
- Next.js: React Testing Library (with Jest or Vitest, whichever the
|
|
44
|
+
project already runs) for a Client Component's interactivity. For a
|
|
45
|
+
Server Component, render its resolved output or exercise it through an
|
|
46
|
+
integration/e2e test — `render()` alone does not run the App Router's
|
|
47
|
+
server data-fetching lifecycle.
|
|
48
|
+
- Nuxt: `@nuxt/test-utils`'s `mountSuspended` (or `renderSuspended`) for
|
|
49
|
+
any component that calls a Nuxt composable needing runtime context;
|
|
50
|
+
plain Vue Test Utils `mount()` only for a component with zero Nuxt
|
|
51
|
+
context dependency.
|
|
52
|
+
- A Server Action or `server/api/**` handler: call the exported function
|
|
53
|
+
directly with a constructed request/args, not through a rendered
|
|
54
|
+
component — the goal is testing the handler's own logic in isolation.
|
|
55
|
+
|
|
56
|
+
### Step 3: Mock at the network boundary, not the data-fetching hook
|
|
57
|
+
|
|
58
|
+
- Mock HTTP with MSW (or the project's existing network mock layer) for
|
|
59
|
+
any test that exercises `fetch`/`useFetch`/`$fetch` — this exercises the
|
|
60
|
+
real request/response handling code instead of a hand-stubbed hook
|
|
61
|
+
return value.
|
|
62
|
+
- For a Server Action/server route test, mock the downstream dependency
|
|
63
|
+
(DB client, external API client) one layer down, and call the real
|
|
64
|
+
handler on top of it, so the test actually proves the handler's
|
|
65
|
+
auth/validation logic runs.
|
|
66
|
+
|
|
67
|
+
### Step 4: Make it deterministic
|
|
68
|
+
|
|
69
|
+
- Freeze/inject time (`vi.setSystemTime`, a clock parameter) for anything
|
|
70
|
+
rendering `Date.now()` or locale-dependent output.
|
|
71
|
+
- Build route params/`searchParams`/`useRoute()` mocks with a realistic
|
|
72
|
+
shape (a fixture/factory), not a hand-built partial object that
|
|
73
|
+
happens to satisfy today's assertions.
|
|
74
|
+
|
|
75
|
+
### Step 5: Verify
|
|
76
|
+
|
|
77
|
+
Run the project's test command and confirm the new test fails without the
|
|
78
|
+
implementation and passes with it (or, for a bug-fix test, fails on the
|
|
79
|
+
buggy code first).
|
|
80
|
+
|
|
81
|
+
## Rules
|
|
82
|
+
|
|
83
|
+
- Follow `rules/testing.mdc` for layout, runner choice, and network
|
|
84
|
+
mocking.
|
|
85
|
+
- Test the Server Action/server route's own auth and validation failure
|
|
86
|
+
paths, not just its success path.
|
|
87
|
+
- NEVER mock the framework's data-fetching hook itself
|
|
88
|
+
(`useFetch`/`useAsyncData`) to return canned data when the point of the
|
|
89
|
+
test is the component's request/response handling — mock the network
|
|
90
|
+
layer beneath it instead.
|
|
91
|
+
- NEVER skip or delete a flaky SSR/hydration-dependent test instead of
|
|
92
|
+
fixing its nondeterminism (freeze time, mock the varying input).
|
|
93
|
+
|
|
94
|
+
## Red Flags
|
|
95
|
+
|
|
96
|
+
| Rationalization | Why it is wrong |
|
|
97
|
+
|---|---|
|
|
98
|
+
| "I'll just mock useAsyncData to return the data directly, simpler than mocking the network" | Tests the mock, not the component's real fetch/error/loading handling; mock at the network boundary instead |
|
|
99
|
+
| "This composable test keeps breaking on Nuxt context, I'll just plain-mount it with Vue Test Utils" | A composable that needs Nuxt's injection context needs `mountSuspended`/Nuxt's test context, not a mount that has none |
|
|
100
|
+
| "This test is flaky because of the date, I'll just skip it" | Skipping hides the same nondeterminism that causes a real hydration mismatch in production; freeze the clock instead |
|
|
101
|
+
| "The server action already has client-side validation tested, no need to test the handler separately" | The handler is a directly reachable endpoint; its own validation/auth path needs its own test regardless of client-side coverage |
|
|
102
|
+
|
|
103
|
+
## Verification
|
|
104
|
+
|
|
105
|
+
Do not report the test done until:
|
|
106
|
+
|
|
107
|
+
- The project's test command passes, and the new test fails against the
|
|
108
|
+
pre-fix/pre-implementation code (proving it actually exercises the
|
|
109
|
+
behavior).
|
|
110
|
+
- No data-fetching hook (`useFetch`/`useAsyncData`/`fetch`) was mocked
|
|
111
|
+
directly when a network-boundary mock (MSW or equivalent) would have
|
|
112
|
+
exercised the real code path.
|
|
113
|
+
- A tested Server Action/server route has at least one assertion covering
|
|
114
|
+
an auth or validation failure, not only the happy path.
|
|
115
|
+
- No `Date.now()`/`Math.random()`/locale-dependent value reaches an
|
|
116
|
+
assertion unfrozen or unmocked.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"triggers": {
|
|
3
|
+
"positive": [
|
|
4
|
+
"This server action creates a new order when called, what's the right way to get test coverage around it?",
|
|
5
|
+
"I've got a composable in my Nuxt app that internally kicks off useAsyncData, what's the best approach for testing it?",
|
|
6
|
+
"This Nuxt component pulls values from useRoute, and I need to render it in a test using @nuxt/test-utils, what's the setup for that?",
|
|
7
|
+
"How do I write a test for what this Next.js App Router server component actually renders?",
|
|
8
|
+
"Write a test for this server/api/orders.ts handler in Nuxt covering the unauthenticated case",
|
|
9
|
+
"There's an authorization check inside this route handler that has zero coverage right now, can you help me write a test for it?",
|
|
10
|
+
"One of my page tests only fails intermittently, and I traced it back to the component calling Date.now() during render, how do I make this deterministic?"
|
|
11
|
+
],
|
|
12
|
+
"negative": [
|
|
13
|
+
"Add a new page to this Next.js app router project",
|
|
14
|
+
"Review this Nuxt server/api/orders.ts route for security issues",
|
|
15
|
+
"Fix this Nuxt build error about a composable being called outside setup",
|
|
16
|
+
"Migrate this Nuxt 2 asyncData call to useAsyncData",
|
|
17
|
+
"Write a Jest test for a plain React hook with no routing or SSR concern",
|
|
18
|
+
"Fix this generic ESLint no-floating-promises failure in a plain Node.js script"
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
"scenarios": [
|
|
22
|
+
{
|
|
23
|
+
"id": "mock-network-not-hook",
|
|
24
|
+
"prompt": "I'm writing a test for a Nuxt page that calls useFetch to load a list of orders. Should I mock useFetch directly to return canned data, or something else?",
|
|
25
|
+
"strictness": "high",
|
|
26
|
+
"expected_behavior": [
|
|
27
|
+
{ "grader": "regex", "value": "MSW|network" },
|
|
28
|
+
{
|
|
29
|
+
"grader": "judge",
|
|
30
|
+
"rubric": "A correct answer recommends mocking at the network/HTTP boundary (e.g. with MSW) rather than mocking useFetch itself, because mocking the hook only tests the mock and skips the component's real request/response handling.",
|
|
31
|
+
"pass_criteria": [
|
|
32
|
+
"Recommends mocking the HTTP/network layer (e.g. MSW, or the project's equivalent network mock) rather than mocking useFetch's return value directly",
|
|
33
|
+
"Explains that mocking useFetch itself tests the mock rather than the component's real request/response/loading/error handling"
|
|
34
|
+
],
|
|
35
|
+
"fail_criteria": [
|
|
36
|
+
"Recommends mocking useFetch's return value (e.g. vi.mock of the composable) as the primary approach -- mentioning that approach only to warn against it is not a failure"
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
"calibration": {
|
|
41
|
+
"known_right": "Mock at the network boundary, not the composable. Use MSW (or whatever network-mocking layer the project already has set up) to intercept the actual HTTP request useFetch makes under the hood, and return the canned orders response from there. That way the test still exercises the real useFetch call, including how the component handles the loading state, the data once it resolves, and an error response if you want to test that path too. If you instead mock useFetch itself to just return { data: ordersFixture } directly, you're only proving your mock works -- the test would still pass even if the component's actual request logic, URL, or error handling were broken.",
|
|
42
|
+
"known_wrong": "Just mock useFetch directly with vi.mock so it returns { data: ref(ordersFixture), pending: ref(false) } -- that's the simplest way to control exactly what the component sees without dealing with setting up a network mocking library.",
|
|
43
|
+
"vague": "Try to test the real data flow rather than just stubbing things out, that gives you more confidence.",
|
|
44
|
+
"subtle_wrong": "Set up MSW to intercept the request, that's the right instinct -- but register the MSW handler to intercept the internal Nuxt $fetch wrapper's resolved promise rather than the actual HTTP endpoint URL the orders API is served from, so you don't have to figure out the real URL pattern; it still counts as 'network-level' since it's below the composable itself."
|
|
45
|
+
},
|
|
46
|
+
"anti_patterns": []
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"id": "server-action-handler-test-coverage",
|
|
50
|
+
"prompt": "I wrote a Next.js server action that creates an order and only has a happy-path test so far. What else should the test cover?",
|
|
51
|
+
"strictness": "high",
|
|
52
|
+
"expected_behavior": [
|
|
53
|
+
{
|
|
54
|
+
"grader": "judge",
|
|
55
|
+
"rubric": "A correct answer states that the server action's own auth/authorization check and input validation failure paths need their own test coverage, calling the handler directly (or through its real invocation path) rather than only asserting the successful-creation case, since the client's own form validation does not substitute for server-side test coverage.",
|
|
56
|
+
"pass_criteria": [
|
|
57
|
+
"Names testing the auth/authorization failure path (e.g. an unauthenticated or unauthorized caller) as missing coverage that should be added",
|
|
58
|
+
"Names testing at least one input-validation failure path (bad/missing input) as missing coverage that should be added",
|
|
59
|
+
"States or implies these should call the real server action handler (with a mocked downstream dependency like the database) rather than only testing the UI form that calls it"
|
|
60
|
+
],
|
|
61
|
+
"fail_criteria": [
|
|
62
|
+
"States that the happy-path test alone is sufficient because the form already validates input client-side, or that server-side auth/validation testing can be skipped since the client already checks it"
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
],
|
|
66
|
+
"calibration": {
|
|
67
|
+
"known_right": "The happy path alone isn't enough -- add tests that call the server action directly (with the database client mocked) covering: an unauthenticated caller (no session) should be rejected before any write happens; an authenticated caller without permission on this resource should also be rejected; and at least one bad-input case (missing or malformed order fields) should fail validation rather than reaching the database call. Each of these exercises the action's own auth and validation logic in isolation, since the server action is a directly reachable endpoint regardless of whether the calling form already validates -- client-side validation doesn't give you any server-side test coverage.",
|
|
68
|
+
"known_wrong": "The happy-path test is probably enough since the form itself already validates required fields before submitting and the user has to be logged in to see the form at all, so those cases shouldn't really be reachable in practice.",
|
|
69
|
+
"vague": "You should probably add a few more test cases for edge cases and errors, not just the success case.",
|
|
70
|
+
"subtle_wrong": "Good idea to add more coverage -- I'd add a test where the form is submitted with an empty title field and assert the submit button stays disabled, plus a test that the login redirect happens if you're not authenticated. That covers the important failure modes on the client side that lead into this action."
|
|
71
|
+
},
|
|
72
|
+
"anti_patterns": []
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
}
|