quello
Guides

Next.js

Three lines, one per file Next makes you own.

Next has no plugin API, so quello cannot arrive the way it does everywhere else. What it can do is put the same code behind three one-line imports — one for each file Next insists the project owns.

Install

Terminal
pnpm add -D @quello/next

Configure

next.config.ts
import { withQuello } from '@quello/next/config'

export default withQuello({
  // your config, untouched
})

That is the whole setup. On the next next dev, withQuello writes your agent file, adds .quello/ to .gitignore, creates the route handler for you, and prints where everything went:

Terminal
  quello    press alt+q to pick
  picks     .quello/picks.json
  endpoint  /api/quello/picks
  agent     AGENTS.md
  created   app/api/quello/[...quello]/route.ts

Render it

One tag, once, in the root layout:

app/layout.tsx
import { Quello } from '@quello/next'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Quello />
      </body>
    </html>
  )
}

<Quello /> is a Server Component that renders a script tag, not a client component that imports the picker. Nothing from @quello/core enters your client bundle — not even as a chunk nobody loads — and in a production build the component renders null.

Props override next.config for a one-off:

<Quello shortcut="ctrl+shift+p" htmlMode="full" />

The route handler

withQuello writes this for you. It is here so you know what it is:

app/api/quello/[...quello]/route.ts
import { quelloRoute } from '@quello/next/route'

export const dynamic = 'force-dynamic'

export const { GET, HEAD, POST, PUT, DELETE, OPTIONS } = quelloRoute()

It serves two things below /api/quello: picks, which reads and writes .quello/picks.json, and client.js, the runtime itself. Together they are what the Vite plugin's dev-server middleware does elsewhere.

Why it cannot be one line, like Nuxt

Nuxt builds on Vite, so vite-plugin-quello gets the dev server's middleware stack, a virtual module and a dev-only mode for free, and the project writes one import. Next gives a package none of those:

  • it runs its own dev server, so there is no setupMiddlewares to add the picks endpoint to — the only place Next accepts an HTTP handler from you is a route file in your own app/;
  • it renders HTML with its own renderer, so there is no transformIndexHtml and no html-webpack-plugin to add the script tag through;
  • it has no plugin API at all. next.config is the only file Next evaluates on your behalf, and from Next 16 the webpack() escape hatch is gone under Turbopack anyway.

So the shape here — a component and a route — is not a workaround. It is the only shape that survives a bundler change, which is why the package builds on it rather than on a webpack hook.

Options

Every plugin option works, plus two of Next's own. Pass them to withQuello as a second argument, or to <Quello /> as props.

OptionDefault
basePath/api/quelloWhere the route handler is mounted.
scaffoldRoutetrueCreate the route file when it is missing.

enabled behaves slightly differently here than in the plugins: it can only ever turn quello off. Production is off regardless — the endpoint writes to disk, so it must not exist outside next dev.

Pages Router

Same idea, one file:

pages/api/quello/[...quello].ts
import { quelloApiConfig, quelloApiRoute } from '@quello/next/route'

// quello reads the body itself, so Next must not parse it first.
export const config = quelloApiConfig

export default quelloApiRoute()

Then render <Quello /> in pages/_document.tsx, inside <body>.

What a pick will know

The component name and the source file:

{ "framework": { "framework": "react", "component": "OverviewPage", "file": "app/page.tsx" } }

Server Components are included — app/layout.tsx comes back for an element rendered there.

Next's App Router bundles React 19, whatever version your package.json names, and React 19 removed _debugSource in favour of owner stacks: an Error captured where each element was written. quello reads the file out of that stack, but not the line — a stack frame addresses the compiled module, and a browser does not run error.stack through source maps, so page.tsx:22 there is not line 22 of page.tsx. A file the agent can search beats a line number that quietly points at the wrong element. Resolving frames through Next's own /__nextjs_original-stack-frame would fix that, and is on the roadmap.An element written inside a dependency — the <a> that next/link renders — reports the component and no file, which is the honest answer: it is not in your code.
Copyright © 2026