Usage
Wrap your config in next.config.ts with withQRCode:
import type { NextConfig } from "next";
import { withQRCode } from "next-plugin-qrcode";
const nextConfig: NextConfig = {
// your Next.js config
};
export default withQRCode(nextConfig);Start your dev server:
npm run devYour terminal shows a QR code encoding your dev server's address on the local network. Scan it with your phone to open the app. Both devices must be on the same network.
Try it live in the demo, or tune the URL with options.
Why a config wrapper and not a bundler plugin
Turbopack is written in Rust, and Next.js is explicit about what that costs: plugins have to be described by name so Rust can load them, because JavaScript functions can't be passed to Rust. That is why remark and rehype plugins are configured as strings under Turbopack:
const withMDX = createMDX({
options: {
remarkPlugins: ["remark-gfm"],
rehypePlugins: [["rehype-katex", { strict: true }]],
},
});A webpack plugin is the opposite of that. It is a JavaScript class with an
apply() method, handed to the bundler as a live object. There is no way to pass one to
Turbopack, so a QR code printed from inside the bundler would work under
next dev --webpack and silently do nothing under Turbopack.
withQRCode sidesteps the boundary instead of trying to cross it. Your
next.config.ts is evaluated by Node before either bundler starts, so the
plugin prints the QR code there and returns your config untouched. Nothing is
registered with webpack, nothing has to be serialized for Turbopack, and the
same code path runs for both.
For the full story on the Rust boundary, see Using plugins with Turbopack in the Next.js documentation.