NextJS Pages Application with D1 bindings

I am trying to get NextJS Pages application to use D1 database. I have gone through the entire Pages documentation but haven’t found an end-to-end example on how to get this to work.

For reference, here’s the example code I’m trying to get to work: https://github.com/i2shar/pages-with-functions.
As suggested, I have a functions/ directory with a function that queries D1. This works locally with the command: wrangler pages dev --d1 DB=025b1980-a534-4336-a6d4-4835bd036f28 -- yarn dev
and when I hit the proxied app at http://localhost:8787/query, I get the expected results. However, when I publish this to CF Pages via git integration, the /query URL shows a NextJS 404 page, so the NextJS router is intercepting this route instead of Pages functions. Why this inconsistent behavior when running with wrangler vs running on the actual platform?

Also, can someone point to an end-to-end example with NextJS app working with D1 bindings? I find the documentation around Bindings in general to be lacking.

1 Like

Update: one thing I noticed is that if I run wrangler with a proxy with -- npm run dev vs specifying the output directory .vercel/output/static I get different behaviors w.r.t. whether http://localhost:8788/query invokes the Pages function or not.

For e.g. the following command gives the right output for localhost:8788/query:

wrangler pages dev  --d1 DB=025b1980-a534-4336-a6d4-4835bd036f28 --compatibility-flag=nodejs_compat --compatibility-date=2023-12-18 -- npm run dev

however with this command I get a 404 from NextJS:

wrangler pages dev  --d1 DB=025b1980-a534-4336-a6d4-4835bd036f28 --compatibility-flag=nodejs_compat --compatibility-date=2023-12-18 .vercel/output/static/
1 Like

Update 2: [Solved]: I couldn’t get the functions directory to work for Next.js at all. Instead, I was able to use stitch information from various sources to get Next.js API routes to recognize bindings for D1. I wish the NextJS framework docs for Pages was clearer, so documenting it here for whoever bumps into this:

Follow the steps in the D1 docs to create a new database using wrangler d1 create | execute ... commands in your project. Then as mentioned in the “Use bindings in your Next.js application” section: https://developers.cloudflare.com/pages/framework-guides/deploy-a-nextjs-site/#use-bindings-in-your-nextjs-application, create the env.d.ts file in your project:

declare global {  
    namespace NodeJS {  
        interface ProcessEnv {  
            [key: string]: string | undefined;  
            // The KV Namespace binding type used here comes  
            // from `@cloudflare/workers-types`, in order to            
            // use it like so, make sure that you have installed            
            // the package as a dev dependency and you have added            
            // it to your `tsconfig.json` file under            
            // `compilerOptions.types`.            DB: D1Database;  
        }  
    }  
}  
  
export {};

But it won’t be automatically picked up - this part is missing from CF Pages docs. For it to be picked up by Typescript compiler, you need to add it to your tsconfig.json as documented in Next.js docs here: https://nextjs.org/docs/pages/building-your-application/configuring/typescript#custom-type-declarations:

"include": [  
  "env.d.ts",
  "next-env.d.ts",
  ...
  ...
],

After this your IDE should start recognizing the D1Database types in your Next.js routes:

import type {NextRequest} from 'next/server'  
  
export const runtime = 'edge'  
  
export async function GET(request: NextRequest) {  
    const db = process.env.DB;  
    const stmt = db.prepare('SELECT * FROM MyTable');  
	const {results} = await stmt.all();  
	return Response.json(results);
}

To run it locally using miniflare, you still need to fully build using next build, and then run npm pages:dev which triggers wrangler pages dev. You may create a wrangler.toml file with bindings or you may add the --d1 DB=<your_database_id> flags. For now it seems there’s no way to run both worker code and Next.js hot reloading together, but I noticed a PR that might fix it soon for better dev mode. See https://github.com/cloudflare/next-on-pages/blob/main/internal-packages/next-dev/README.md and https://github.com/cloudflare/next-on-pages/pull/622 .

1 Like