
documentation-lookup
Fetches up-to-date library and framework documentation via Context7 MCP so answers about APIs, setup, and code examples reflect current versions instead of training data.
Lift+0ppscreen tier · directional
90
Trustsecurity · quality · license · upkeep
Scan Saferisk 0/100
LicenseMITserved via MCP
Skill-matched tasks (generated, public + held-out) · glm-5.3-flash@cf
+0pp95% CI [0, 0]unverified · screen tier
trigger rate 100% · 12 trials
A/B outputs — median trial per arm
Same task, same model: without the skill (left) vs with it (right).
documentation-lookup--m1
baseline · 1.00
Here's a complete setup for Next.js 15 (which uses the stable `middleware.ts` at the project root or inside `src/`):
## middleware.ts
```ts
import { NextResponse, type NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
// Read your session cookie / token — adjust the name to your auth setup
const token = request.cookies.get('session')?.value;
if (!token) {
// Redirect to login, preserving where the user was headed
const loginUrl = new URL('/login', request.url);
loginUrl.searchParams.set('from', request.nextUrl.pathname);
return NextResponse.redirect(loginUrl);
}
return NextResponse.next();
}
export const config = {
matcher: [
/*
* Match everything except:
* - /api routes
* - Next.js internals (_next/static, _next/image, etc.)
* - Static files with extensions (favicon.ico, images, etc.)
*/
'/((?!api|_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js|woff|woff2)$).*)',
],
};
```
## How the matcher works
The negative lookahead `(?!...)` excludes paths from middleware entirely:
- `api` — excludes `/api/*`
- `_next/static|_next/image` — Next.js internals
- `.*\\.(?:...)$` — any path ending in a static file extension
Everything else (including `/dashboard` and `/account`) runs through the middleware.
## Alternative: simpler matcher + explicit checks
If you prefer a narrower matcher and check paths in code:
```ts
export const config = {
matcher: ['/dashboard/:path*', '/account/:path*'],
};
export function middleware(request: NextRequest) {
const token = request.cookies.get('session')?.value;
if (!token) {
const loginUrl = new URL('/login', request.url);
loginUrl.searchParams.set('from', request.nextUrl.pathname);
return NextResponse.redirect(loginUrl);
}
return NextResponse.next();
}
```
This version is often preferable: the middleware only runs on the routes that need it, so there's zero overhead on public pages, and you don't need the regex exclusions at all.
## Notes for Next.js 15
- Place the file at the project root, or in `src/` if you use a `src` directory.
- In your `/login` page, you can read the `from` search param to redirect users back after login.
- If your auth uses a header-based check or a library like NextAuth/Auth.js, replace the cookie read accordingly (e.g., `getToken` from `next-auth/jwt` or verifying a JWT with `jose`).
- Middleware runs on the Edge runtime by default, so avoid Node-only APIs there.with skill · 1.00
The Context7 MCP tools aren't available in this environment, so I'll answer directly from Next.js 15 knowledge.
## `middleware.ts` (project root or `src/`)
```ts
import { NextRequest, NextResponse } from 'next/server'
export function middleware(request: NextRequest) {
const isAuthenticated = Boolean(request.cookies.get('session')?.value) // your auth check
if (!isAuthenticated) {
const loginUrl = new URL('/login', request.url)
// optional: send user back after login
loginUrl.searchParams.set('next', request.nextUrl.pathname)
return NextResponse.redirect(loginUrl)
}
return NextResponse.next()
}
export const config = {
matcher: [
// Protect dashboard and account, but exclude /api, static files, and Next internals
'/dashboard/:path*',
'/account/:path*',
],
}
```
## Why this matcher style
Since you only want to protect two routes, the simplest and safest matcher is to **explicitly list the protected paths** rather than match everything and exclude. But if you prefer the "match all, exclude" pattern (common when protecting many routes), use:
```ts
export const config = {
matcher: [
/*
* Match all paths except:
* - /api routes
* - Next.js internals (_next)
* - static files (files with an extension, e.g. favicon.ico, images)
* - metadata files (robots.txt, sitemap.xml, etc.)
*/
'/((?!api|_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js|woff2?)$|robots.txt|sitemap.xml).*)',
],
}
```
With this second approach, your middleware logic must then check the pathname:
```ts
const { pathname } = request.nextUrl
const isProtected = pathname.startsWith('/dashboard') || pathname.startsWith('/account')
if (isProtected && !isAuthenticated) { ... redirect ... }
return NextResponse.next()
```
## Notes for Next.js 15
- Middleware runs on the Edge runtime — don't use Node-only APIs or heavy libraries (e.g. `bcrypt`, full `pg` clients). Verify JWTs with a Web Crypto-compatible library like `jose`, or just check for a session cookie set by your auth provider.
- The `matcher` supports negative lookaheads but not arbitrary regex — keep it to the patterns above.
- If you're on Next.js 15.2+, note that `middleware.ts` still works the same; the newer `proxy.ts` convention is experimental and not required.
- Always `return NextResponse.next()` for allowed requests so headers/cookies can still be forwarded if needed.documentation-lookup--m2
baseline · 0.85
```ts
const post = await prisma.post.findUnique({
where: { id: postId },
include: {
author: true,
comments: {
orderBy: { createdAt: 'asc' }, // or 'desc' for newest first
},
},
});
```
To return only approved comments, use `where` on the relation:
```ts
const post = await prisma.post.findUnique({
where: { id: postId },
include: {
author: true,
comments: {
where: { approved: true },
orderBy: { createdAt: 'asc' },
},
},
});
```
Note: with `include` + `where`, the post itself is still returned even if it has no approved comments — you just get an empty `comments` array. If you'd rather exclude posts with no approved comments entirely, use `prisma.post.findFirst({ where: { id: postId, comments: { some: { approved: true } } }, include: ... })`.with skill · 0.85
```ts
const post = await prisma.post.findUnique({
where: { id: 1 },
include: {
author: true,
comments: {
orderBy: { createdAt: 'asc' }, // or 'desc' for newest first
},
},
});
```
To fetch only approved comments, add a `where` filter inside the `include`:
```ts
const post = await prisma.post.findUnique({
where: { id: 1 },
include: {
author: true,
comments: {
where: { approved: true },
orderBy: { createdAt: 'asc' },
},
},
});
```
Notes:
- `findUnique` works because `id` is the `@id` field; if you were querying by a non-unique field you'd use `findFirst` instead.
- The `where` inside `include.comments` filters only the related comments returned — the post itself is always returned even if it has no approved comments.
- You can combine `orderBy` and `where` freely, and add `take`/`skip` for pagination of comments if needed.documentation-lookup--m3
baseline · 1.00
In React 19, `use` is a new API that can read a context value — and unlike hooks, it can be called conditionally or inside loops, because it's not a hook (no `use` prefix rules apply to it in the same way... actually it does start with "use", but it's exempt from hook call rules).
## Usage
```jsx
import { createContext, use } from 'react';
const ThemeContext = createContext('light');
function ThemedButton({ showTheme }) {
// ✅ Allowed: `use` can be called conditionally
if (showTheme) {
const theme = use(ThemeContext);
return <button className={theme}>Themed</button>;
}
return <button>Plain</button>;
}
```
You can also call it inside an event handler's render-time helper or nested functions, as long as it's still during rendering:
```jsx
function Toolbar() {
function getTheme() {
// ✅ Fine: called during render
return use(ThemeContext);
}
const theme = getTheme();
return <div className={theme}>Toolbar</div>;
}
```
## Rules for `use`
1. **Call it during render only** — like hooks, it can't be called from plain event handlers (e.g. inside `onClick` callbacks after render), `setTimeout`, etc.
2. **Conditional/loop calls are allowed** — this is the key difference from `useContext`.
3. **Pass a Context or a Promise** — `use(ThemeContext)` reads context; `use(somePromise)` unwraps a promise (with Suspense integration).
4. **Don't call it inside a component you `memo`-wrap with a condition that skips rendering** — normal render rules apply.
5. **For context specifically**, it behaves like `useContext`: re-renders when the provider value changes.
## Important caveat about event handlers
If you want to read context inside an `onClick` handler, you still read it during render and close over it:
```jsx
function SaveButton() {
const theme = use(ThemeContext); // read during render
function handleClick() {
console.log(theme); // ✅ use the closed-over value
// use(ThemeContext); ❌ NOT allowed here — not during render
}
return <button onClick={handleClick} className={theme}>Save</button>;
}
```
So: use `use` when you need conditional/lazy context reads during render; for event handlers, read once during render and reference the value in the handler.with skill · 1.00
The Context7 MCP tools aren't available in this environment, so I'll answer directly from React 19 knowledge.
## `use(Context)` in React 19
`use` is a new API that lets you read context (or a promise) — and unlike hooks, it **can be called conditionally or inside loops**, as long as it's still called during render (not inside event handlers).
```jsx
import { use } from 'react';
function ThemedButton({ showTheme }) {
if (showTheme) {
// ✅ allowed: use() can be called conditionally
const theme = use(ThemeContext);
return <button className={theme}>Click</button>;
}
return <button>Click</button>;
}
```
You can also call it inside a loop or after an early return — the normal "rules of hooks" don't apply to `use`.
## The rules
1. **Must be called during render** — not inside event handlers, callbacks, or effects. So you *cannot* do `onClick={() => use(ThemeContext)}`. If you need the value in an event handler, read it during render and capture it in a variable/closure:
```jsx
function SaveButton() {
const theme = use(ThemeContext); // read during render
const handleClick = () => {
console.log('current theme:', theme); // use it in the handler
};
return <button onClick={handleClick}>Save</button>;
}
```
2. **Only call it from a component or a custom hook** (a function starting with `use`), like other hooks.
3. **Pass a Context object or a Promise.** With a promise, React suspends until it resolves (works with `<Suspense>` and works best with a caching mechanism like React Query or RSC — don't create a fresh promise on every render).
4. `use` does **not** create a subscription boundary the way `useContext` does in some edge cases — it behaves like `useContext` for context: it reads the nearest provider above the calling component.
## Key takeaway
`use` gives you *conditional* context reads during render, but event handlers still need the value read at render time. If you truly need to read context lazily inside a handler, capture it in a closure as shown above — that's the idiomatic pattern.documentation-lookup--m4
baseline · 0.82
In Next.js 15, `cookies()` is now **async** — it returns a Promise, so you must `await` it. That's why your old code throws.
## Route Handler — reading a cookie
```ts
// app/api/example/route.ts
import { cookies } from 'next/headers';
import { NextResponse } from 'next/server';
export async function GET() {
const cookieStore = await cookies();
const session = cookieStore.get('session');
if (!session) {
return NextResponse.json({ error: 'No session' }, { status: 401 });
}
return NextResponse.json({ sessionId: session.value });
}
```
## Server Action — setting a cookie after login
```ts
// app/actions/auth.ts
'use server';
import { cookies } from 'next/headers';
export async function login(formData: FormData) {
const email = formData.get('email');
const password = formData.get('password');
// ...validate credentials, get session token...
const cookieStore = await cookies();
cookieStore.set('session', sessionToken, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
path: '/',
maxAge: 60 * 60 * 24 * 7, // 1 week
});
return { success: true };
}
```
Key points for the 15 upgrade:
- `await cookies()` everywhere — this applies to route handlers, Server Components, and Server Actions alike.
- `cookieStore.get('session')` returns `undefined` if missing, or an object like `{ name: 'session', value: '...' }`.
- Setting cookies is only allowed in Server Actions and Route Handlers (mutating contexts) — not in Server Components during render.
- Same change applies to `headers()` and the `params`/`searchParams` props in pages, which are also now async.with skill · 0.82
The Context7 MCP tools aren't available in this session, so I'll answer directly — but this is well-established Next.js 15 behavior.
In Next.js 15, `cookies()` (and `headers()`, `params`, `searchParams`) became **async**, so you must `await` it. Calling `.get()` on the promise itself is what throws.
## Route Handler — reading a cookie
```ts
// app/api/session/route.ts
import { cookies } from 'next/headers';
export async function GET() {
const cookieStore = await cookies();
const session = cookieStore.get('session');
if (!session) {
return Response.json({ error: 'No session' }, { status: 401 });
}
return Response.json({ sessionId: session.value });
}
```
## Server Action — setting a cookie after login
```ts
// app/actions/auth.ts
'use server';
import { cookies } from 'next/headers';
export async function login(formData: FormData) {
const email = String(formData.get('email'));
const password = String(formData.get('password'));
// ...validate credentials, create session token...
const cookieStore = await cookies();
cookieStore.set('session', token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
path: '/',
maxAge: 60 * 60 * 24 * 7, // 1 week
});
return { success: true };
}
```
Key points:
- **`await cookies()`** everywhere in Next.js 15 — route handlers, Server Actions, and Server Components.
- `cookies().set()` is only allowed in a **Server Action or Route Handler** (places where a response is being written), not in Server Components during render.
- If you also need to delete: `cookieStore.delete('session')` — same async rule applies.
- For TypeScript, `cookieStore.get()` returns `ResponseCookie | undefined`, so handle the missing case as shown.Limitations
- Agent noise: single-model results vary run to run; the confidence interval reflects task-level variance.
- Screen tier (1 trial/arm) is a directional gate, not a verified claim.
- Results are for the SkillzBench Reference Agent on glm-5.3-flash@cf and do not necessarily transfer to other agents or models.
- Task coverage: Skill-matched tasks (generated, public + held-out) only; a skill can shine elsewhere.