Next.js
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
pnpm add -D @quello/next
Configure
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:
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:
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:
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
setupMiddlewaresto add the picks endpoint to — the only place Next accepts an HTTP handler from you is a route file in your ownapp/; - it renders HTML with its own renderer, so there is no
transformIndexHtmland nohtml-webpack-pluginto add the script tag through; - it has no plugin API at all.
next.configis the only file Next evaluates on your behalf, and from Next 16 thewebpack()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.
| Option | Default | |
|---|---|---|
basePath | /api/quello | Where the route handler is mounted. |
scaffoldRoute | true | Create 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:
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.
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.