Sign inGet started

documentation-lookup

by affaan-m/ECC · Coding & Development

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
baseline 100% → skill 100% pass
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.