├── benchmarking ├── .gitignore ├── package.json └── tsconfig.json ├── examples ├── playground14 │ ├── public │ │ ├── .gitkeep │ │ └── snipp │ │ │ └── snipp.webp │ ├── .dev.vars │ ├── .env.development │ ├── app │ │ ├── page.js │ │ ├── api │ │ │ ├── request │ │ │ │ └── route.ts │ │ │ ├── env │ │ │ │ └── route.ts │ │ │ ├── buildid │ │ │ │ └── route.ts │ │ │ ├── instrumentation │ │ │ │ └── route.ts │ │ │ └── hello │ │ │ │ └── route.ts │ │ └── layout.js │ ├── e2e │ │ ├── playwright.config.ts │ │ ├── playwright.dev.config.ts │ │ └── head.spec.ts │ ├── pages │ │ ├── api │ │ │ └── pages.ts │ │ └── head.tsx │ ├── open-next.config.ts │ ├── middleware.js │ ├── wrangler.jsonc │ ├── worker.ts │ ├── tsconfig.json │ └── .gitignore ├── playground15 │ ├── public │ │ ├── .gitkeep │ │ ├── test.jpg │ │ └── tomine.webp │ ├── .dev.vars │ ├── .env.development │ ├── data.module.css │ ├── data.js │ ├── app │ │ ├── page.js │ │ ├── api │ │ │ ├── request │ │ │ │ └── route.ts │ │ │ ├── signal │ │ │ │ └── revalidate │ │ │ │ │ └── route.ts │ │ │ ├── instrumentation │ │ │ │ └── route.ts │ │ │ ├── buildid │ │ │ │ └── route.ts │ │ │ ├── env │ │ │ │ └── route.ts │ │ │ └── hello │ │ │ │ └── route.ts │ │ ├── image │ │ │ └── page.tsx │ │ ├── layout.js │ │ ├── signal │ │ │ └── page.tsx │ │ ├── other-app │ │ │ └── page.tsx │ │ └── from-app │ │ │ └── page.tsx │ ├── e2e │ │ ├── playwright.config.ts │ │ ├── playwright.dev.config.ts │ │ ├── image.test.ts │ │ ├── cloudflare.spec.ts │ │ └── head.spec.ts │ ├── worker-configuration.d.ts │ ├── middleware.js │ ├── pages │ │ └── head.tsx │ ├── next.config.ts │ ├── open-next.config.ts │ ├── tsconfig.json │ └── .gitignore ├── bugs │ ├── gh-219 │ │ ├── .dev.vars │ │ ├── src │ │ │ └── app │ │ │ │ ├── favicon.ico │ │ │ │ └── globals.css │ │ ├── open-next.config.ts │ │ ├── public │ │ │ ├── vercel.svg │ │ │ ├── window.svg │ │ │ └── file.svg │ │ ├── e2e │ │ │ ├── playwright.config.ts │ │ │ └── base.spec.ts │ │ ├── postcss.config.mjs │ │ ├── next.config.ts │ │ ├── wrangler.jsonc │ │ ├── eslint.config.mjs │ │ ├── tailwind.config.ts │ │ └── tsconfig.json │ ├── gh-223 │ │ ├── .eslintrc.json │ │ ├── app │ │ │ ├── favicon.ico │ │ │ ├── api │ │ │ │ └── image │ │ │ │ │ └── route.ts │ │ │ ├── layout.tsx │ │ │ └── globals.css │ │ ├── open-next.config.ts │ │ ├── e2e │ │ │ ├── playwright.config.ts │ │ │ └── base.spec.ts │ │ ├── postcss.config.mjs │ │ ├── next.config.mjs │ │ ├── wrangler.jsonc │ │ ├── tailwind.config.ts │ │ └── public │ │ │ └── vercel.svg │ └── gh-119 │ │ ├── .eslintrc.json │ │ ├── app │ │ ├── favicon.ico │ │ ├── fonts │ │ │ ├── GeistVF.woff │ │ │ └── GeistMonoVF.woff │ │ └── globals.css │ │ ├── open-next.config.ts │ │ ├── public │ │ ├── vercel.svg │ │ ├── window.svg │ │ └── file.svg │ │ ├── e2e │ │ ├── playwright.config.ts │ │ └── base.spec.ts │ │ ├── postcss.config.mjs │ │ ├── next.config.ts │ │ ├── wrangler.jsonc │ │ ├── tailwind.config.ts │ │ └── tsconfig.json ├── e2e │ ├── app-pages-router │ │ ├── .env │ │ ├── app │ │ │ ├── parallel │ │ │ │ ├── page.tsx │ │ │ │ ├── @a │ │ │ │ │ ├── a-page │ │ │ │ │ │ └── page.tsx │ │ │ │ │ └── page.tsx │ │ │ │ └── @b │ │ │ │ │ ├── b-page │ │ │ │ │ └── page.tsx │ │ │ │ │ └── page.tsx │ │ │ ├── albums │ │ │ │ ├── @modal │ │ │ │ │ ├── default.tsx │ │ │ │ │ └── (.)[album] │ │ │ │ │ │ └── page.tsx │ │ │ │ ├── [album] │ │ │ │ │ ├── page.tsx │ │ │ │ │ └── [song] │ │ │ │ │ │ └── page.tsx │ │ │ │ ├── layout.tsx │ │ │ │ └── page.tsx │ │ │ ├── ssr │ │ │ │ ├── loading.tsx │ │ │ │ ├── layout.tsx │ │ │ │ └── page.tsx │ │ │ ├── redirect-destination │ │ │ │ └── page.tsx │ │ │ ├── api │ │ │ │ ├── client │ │ │ │ │ └── route.ts │ │ │ │ └── host │ │ │ │ │ └── route.ts │ │ │ ├── ssg │ │ │ │ └── page.tsx │ │ │ ├── server-actions │ │ │ │ └── page.tsx │ │ │ ├── isr │ │ │ │ └── page.tsx │ │ │ ├── image-optimization │ │ │ │ └── page.tsx │ │ │ ├── rewrite-destination │ │ │ │ └── page.tsx │ │ │ ├── layout.tsx │ │ │ └── globals.css │ │ ├── README.md │ │ ├── postcss.config.js │ │ ├── public │ │ │ ├── favicon.ico │ │ │ └── static │ │ │ │ ├── frank.webp │ │ │ │ └── corporate_holiday_card.jpg │ │ ├── e2e │ │ │ ├── playwright.config.ts │ │ │ ├── playwright.turbopack.config.ts │ │ │ ├── skip_trailing.test.ts │ │ │ ├── host.test.ts │ │ │ ├── headers.test.ts │ │ │ └── middleware.test.ts │ │ ├── open-next.turbopack.config.ts │ │ ├── pages │ │ │ ├── _app.tsx │ │ │ ├── _document.tsx │ │ │ ├── api │ │ │ │ └── hello.ts │ │ │ ├── pages_ssr │ │ │ │ └── index.tsx │ │ │ └── pages_isr │ │ │ │ └── index.tsx │ │ ├── next.config.ts │ │ ├── open-next.config.ts │ │ ├── tailwind.config.ts │ │ ├── .gitignore │ │ └── wrangler.jsonc │ ├── pages-router │ │ ├── .env.production │ │ ├── README.md │ │ ├── public │ │ │ ├── favicon.ico │ │ │ └── static │ │ │ │ └── frank.webp │ │ ├── e2e │ │ │ ├── playwright.config.ts │ │ │ ├── playwright.turbopack.config.ts │ │ │ ├── middleware.test.ts │ │ │ ├── 404.test.ts │ │ │ ├── trailing.test.ts │ │ │ ├── i18n.test.ts │ │ │ └── header.test.ts │ │ ├── postcss.config.js │ │ ├── open-next.turbopack.config.ts │ │ ├── src │ │ │ ├── pages │ │ │ │ ├── _app.tsx │ │ │ │ ├── api │ │ │ │ │ ├── query.ts │ │ │ │ │ ├── dynamic │ │ │ │ │ │ ├── precedence │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── [slug].ts │ │ │ │ │ │ ├── catch-all-optional │ │ │ │ │ │ │ └── [[...slug]].ts │ │ │ │ │ │ └── catch-all │ │ │ │ │ │ │ └── [...slug].ts │ │ │ │ │ ├── hello.ts │ │ │ │ │ └── revalidate.ts │ │ │ │ ├── fallback-intercepted │ │ │ │ │ ├── static.tsx │ │ │ │ │ ├── ssg.tsx │ │ │ │ │ ├── [...slugs].tsx │ │ │ │ │ └── [slug].tsx │ │ │ │ ├── _document.tsx │ │ │ │ ├── ssg │ │ │ │ │ └── index.tsx │ │ │ │ ├── isr │ │ │ │ │ └── index.tsx │ │ │ │ ├── ssr │ │ │ │ │ └── index.tsx │ │ │ │ └── fallback │ │ │ │ │ └── [slug].tsx │ │ │ └── middleware.ts │ │ ├── open-next.config.ts │ │ ├── wrangler.jsonc │ │ └── .gitignore │ ├── shared │ │ ├── sst-env.d.ts │ │ ├── components │ │ │ ├── Album │ │ │ │ ├── Album.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── Song.tsx │ │ │ └── Filler │ │ │ │ └── index.tsx │ │ └── package.json │ ├── app-router │ │ ├── README.md │ │ ├── app │ │ │ ├── og │ │ │ │ └── page.tsx │ │ │ ├── parallel │ │ │ │ ├── page.tsx │ │ │ │ ├── @a │ │ │ │ │ ├── a-page │ │ │ │ │ │ └── page.tsx │ │ │ │ │ └── page.tsx │ │ │ │ └── @b │ │ │ │ │ ├── b-page │ │ │ │ │ └── page.tsx │ │ │ │ │ └── page.tsx │ │ │ ├── albums │ │ │ │ ├── @modal │ │ │ │ │ ├── default.tsx │ │ │ │ │ └── (.)[album] │ │ │ │ │ │ └── page.tsx │ │ │ │ ├── [album] │ │ │ │ │ ├── page.tsx │ │ │ │ │ └── [song] │ │ │ │ │ │ └── page.tsx │ │ │ │ ├── layout.tsx │ │ │ │ └── page.tsx │ │ │ ├── ssr │ │ │ │ ├── loading.tsx │ │ │ │ ├── layout.tsx │ │ │ │ └── page.tsx │ │ │ ├── revalidate-tag │ │ │ │ ├── nested │ │ │ │ │ └── page.tsx │ │ │ │ ├── page.tsx │ │ │ │ └── layout.tsx │ │ │ ├── redirect-destination │ │ │ │ └── page.tsx │ │ │ ├── rewrite-destination │ │ │ │ └── page.tsx │ │ │ ├── methods │ │ │ │ ├── get │ │ │ │ │ ├── redirect │ │ │ │ │ │ └── route.ts │ │ │ │ │ ├── dynamic-segments │ │ │ │ │ │ └── [slug] │ │ │ │ │ │ │ └── route.ts │ │ │ │ │ ├── revalidate │ │ │ │ │ │ └── route.ts │ │ │ │ │ ├── static │ │ │ │ │ │ └── route.ts │ │ │ │ │ └── query │ │ │ │ │ │ └── route.ts │ │ │ │ └── post │ │ │ │ │ ├── formdata │ │ │ │ │ └── route.ts │ │ │ │ │ └── cookies │ │ │ │ │ └── route.ts │ │ │ ├── api │ │ │ │ ├── client │ │ │ │ │ └── route.ts │ │ │ │ ├── host │ │ │ │ │ └── route.ts │ │ │ │ ├── revalidate-path │ │ │ │ │ └── route.ts │ │ │ │ ├── revalidate-tag │ │ │ │ │ └── route.ts │ │ │ │ ├── auth │ │ │ │ │ └── [...better-auth] │ │ │ │ │ │ └── route.ts │ │ │ │ └── after │ │ │ │ │ ├── ssg │ │ │ │ │ └── route.ts │ │ │ │ │ └── revalidate │ │ │ │ │ └── route.ts │ │ │ ├── server-actions │ │ │ │ └── page.tsx │ │ │ ├── cookies │ │ │ │ └── page.tsx │ │ │ ├── isr │ │ │ │ └── page.tsx │ │ │ ├── headers │ │ │ │ └── page.tsx │ │ │ ├── config-redirect │ │ │ │ ├── dest │ │ │ │ │ └── page.tsx │ │ │ │ └── page.tsx │ │ │ ├── image-optimization │ │ │ │ └── page.tsx │ │ │ ├── layout.tsx │ │ │ ├── globals.css │ │ │ └── revalidate-path │ │ │ │ └── page.tsx │ │ ├── postcss.config.js │ │ ├── public │ │ │ ├── favicon.ico │ │ │ └── static │ │ │ │ ├── frank.webp │ │ │ │ └── corporate_holiday_card.jpg │ │ ├── e2e │ │ │ ├── playwright.config.ts │ │ │ ├── playwright.turbopack.config.ts │ │ │ ├── host.test.ts │ │ │ ├── isr.revalidate.test.ts │ │ │ └── dynamic.catch-all.hypen.test.ts │ │ ├── open-next.turbopack.config.ts │ │ ├── tailwind.config.ts │ │ └── .gitignore │ ├── experimental │ │ ├── src │ │ │ ├── app │ │ │ │ ├── favicon.ico │ │ │ │ ├── api │ │ │ │ │ └── revalidate │ │ │ │ │ │ └── route.ts │ │ │ │ ├── use-cache │ │ │ │ │ ├── layout.tsx │ │ │ │ │ ├── isr │ │ │ │ │ │ └── page.tsx │ │ │ │ │ └── fetch │ │ │ │ │ │ └── page.tsx │ │ │ │ ├── page.tsx │ │ │ │ └── ppr │ │ │ │ │ └── page.tsx │ │ │ └── components │ │ │ │ ├── static.tsx │ │ │ │ └── dynamic.tsx │ │ ├── README.md │ │ ├── e2e │ │ │ └── playwright.config.ts │ │ ├── next.config.ts │ │ └── tsconfig.json │ └── utils.ts ├── middleware │ ├── .env │ ├── app │ │ ├── about │ │ │ └── page.tsx │ │ ├── about2 │ │ │ └── page.tsx │ │ ├── another │ │ │ └── page.tsx │ │ ├── rewrite │ │ │ └── page.tsx │ │ ├── clerk │ │ │ └── route.ts │ │ ├── redirected │ │ │ └── page.tsx │ │ ├── layout.tsx │ │ ├── page.tsx │ │ └── middleware │ │ │ └── page.tsx │ ├── public │ │ └── favicon.ico │ ├── open-next.config.ts │ ├── e2e │ │ ├── playwright.config.ts │ │ ├── playwright.dev.config.ts │ │ └── cloudflare-context.spec.ts │ ├── next.config.mjs │ ├── wrangler.jsonc │ ├── .gitignore │ └── tsconfig.json ├── ssg-app │ ├── .dev.vars │ ├── app │ │ ├── favicon.ico │ │ ├── globals.css │ │ ├── page.module.css │ │ ├── page.tsx │ │ └── layout.tsx │ ├── worker-configuration.d.ts │ ├── e2e │ │ └── playwright.config.ts │ ├── open-next.config.ts │ ├── next.config.ts │ ├── wrangler.jsonc │ └── tsconfig.json ├── next-partial-prerendering │ ├── .prettierrc │ ├── postcss.config.js │ ├── types │ │ └── review.d.ts │ ├── app │ │ ├── favicon.ico │ │ ├── twitter-image.png │ │ ├── opengraph-image.png │ │ └── not-found.tsx │ ├── e2e │ │ └── playwright.config.ts │ ├── public │ │ ├── nextjs-icon-light-background.png │ │ ├── patrick-OIFgeLnjwrM-unsplash.jpg │ │ ├── eniko-kis-KsLPTsYaqIQ-unsplash.jpg │ │ ├── prince-akachi-LWkFHEGpleE-unsplash.jpg │ │ ├── yoann-siloine-_T4w3JDm6ug-unsplash.jpg │ │ ├── guillaume-coupy-6HuoHgK7FN8-unsplash.jpg │ │ └── alexander-andrews-brAkTCdnhW8-unsplash.jpg │ ├── components │ │ ├── product-best-seller.tsx │ │ ├── cart-count.tsx │ │ ├── product-low-stock-warning.tsx │ │ ├── ping.tsx │ │ ├── product-rating.tsx │ │ ├── product-currency-symbol.tsx │ │ ├── product-used-price.tsx │ │ ├── product-estimated-arrival.tsx │ │ ├── product-split-payments.tsx │ │ └── product-review-card.tsx │ ├── next.config.js │ ├── open-next.config.ts │ ├── wrangler.jsonc │ ├── lib │ │ └── delay.ts │ └── .gitignore ├── common │ ├── package.json │ └── tsconfig.json ├── create-next-app │ ├── .eslintrc.json │ ├── src │ │ └── app │ │ │ ├── favicon.ico │ │ │ ├── fonts │ │ │ ├── GeistVF.woff │ │ │ └── GeistMonoVF.woff │ │ │ └── globals.css │ ├── open-next.config.ts │ ├── e2e │ │ ├── playwright.config.ts │ │ └── base.spec.ts │ ├── postcss.config.mjs │ ├── next.config.mjs │ ├── wrangler.jsonc │ ├── tailwind.config.ts │ ├── public │ │ └── vercel.svg │ ├── tsconfig.json │ └── .gitignore ├── vercel-blog-starter │ ├── src │ │ ├── app │ │ │ ├── globals.css │ │ │ └── _components │ │ │ │ ├── section-separator.tsx │ │ │ │ ├── container.tsx │ │ │ │ ├── date-formatter.tsx │ │ │ │ ├── markdown-styles.module.css │ │ │ │ ├── header.tsx │ │ │ │ ├── post-body.tsx │ │ │ │ ├── post-title.tsx │ │ │ │ ├── avatar.tsx │ │ │ │ └── intro.tsx │ │ ├── interfaces │ │ │ ├── author.ts │ │ │ └── post.ts │ │ └── lib │ │ │ ├── markdownToHtml.ts │ │ │ └── constants.ts │ ├── postcss.config.js │ ├── public │ │ ├── favicon │ │ │ ├── favicon.ico │ │ │ ├── favicon-16x16.png │ │ │ ├── favicon-32x32.png │ │ │ ├── mstile-150x150.png │ │ │ ├── apple-touch-icon.png │ │ │ ├── android-chrome-192x192.png │ │ │ ├── android-chrome-512x512.png │ │ │ ├── browserconfig.xml │ │ │ └── site.webmanifest │ │ └── assets │ │ │ └── blog │ │ │ ├── authors │ │ │ ├── jj.jpeg │ │ │ ├── joe.jpeg │ │ │ └── tim.jpeg │ │ │ ├── preview │ │ │ └── cover.jpg │ │ │ ├── hello-world │ │ │ └── cover.jpg │ │ │ └── dynamic-routing │ │ │ └── cover.jpg │ ├── next.config.mjs │ ├── open-next.config.ts │ ├── wrangler.jsonc │ ├── .gitignore │ └── tsconfig.json ├── prisma │ ├── src │ │ ├── app │ │ │ ├── favicon.ico │ │ │ └── page.tsx │ │ └── lib │ │ │ └── db.ts │ ├── open-next.config.ts │ ├── e2e │ │ ├── playwright.config.ts │ │ └── playwright.dev.config.ts │ ├── prisma.config.ts │ ├── schema.prisma │ ├── populate.sql │ ├── next.config.ts │ ├── wrangler.jsonc │ └── tsconfig.json └── overrides │ ├── d1-tag-next │ ├── app │ │ ├── favicon.ico │ │ ├── globals.css │ │ ├── action.ts │ │ ├── page.module.css │ │ └── components │ │ │ └── revalidationButtons.tsx │ ├── e2e │ │ └── playwright.config.ts │ ├── next.config.ts │ ├── open-next.config.ts │ └── tsconfig.json │ ├── kv-tag-next │ ├── app │ │ ├── favicon.ico │ │ ├── globals.css │ │ ├── action.ts │ │ ├── page.module.css │ │ └── components │ │ │ └── revalidationButtons.tsx │ ├── e2e │ │ └── playwright.config.ts │ ├── next.config.ts │ ├── open-next.config.ts │ ├── wrangler.e2e.jsonc │ └── tsconfig.json │ ├── memory-queue │ ├── app │ │ ├── favicon.ico │ │ ├── globals.css │ │ ├── page.module.css │ │ ├── page.tsx │ │ └── layout.tsx │ ├── e2e │ │ └── playwright.config.ts │ ├── next.config.ts │ ├── open-next.config.ts │ ├── wrangler.jsonc │ └── tsconfig.json │ ├── r2-incremental-cache │ ├── app │ │ ├── favicon.ico │ │ ├── globals.css │ │ ├── page.module.css │ │ ├── page.tsx │ │ └── layout.tsx │ ├── e2e │ │ └── playwright.config.ts │ └── next.config.ts │ └── static-assets-incremental-cache │ ├── app │ ├── favicon.ico │ ├── globals.css │ ├── action.ts │ ├── page.module.css │ └── components │ │ └── revalidationButtons.tsx │ ├── e2e │ └── playwright.config.ts │ ├── open-next.config.ts │ ├── next.config.ts │ └── wrangler.jsonc ├── packages └── cloudflare │ ├── .gitignore │ ├── src │ ├── cli │ │ ├── templates │ │ │ └── shims │ │ │ │ ├── empty.ts │ │ │ │ ├── fetch.ts │ │ │ │ ├── env.ts │ │ │ │ └── throw.ts │ │ ├── build │ │ │ └── utils │ │ │ │ ├── normalize-path.ts │ │ │ │ ├── index.ts │ │ │ │ ├── version.ts │ │ │ │ └── test-patch.ts │ │ ├── utils │ │ │ └── ask-confirmation.ts │ │ └── project-options.ts │ ├── api │ │ └── index.ts │ └── utils │ │ └── get-package-templates-dir-path.ts │ ├── env.d.ts │ ├── templates │ └── open-next.config.ts │ └── tsconfig.json ├── .gitignore ├── .vscode └── settings.json ├── .editorconfig ├── create-cloudflare └── next │ ├── .dev.vars │ ├── .vscode │ └── settings.json │ ├── postcss.config.mjs │ ├── public │ ├── _headers │ ├── window.svg │ └── file.svg │ ├── next.config.ts │ ├── open-next.config.ts │ ├── eslint.config.mjs │ ├── src │ └── app │ │ └── globals.css │ └── tsconfig.json ├── .prettierignore ├── .github ├── ISSUE_TEMPLATE │ └── config.yml └── workflows │ └── checks.yml ├── .prettierrc └── .changeset ├── config.json └── README.md /benchmarking/.gitignore: -------------------------------------------------------------------------------- 1 | results/ 2 | -------------------------------------------------------------------------------- /examples/playground14/public/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/playground15/public/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/cloudflare/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | -------------------------------------------------------------------------------- /examples/bugs/gh-219/.dev.vars: -------------------------------------------------------------------------------- 1 | NEXTJS_ENV=development -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/.env: -------------------------------------------------------------------------------- 1 | SOME_ENV_VAR=foo -------------------------------------------------------------------------------- /examples/playground14/.dev.vars: -------------------------------------------------------------------------------- 1 | NEXTJS_ENV=development -------------------------------------------------------------------------------- /examples/playground15/.dev.vars: -------------------------------------------------------------------------------- 1 | NEXTJS_ENV=development -------------------------------------------------------------------------------- /examples/e2e/pages-router/.env.production: -------------------------------------------------------------------------------- 1 | SOME_PROD_VAR=bar -------------------------------------------------------------------------------- /examples/middleware/.env: -------------------------------------------------------------------------------- 1 | CLERK_ENCRYPTION_KEY="key" 2 | -------------------------------------------------------------------------------- /examples/playground15/.env.development: -------------------------------------------------------------------------------- 1 | TEST_ENV_VAR=TEST_VALUE -------------------------------------------------------------------------------- /examples/ssg-app/.dev.vars: -------------------------------------------------------------------------------- 1 | MY_SECRET = "psst... this is a secret!" 2 | -------------------------------------------------------------------------------- /examples/playground15/data.module.css: -------------------------------------------------------------------------------- 1 | .wrap { 2 | display: flex; 3 | } 4 | -------------------------------------------------------------------------------- /packages/cloudflare/src/cli/templates/shims/empty.ts: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /packages/cloudflare/src/cli/templates/shims/fetch.ts: -------------------------------------------------------------------------------- 1 | export default fetch; 2 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } 4 | -------------------------------------------------------------------------------- /examples/bugs/gh-223/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /examples/playground14/.env.development: -------------------------------------------------------------------------------- 1 | TEST_ENV_VAR=TEST_VALUE 2 | PROCESS_ENV_VAR=.ENV_FILE -------------------------------------------------------------------------------- /packages/cloudflare/src/cli/templates/shims/env.ts: -------------------------------------------------------------------------------- 1 | export function loadEnvConfig() {} 2 | -------------------------------------------------------------------------------- /examples/e2e/shared/sst-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | 4 | output 5 | .open-next 6 | .wrangler 7 | .turbo 8 | dist -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true, 3 | "cSpell.words": ["nextjs"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/cloudflare/src/cli/templates/shims/throw.ts: -------------------------------------------------------------------------------- 1 | throw "OpenNext shim"; 2 | export default {}; 3 | -------------------------------------------------------------------------------- /examples/bugs/gh-119/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["next/core-web-vitals", "next/typescript"] 3 | } 4 | -------------------------------------------------------------------------------- /examples/common/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "common", 3 | "private": true, 4 | "type": "module" 5 | } 6 | -------------------------------------------------------------------------------- /examples/e2e/app-router/README.md: -------------------------------------------------------------------------------- 1 | # App Router 2 | 3 | This project uses the App Router exclusively... 4 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/og/page.tsx: -------------------------------------------------------------------------------- 1 | export default function Page() { 2 | return
; 3 | } 4 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/parallel/page.tsx: -------------------------------------------------------------------------------- 1 | export default function Page() { 2 | return null; 3 | } 4 | -------------------------------------------------------------------------------- /examples/create-next-app/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["next/core-web-vitals", "next/typescript"] 3 | } 4 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/app/parallel/page.tsx: -------------------------------------------------------------------------------- 1 | export default function Page() { 2 | return null; 3 | } 4 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/README.md: -------------------------------------------------------------------------------- 1 | # Pages Router 2 | 3 | This project uses the Pages Router exclusively. 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = tab 6 | end_of_line = lf 7 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/albums/@modal/default.tsx: -------------------------------------------------------------------------------- 1 | export default function Default() { 2 | return null; 3 | } 4 | -------------------------------------------------------------------------------- /examples/middleware/app/about/page.tsx: -------------------------------------------------------------------------------- 1 | export default function AboutPage() { 2 | return

About

; 3 | } 4 | -------------------------------------------------------------------------------- /examples/middleware/app/about2/page.tsx: -------------------------------------------------------------------------------- 1 | export default function About2Page() { 2 | return

About 2

; 3 | } 4 | -------------------------------------------------------------------------------- /create-cloudflare/next/.dev.vars: -------------------------------------------------------------------------------- 1 | # Load .env.development* files when running `wrangler dev` 2 | NEXTJS_ENV=development 3 | -------------------------------------------------------------------------------- /create-cloudflare/next/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "wrangler.json": "jsonc" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/README.md: -------------------------------------------------------------------------------- 1 | # App Pages Router 2 | 3 | This project uses both the App and Pages router. 4 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/app/albums/@modal/default.tsx: -------------------------------------------------------------------------------- 1 | export default function Default() { 2 | return null; 3 | } 4 | -------------------------------------------------------------------------------- /examples/middleware/app/another/page.tsx: -------------------------------------------------------------------------------- 1 | export default function AnotherPage() { 2 | return

Another

; 3 | } 4 | -------------------------------------------------------------------------------- /examples/middleware/app/rewrite/page.tsx: -------------------------------------------------------------------------------- 1 | export default function RewritePage() { 2 | return

Rewrite

; 3 | } 4 | -------------------------------------------------------------------------------- /examples/vercel-blog-starter/src/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/ssr/loading.tsx: -------------------------------------------------------------------------------- 1 | export default function Loading() { 2 | return
Loading...
; 3 | } 4 | -------------------------------------------------------------------------------- /examples/vercel-blog-starter/src/interfaces/author.ts: -------------------------------------------------------------------------------- 1 | export type Author = { 2 | name: string; 3 | picture: string; 4 | }; 5 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/app/ssr/loading.tsx: -------------------------------------------------------------------------------- 1 | export default function Loading() { 2 | return
Loading...
; 3 | } 4 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/albums/[album]/page.tsx: -------------------------------------------------------------------------------- 1 | export default function ArtistPage() { 2 | return
Artist
; 3 | } 4 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/parallel/@a/a-page/page.tsx: -------------------------------------------------------------------------------- 1 | export default function APage() { 2 | return
A Page
; 3 | } 4 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/parallel/@b/b-page/page.tsx: -------------------------------------------------------------------------------- 1 | export default function BPage() { 2 | return
B Page
; 3 | } 4 | -------------------------------------------------------------------------------- /examples/ssg-app/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/ssg-app/app/favicon.ico -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .next 2 | .wrangler 3 | pnpm-lock.yaml 4 | .vscode/setting.json 5 | test-fixtures 6 | test-snapshots 7 | playwright-report -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/app/albums/[album]/page.tsx: -------------------------------------------------------------------------------- 1 | export default function ArtistPage() { 2 | return
Artist
; 3 | } 4 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/app/parallel/@a/a-page/page.tsx: -------------------------------------------------------------------------------- 1 | export default function APage() { 2 | return
A Page
; 3 | } 4 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/app/parallel/@b/b-page/page.tsx: -------------------------------------------------------------------------------- 1 | export default function BPage() { 2 | return
B Page
; 3 | } 4 | -------------------------------------------------------------------------------- /examples/middleware/app/clerk/route.ts: -------------------------------------------------------------------------------- 1 | export async function POST(request: Request) { 2 | return new Response(`Hello clerk`); 3 | } 4 | -------------------------------------------------------------------------------- /examples/prisma/src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/prisma/src/app/favicon.ico -------------------------------------------------------------------------------- /create-cloudflare/next/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | const config = { 2 | plugins: ["@tailwindcss/postcss"], 3 | }; 4 | 5 | export default config; 6 | -------------------------------------------------------------------------------- /examples/bugs/gh-119/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/bugs/gh-119/app/favicon.ico -------------------------------------------------------------------------------- /examples/bugs/gh-223/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/bugs/gh-223/app/favicon.ico -------------------------------------------------------------------------------- /examples/e2e/app-router/app/revalidate-tag/nested/page.tsx: -------------------------------------------------------------------------------- 1 | export default async function Nested() { 2 | return
Nested
; 3 | } 4 | -------------------------------------------------------------------------------- /examples/e2e/app-router/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /examples/middleware/app/redirected/page.tsx: -------------------------------------------------------------------------------- 1 | export default function RedirectedPage() { 2 | return

Redirected from /about

; 3 | } 4 | -------------------------------------------------------------------------------- /examples/playground15/public/test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/playground15/public/test.jpg -------------------------------------------------------------------------------- /examples/bugs/gh-219/src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/bugs/gh-219/src/app/favicon.ico -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /examples/middleware/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/middleware/public/favicon.ico -------------------------------------------------------------------------------- /examples/playground15/data.js: -------------------------------------------------------------------------------- 1 | import styles from "./data.module.css"; 2 | 3 | export const data = { 4 | now: Date.now(), 5 | styles, 6 | }; 7 | -------------------------------------------------------------------------------- /examples/playground15/public/tomine.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/playground15/public/tomine.webp -------------------------------------------------------------------------------- /examples/vercel-blog-starter/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /examples/e2e/app-router/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/e2e/app-router/public/favicon.ico -------------------------------------------------------------------------------- /examples/next-partial-prerendering/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /examples/ssg-app/worker-configuration.d.ts: -------------------------------------------------------------------------------- 1 | interface CloudflareEnv { 2 | APP_VERSION: "1.2.345"; 3 | MY_SECRET: string; 4 | ASSETS: Fetcher; 5 | } 6 | -------------------------------------------------------------------------------- /examples/bugs/gh-119/app/fonts/GeistVF.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/bugs/gh-119/app/fonts/GeistVF.woff -------------------------------------------------------------------------------- /examples/create-next-app/src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/create-next-app/src/app/favicon.ico -------------------------------------------------------------------------------- /examples/e2e/experimental/src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/e2e/experimental/src/app/favicon.ico -------------------------------------------------------------------------------- /examples/e2e/pages-router/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/e2e/pages-router/public/favicon.ico -------------------------------------------------------------------------------- /examples/middleware/open-next.config.ts: -------------------------------------------------------------------------------- 1 | import { defineCloudflareConfig } from "@opennextjs/cloudflare"; 2 | 3 | export default defineCloudflareConfig(); 4 | -------------------------------------------------------------------------------- /examples/playground14/public/snipp/snipp.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/playground14/public/snipp/snipp.webp -------------------------------------------------------------------------------- /examples/prisma/open-next.config.ts: -------------------------------------------------------------------------------- 1 | import { defineCloudflareConfig } from "@opennextjs/cloudflare"; 2 | 3 | export default defineCloudflareConfig({}); 4 | -------------------------------------------------------------------------------- /examples/bugs/gh-119/app/fonts/GeistMonoVF.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/bugs/gh-119/app/fonts/GeistMonoVF.woff -------------------------------------------------------------------------------- /examples/bugs/gh-119/open-next.config.ts: -------------------------------------------------------------------------------- 1 | import { defineCloudflareConfig } from "@opennextjs/cloudflare"; 2 | 3 | export default defineCloudflareConfig(); 4 | -------------------------------------------------------------------------------- /examples/bugs/gh-219/open-next.config.ts: -------------------------------------------------------------------------------- 1 | import { defineCloudflareConfig } from "@opennextjs/cloudflare"; 2 | 3 | export default defineCloudflareConfig(); 4 | -------------------------------------------------------------------------------- /examples/bugs/gh-223/open-next.config.ts: -------------------------------------------------------------------------------- 1 | import { defineCloudflareConfig } from "@opennextjs/cloudflare"; 2 | 3 | export default defineCloudflareConfig(); 4 | -------------------------------------------------------------------------------- /examples/create-next-app/open-next.config.ts: -------------------------------------------------------------------------------- 1 | import { defineCloudflareConfig } from "@opennextjs/cloudflare"; 2 | 3 | export default defineCloudflareConfig(); 4 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/redirect-destination/page.tsx: -------------------------------------------------------------------------------- 1 | export default function RedirectDestination() { 2 | return
Redirect Destination
; 3 | } 4 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/rewrite-destination/page.tsx: -------------------------------------------------------------------------------- 1 | export default function RewriteDestination() { 2 | return
Rewritten Destination
; 3 | } 4 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/types/review.d.ts: -------------------------------------------------------------------------------- 1 | export type Review = { 2 | id: string; 3 | name: string; 4 | rating: number; 5 | text: string; 6 | }; 7 | -------------------------------------------------------------------------------- /examples/overrides/d1-tag-next/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/overrides/d1-tag-next/app/favicon.ico -------------------------------------------------------------------------------- /examples/overrides/kv-tag-next/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/overrides/kv-tag-next/app/favicon.ico -------------------------------------------------------------------------------- /examples/overrides/memory-queue/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/overrides/memory-queue/app/favicon.ico -------------------------------------------------------------------------------- /examples/playground14/app/page.js: -------------------------------------------------------------------------------- 1 | export default function Home() { 2 | return ( 3 |
4 |

Test misc Next features

5 |
6 | ); 7 | } 8 | -------------------------------------------------------------------------------- /examples/playground15/app/page.js: -------------------------------------------------------------------------------- 1 | export default function Home() { 2 | return ( 3 |
4 |

Test misc Next features

5 |
6 | ); 7 | } 8 | -------------------------------------------------------------------------------- /examples/prisma/e2e/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../common/config-e2e"; 2 | 3 | export default configurePlaywright("prisma"); 4 | -------------------------------------------------------------------------------- /examples/bugs/gh-119/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/bugs/gh-219/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/app/redirect-destination/page.tsx: -------------------------------------------------------------------------------- 1 | export default function RedirectDestination() { 2 | return
Redirect Destination
; 3 | } 4 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/e2e/app-pages-router/public/favicon.ico -------------------------------------------------------------------------------- /examples/e2e/app-router/public/static/frank.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/e2e/app-router/public/static/frank.webp -------------------------------------------------------------------------------- /examples/e2e/experimental/README.md: -------------------------------------------------------------------------------- 1 | # Experimental 2 | 3 | This project is meant to test experimental features that are only available on canary builds of Next.js. 4 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/public/static/frank.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/e2e/pages-router/public/static/frank.webp -------------------------------------------------------------------------------- /examples/next-partial-prerendering/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/next-partial-prerendering/app/favicon.ico -------------------------------------------------------------------------------- /examples/ssg-app/e2e/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../common/config-e2e"; 2 | 3 | export default configurePlaywright("ssg-app"); 4 | -------------------------------------------------------------------------------- /examples/bugs/gh-119/e2e/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../../common/config-e2e"; 2 | 3 | export default configurePlaywright("gh-119"); 4 | -------------------------------------------------------------------------------- /examples/bugs/gh-219/e2e/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../../common/config-e2e"; 2 | 3 | export default configurePlaywright("gh-219"); 4 | -------------------------------------------------------------------------------- /examples/bugs/gh-223/e2e/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../../common/config-e2e"; 2 | 3 | export default configurePlaywright("gh-223"); 4 | -------------------------------------------------------------------------------- /examples/create-next-app/src/app/fonts/GeistVF.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/create-next-app/src/app/fonts/GeistVF.woff -------------------------------------------------------------------------------- /examples/create-next-app/src/app/fonts/GeistMonoVF.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/create-next-app/src/app/fonts/GeistMonoVF.woff -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/public/static/frank.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/e2e/app-pages-router/public/static/frank.webp -------------------------------------------------------------------------------- /examples/overrides/r2-incremental-cache/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/overrides/r2-incremental-cache/app/favicon.ico -------------------------------------------------------------------------------- /examples/playground14/e2e/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../common/config-e2e"; 2 | 3 | export default configurePlaywright("playground14"); 4 | -------------------------------------------------------------------------------- /examples/playground15/e2e/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../common/config-e2e"; 2 | 3 | export default configurePlaywright("playground15"); 4 | -------------------------------------------------------------------------------- /examples/vercel-blog-starter/public/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/vercel-blog-starter/public/favicon/favicon.ico -------------------------------------------------------------------------------- /packages/cloudflare/src/api/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./cloudflare-context.js"; 2 | export { defineCloudflareConfig, getDeploymentId, type OpenNextConfig } from "./config.js"; 3 | -------------------------------------------------------------------------------- /examples/e2e/experimental/e2e/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../../common/config-e2e"; 2 | 3 | export default configurePlaywright("experimental"); 4 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/app/twitter-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/next-partial-prerendering/app/twitter-image.png -------------------------------------------------------------------------------- /examples/vercel-blog-starter/src/app/_components/section-separator.tsx: -------------------------------------------------------------------------------- 1 | export function SectionSeparator() { 2 | return
; 3 | } 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: Support 4 | url: https://discord.gg/opennextjs 5 | about: "Join us on Discord!" 6 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/app/opengraph-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/next-partial-prerendering/app/opengraph-image.png -------------------------------------------------------------------------------- /examples/prisma/prisma.config.ts: -------------------------------------------------------------------------------- 1 | import type { PrismaConfig } from "prisma"; 2 | 3 | export default { 4 | earlyAccess: true, 5 | schema: "./schema.prisma", 6 | } satisfies PrismaConfig; 7 | -------------------------------------------------------------------------------- /examples/vercel-blog-starter/public/favicon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/vercel-blog-starter/public/favicon/favicon-16x16.png -------------------------------------------------------------------------------- /examples/vercel-blog-starter/public/favicon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/vercel-blog-starter/public/favicon/favicon-32x32.png -------------------------------------------------------------------------------- /examples/vercel-blog-starter/public/favicon/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/vercel-blog-starter/public/favicon/mstile-150x150.png -------------------------------------------------------------------------------- /examples/e2e/app-router/public/static/corporate_holiday_card.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/e2e/app-router/public/static/corporate_holiday_card.jpg -------------------------------------------------------------------------------- /examples/middleware/e2e/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../common/config-e2e"; 2 | 3 | export default configurePlaywright("middleware", { multipleBrowsers: true }); 4 | -------------------------------------------------------------------------------- /examples/vercel-blog-starter/public/assets/blog/authors/jj.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/vercel-blog-starter/public/assets/blog/authors/jj.jpeg -------------------------------------------------------------------------------- /examples/vercel-blog-starter/public/assets/blog/authors/joe.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/vercel-blog-starter/public/assets/blog/authors/joe.jpeg -------------------------------------------------------------------------------- /examples/vercel-blog-starter/public/assets/blog/authors/tim.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/vercel-blog-starter/public/assets/blog/authors/tim.jpeg -------------------------------------------------------------------------------- /examples/vercel-blog-starter/public/assets/blog/preview/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/vercel-blog-starter/public/assets/blog/preview/cover.jpg -------------------------------------------------------------------------------- /examples/vercel-blog-starter/public/favicon/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/vercel-blog-starter/public/favicon/apple-touch-icon.png -------------------------------------------------------------------------------- /examples/bugs/gh-119/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /examples/bugs/gh-219/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /examples/bugs/gh-223/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /examples/e2e/app-router/e2e/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../../common/config-e2e"; 2 | 3 | export default configurePlaywright("app-router", { useTurbopack: false }); 4 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/e2e/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from '../../common/config-e2e'; 2 | 3 | export default configurePlaywright('next-partial-prerendering'); 4 | -------------------------------------------------------------------------------- /examples/overrides/static-assets-incremental-cache/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/overrides/static-assets-incremental-cache/app/favicon.ico -------------------------------------------------------------------------------- /examples/create-next-app/e2e/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../common/config-e2e"; 2 | 3 | export default configurePlaywright("create-next-app", { multipleBrowsers: true }); 4 | -------------------------------------------------------------------------------- /examples/create-next-app/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/public/static/corporate_holiday_card.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/e2e/app-pages-router/public/static/corporate_holiday_card.jpg -------------------------------------------------------------------------------- /examples/e2e/app-router/app/methods/get/redirect/route.ts: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export async function GET(request: Request) { 4 | redirect("https://nextjs.org/"); 5 | } 6 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/e2e/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../../common/config-e2e"; 2 | 3 | export default configurePlaywright("pages-router", { useTurbopack: false }); 4 | -------------------------------------------------------------------------------- /examples/vercel-blog-starter/public/assets/blog/hello-world/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/vercel-blog-starter/public/assets/blog/hello-world/cover.jpg -------------------------------------------------------------------------------- /examples/vercel-blog-starter/public/favicon/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/vercel-blog-starter/public/favicon/android-chrome-192x192.png -------------------------------------------------------------------------------- /examples/vercel-blog-starter/public/favicon/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/vercel-blog-starter/public/favicon/android-chrome-512x512.png -------------------------------------------------------------------------------- /packages/cloudflare/src/cli/build/utils/normalize-path.ts: -------------------------------------------------------------------------------- 1 | import { posix, sep } from "node:path"; 2 | 3 | export function normalizePath(path: string) { 4 | return path.replaceAll(sep, posix.sep); 5 | } 6 | -------------------------------------------------------------------------------- /examples/e2e/app-router/e2e/playwright.turbopack.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../../common/config-e2e"; 2 | 3 | export default configurePlaywright("app-router", { useTurbopack: true }); 4 | -------------------------------------------------------------------------------- /examples/e2e/experimental/src/app/api/revalidate/route.ts: -------------------------------------------------------------------------------- 1 | import { revalidateTag } from "next/cache"; 2 | 3 | export function GET() { 4 | revalidateTag("fullyTagged"); 5 | return new Response("DONE"); 6 | } 7 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/e2e/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../../common/config-e2e"; 2 | 3 | export default configurePlaywright("app-pages-router", { useTurbopack: false }); 4 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/e2e/playwright.turbopack.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../../common/config-e2e"; 2 | 3 | export default configurePlaywright("pages-router", { useTurbopack: true }); 4 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/public/nextjs-icon-light-background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/next-partial-prerendering/public/nextjs-icon-light-background.png -------------------------------------------------------------------------------- /examples/next-partial-prerendering/public/patrick-OIFgeLnjwrM-unsplash.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/next-partial-prerendering/public/patrick-OIFgeLnjwrM-unsplash.jpg -------------------------------------------------------------------------------- /examples/vercel-blog-starter/public/assets/blog/dynamic-routing/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/vercel-blog-starter/public/assets/blog/dynamic-routing/cover.jpg -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/e2e/playwright.turbopack.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../../common/config-e2e"; 2 | 3 | export default configurePlaywright("app-pages-router", { useTurbopack: true }); 4 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/api/client/route.ts: -------------------------------------------------------------------------------- 1 | import { NextResponse } from "next/server"; 2 | 3 | export async function GET(request: Request) { 4 | return NextResponse.json({ 5 | hello: "client", 6 | }); 7 | } 8 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/api/host/route.ts: -------------------------------------------------------------------------------- 1 | import { NextResponse } from "next/server"; 2 | 3 | export async function GET(request: Request) { 4 | return NextResponse.json({ 5 | url: request.url, 6 | }); 7 | } 8 | -------------------------------------------------------------------------------- /examples/e2e/utils.ts: -------------------------------------------------------------------------------- 1 | import { createHash } from "node:crypto"; 2 | 3 | export function validateMd5(data: Buffer, expectedHash: string) { 4 | return createHash("md5").update(data).digest("hex") === expectedHash; 5 | } 6 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/public/eniko-kis-KsLPTsYaqIQ-unsplash.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/next-partial-prerendering/public/eniko-kis-KsLPTsYaqIQ-unsplash.jpg -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/app/api/client/route.ts: -------------------------------------------------------------------------------- 1 | import { NextResponse } from "next/server"; 2 | 3 | export async function GET(request: Request) { 4 | return NextResponse.json({ 5 | hello: "client", 6 | }); 7 | } 8 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/app/api/host/route.ts: -------------------------------------------------------------------------------- 1 | import { NextResponse } from "next/server"; 2 | 3 | export async function GET(request: Request) { 4 | return NextResponse.json({ 5 | url: request.url, 6 | }); 7 | } 8 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/public/prince-akachi-LWkFHEGpleE-unsplash.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/next-partial-prerendering/public/prince-akachi-LWkFHEGpleE-unsplash.jpg -------------------------------------------------------------------------------- /examples/next-partial-prerendering/public/yoann-siloine-_T4w3JDm6ug-unsplash.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/next-partial-prerendering/public/yoann-siloine-_T4w3JDm6ug-unsplash.jpg -------------------------------------------------------------------------------- /examples/prisma/e2e/playwright.dev.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../common/config-e2e"; 2 | 3 | export default configurePlaywright("prisma", { 4 | isCI: !!process.env.CI, 5 | isWorker: false, 6 | }); 7 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/public/guillaume-coupy-6HuoHgK7FN8-unsplash.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/next-partial-prerendering/public/guillaume-coupy-6HuoHgK7FN8-unsplash.jpg -------------------------------------------------------------------------------- /examples/playground15/worker-configuration.d.ts: -------------------------------------------------------------------------------- 1 | // Generated by Wrangler by running `wrangler types --env-interface CloudflareEnv` 2 | 3 | interface CloudflareEnv { 4 | hello: "Hello World from the cloudflare context!"; 5 | } 6 | -------------------------------------------------------------------------------- /examples/bugs/gh-223/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | typescript: { ignoreBuildErrors: true }, 4 | eslint: { ignoreDuringBuilds: true }, 5 | }; 6 | 7 | export default nextConfig; 8 | -------------------------------------------------------------------------------- /examples/middleware/e2e/playwright.dev.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../common/config-e2e"; 2 | 3 | export default configurePlaywright("middleware", { 4 | isCI: !!process.env.CI, 5 | isWorker: false, 6 | }); 7 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/public/alexander-andrews-brAkTCdnhW8-unsplash.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opennextjs/opennextjs-cloudflare/HEAD/examples/next-partial-prerendering/public/alexander-andrews-brAkTCdnhW8-unsplash.jpg -------------------------------------------------------------------------------- /examples/playground14/e2e/playwright.dev.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../common/config-e2e"; 2 | 3 | export default configurePlaywright("playground14", { 4 | isCI: !!process.env.CI, 5 | isWorker: false, 6 | }); 7 | -------------------------------------------------------------------------------- /examples/playground15/e2e/playwright.dev.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../common/config-e2e"; 2 | 3 | export default configurePlaywright("playground15", { 4 | isCI: !!process.env.CI, 5 | isWorker: false, 6 | }); 7 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/app/ssg/page.tsx: -------------------------------------------------------------------------------- 1 | export const dynamic = "force-static"; 2 | 3 | export default function Page() { 4 | return ( 5 |
6 | This is a static page 7 |
8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/server-actions/page.tsx: -------------------------------------------------------------------------------- 1 | import Client from "./client"; 2 | 3 | export default function Page() { 4 | return ( 5 |
6 |

Server Actions

7 | 8 |
9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /examples/e2e/experimental/src/components/static.tsx: -------------------------------------------------------------------------------- 1 | export function StaticComponent() { 2 | return ( 3 |
4 |

Static Component

5 |

This is a static component that does not change.

6 |
7 | ); 8 | } 9 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: { 4 | content: ["./src/**/*.{js,ts,jsx,tsx,mdx}", "../../examples/shared/**/*.{jsx,tsx}"], 5 | }, 6 | autoprefixer: {}, 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/app/server-actions/page.tsx: -------------------------------------------------------------------------------- 1 | import Client from "./client"; 2 | 3 | export default function Page() { 4 | return ( 5 |
6 |

Server Actions

7 | 8 |
9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/revalidate-tag/page.tsx: -------------------------------------------------------------------------------- 1 | async function getTime() { 2 | return new Date().toISOString(); 3 | } 4 | 5 | export default async function ISR() { 6 | const time = getTime(); 7 | return
Time: {time}
; 8 | } 9 | -------------------------------------------------------------------------------- /examples/e2e/app-router/open-next.turbopack.config.ts: -------------------------------------------------------------------------------- 1 | import config from "./open-next.config.js"; 2 | 3 | export default { 4 | ...config, 5 | // Override the build command to use Turbopack 6 | buildCommand: "next build --turbopack", 7 | }; 8 | -------------------------------------------------------------------------------- /examples/vercel-blog-starter/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | typescript: { ignoreBuildErrors: true }, 4 | eslint: { ignoreDuringBuilds: true }, 5 | }; 6 | 7 | export default nextConfig; 8 | -------------------------------------------------------------------------------- /examples/bugs/gh-119/next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from "next"; 2 | 3 | const nextConfig: NextConfig = { 4 | typescript: { ignoreBuildErrors: true }, 5 | eslint: { ignoreDuringBuilds: true }, 6 | }; 7 | 8 | export default nextConfig; 9 | -------------------------------------------------------------------------------- /examples/bugs/gh-219/next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from "next"; 2 | 3 | const nextConfig: NextConfig = { 4 | typescript: { ignoreBuildErrors: true }, 5 | eslint: { ignoreDuringBuilds: true }, 6 | }; 7 | 8 | export default nextConfig; 9 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/open-next.turbopack.config.ts: -------------------------------------------------------------------------------- 1 | import config from "./open-next.config.js"; 2 | 3 | export default { 4 | ...config, 5 | // Override the build command to use Turbopack 6 | buildCommand: "next build --turbopack", 7 | }; 8 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import "@/styles/globals.css"; 2 | 3 | import type { AppProps } from "next/app"; 4 | 5 | export default function App({ Component, pageProps }: AppProps) { 6 | return ; 7 | } 8 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/cookies/page.tsx: -------------------------------------------------------------------------------- 1 | import { cookies } from "next/headers"; 2 | 3 | export default async function Page() { 4 | const foo = (await cookies()).get("foo")?.value; 5 | 6 | return
{foo}
; 7 | } 8 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/methods/get/dynamic-segments/[slug]/route.ts: -------------------------------------------------------------------------------- 1 | export async function GET(request: Request, { params }: { params: Promise<{ slug: string }> }) { 2 | const { slug } = await params; 3 | return Response.json({ slug }); 4 | } 5 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/open-next.turbopack.config.ts: -------------------------------------------------------------------------------- 1 | import config from "./open-next.config.js"; 2 | 3 | export default { 4 | ...config, 5 | // Override the build command to use Turbopack 6 | buildCommand: "next build --turbopack", 7 | }; 8 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/src/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import "@/styles/globals.css"; 2 | 3 | import type { AppProps } from "next/app"; 4 | 5 | export default function App({ Component, pageProps }: AppProps) { 6 | return ; 7 | } 8 | -------------------------------------------------------------------------------- /examples/playground14/app/api/request/route.ts: -------------------------------------------------------------------------------- 1 | import { NextRequest } from "next/server"; 2 | 3 | export const GET = (request: NextRequest) => { 4 | return new Response(JSON.stringify({ nextUrl: request.nextUrl.href, url: request.url })); 5 | }; 6 | -------------------------------------------------------------------------------- /examples/playground15/app/api/request/route.ts: -------------------------------------------------------------------------------- 1 | import { NextRequest } from "next/server"; 2 | 3 | export const GET = (request: NextRequest) => { 4 | return new Response(JSON.stringify({ nextUrl: request.nextUrl.href, url: request.url })); 5 | }; 6 | -------------------------------------------------------------------------------- /create-cloudflare/next/public/_headers: -------------------------------------------------------------------------------- 1 | # https://developers.cloudflare.com/workers/static-assets/headers 2 | # https://opennext.js.org/cloudflare/caching#static-assets-caching 3 | /_next/static/* 4 | Cache-Control: public,max-age=31536000,immutable 5 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/src/pages/api/query.ts: -------------------------------------------------------------------------------- 1 | import type { NextApiRequest, NextApiResponse } from "next"; 2 | 3 | export default function handler(req: NextApiRequest, res: NextApiResponse) { 4 | res.status(200).json({ query: req.query }); 5 | } 6 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/src/pages/fallback-intercepted/static.tsx: -------------------------------------------------------------------------------- 1 | export default function Page() { 2 | return ( 3 |
4 |

Static Fallback Page

5 |

This is a fully static page.

6 |
7 | ); 8 | } 9 | -------------------------------------------------------------------------------- /examples/overrides/d1-tag-next/e2e/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../../common/config-e2e"; 2 | 3 | // Here we don't want to run the tests in parallel 4 | export default configurePlaywright("d1-tag-next", { parallel: false }); 5 | -------------------------------------------------------------------------------- /examples/overrides/kv-tag-next/e2e/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../../common/config-e2e"; 2 | 3 | // Here we don't want to run the tests in parallel 4 | export default configurePlaywright("kv-tag-next", { parallel: false }); 5 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/components/product-best-seller.tsx: -------------------------------------------------------------------------------- 1 | export const ProductBestSeller = () => { 2 | return ( 3 |
4 | Best Seller 5 |
6 | ); 7 | }; 8 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/app/ssr/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { PropsWithChildren } from "react"; 2 | 3 | export default function Layout({ children }: PropsWithChildren) { 4 | return ( 5 |
6 |

SSR

7 | {children} 8 |
9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/isr/page.tsx: -------------------------------------------------------------------------------- 1 | async function getTime() { 2 | return new Date().toISOString(); 3 | } 4 | 5 | export const revalidate = 10; 6 | export default async function ISR() { 7 | const time = getTime(); 8 | return
Time: {time}
; 9 | } 10 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/src/pages/api/dynamic/precedence/index.ts: -------------------------------------------------------------------------------- 1 | import type { NextApiRequest, NextApiResponse } from "next"; 2 | 3 | export default function handler(req: NextApiRequest, res: NextApiResponse) { 4 | res.status(200).json({ precedence: "true" }); 5 | } 6 | -------------------------------------------------------------------------------- /examples/playground15/app/api/signal/revalidate/route.ts: -------------------------------------------------------------------------------- 1 | import { revalidatePath } from "next/cache"; 2 | 3 | export const dynamic = "force-dynamic"; 4 | 5 | export async function GET() { 6 | revalidatePath("/signal/"); 7 | 8 | return new Response("ok"); 9 | } 10 | -------------------------------------------------------------------------------- /examples/ssg-app/app/globals.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | max-width: 100vw; 4 | overflow-x: hidden; 5 | height: 100vh; 6 | display: flex; 7 | flex-direction: column; 8 | } 9 | 10 | footer { 11 | padding: 1rem; 12 | display: flex; 13 | justify-content: end; 14 | } 15 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/app/isr/page.tsx: -------------------------------------------------------------------------------- 1 | async function getTime() { 2 | return new Date().toISOString(); 3 | } 4 | 5 | export const revalidate = 10; 6 | export default async function ISR() { 7 | const time = getTime(); 8 | return
Time: {time}
; 9 | } 10 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/api/revalidate-path/route.ts: -------------------------------------------------------------------------------- 1 | import { revalidatePath } from "next/cache"; 2 | 3 | export const dynamic = "force-dynamic"; 4 | 5 | export async function GET() { 6 | revalidatePath("/revalidate-path"); 7 | 8 | return new Response("ok"); 9 | } 10 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/src/pages/api/dynamic/[slug].ts: -------------------------------------------------------------------------------- 1 | import type { NextApiRequest, NextApiResponse } from "next"; 2 | 3 | export default function handler(req: NextApiRequest, res: NextApiResponse) { 4 | const { slug } = req.query; 5 | res.status(200).json({ slug }); 6 | } 7 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/src/pages/api/dynamic/catch-all-optional/[[...slug]].ts: -------------------------------------------------------------------------------- 1 | import type { NextApiRequest, NextApiResponse } from "next"; 2 | 3 | export default function handler(req: NextApiRequest, res: NextApiResponse) { 4 | res.status(200).json({ optional: "true" }); 5 | } 6 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/albums/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from "react"; 2 | 3 | export default function Layout({ children, modal }: { children: ReactNode; modal: ReactNode }) { 4 | return ( 5 |
6 | {children} 7 | {modal} 8 |
9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/api/revalidate-tag/route.ts: -------------------------------------------------------------------------------- 1 | import { revalidateTag } from "next/cache"; 2 | 3 | export const dynamic = "force-dynamic"; 4 | 5 | export async function GET() { 6 | revalidateTag("revalidate", { expire: 0 }); 7 | 8 | return new Response("ok"); 9 | } 10 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/app/albums/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from "react"; 2 | 3 | export default function Layout({ children, modal }: { children: ReactNode; modal: ReactNode }) { 4 | return ( 5 |
6 | {children} 7 | {modal} 8 |
9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/parallel/@a/page.tsx: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | 3 | export default function A() { 4 | return ( 5 |
6 |

Parallel Route A

7 | Go to a-page 8 |
9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /examples/overrides/d1-tag-next/app/globals.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | max-width: 100vw; 4 | overflow-x: hidden; 5 | height: 100vh; 6 | display: flex; 7 | flex-direction: column; 8 | } 9 | 10 | footer { 11 | padding: 1rem; 12 | display: flex; 13 | justify-content: end; 14 | } 15 | -------------------------------------------------------------------------------- /examples/overrides/kv-tag-next/app/globals.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | max-width: 100vw; 4 | overflow-x: hidden; 5 | height: 100vh; 6 | display: flex; 7 | flex-direction: column; 8 | } 9 | 10 | footer { 11 | padding: 1rem; 12 | display: flex; 13 | justify-content: end; 14 | } 15 | -------------------------------------------------------------------------------- /examples/overrides/memory-queue/app/globals.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | max-width: 100vw; 4 | overflow-x: hidden; 5 | height: 100vh; 6 | display: flex; 7 | flex-direction: column; 8 | } 9 | 10 | footer { 11 | padding: 1rem; 12 | display: flex; 13 | justify-content: end; 14 | } 15 | -------------------------------------------------------------------------------- /examples/vercel-blog-starter/src/app/_components/container.tsx: -------------------------------------------------------------------------------- 1 | type Props = { 2 | children?: React.ReactNode; 3 | }; 4 | 5 | const Container = ({ children }: Props) => { 6 | return
{children}
; 7 | }; 8 | 9 | export default Container; 10 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/methods/get/revalidate/route.ts: -------------------------------------------------------------------------------- 1 | export const revalidate = 5; 2 | 3 | async function getTime() { 4 | return new Date().toISOString(); 5 | } 6 | 7 | export async function GET() { 8 | const time = await getTime(); 9 | return Response.json({ time }); 10 | } 11 | -------------------------------------------------------------------------------- /examples/playground15/app/image/page.tsx: -------------------------------------------------------------------------------- 1 | import Image from "next/image"; 2 | 3 | import tomineImg from "../../public/tomine.webp"; 4 | 5 | export default function Page() { 6 | return ( 7 |
8 | Picture of Tomine 9 |
10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /examples/vercel-blog-starter/src/lib/markdownToHtml.ts: -------------------------------------------------------------------------------- 1 | import { remark } from "remark"; 2 | import html from "remark-html"; 3 | 4 | export default async function markdownToHtml(markdown: string) { 5 | const result = await remark().use(html).process(markdown); 6 | return result.toString(); 7 | } 8 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/app/parallel/@a/page.tsx: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | 3 | export default function A() { 4 | return ( 5 |
6 |

Parallel Route A

7 | Go to a-page 8 |
9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/methods/get/static/route.ts: -------------------------------------------------------------------------------- 1 | export const dynamic = "force-static"; 2 | 3 | async function getTime() { 4 | return new Date().toISOString(); 5 | } 6 | 7 | export async function GET() { 8 | const time = await getTime(); 9 | return Response.json({ time }); 10 | } 11 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/parallel/@b/page.tsx: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | 3 | export default function B() { 4 | return ( 5 |
6 |

Parallel Route B

7 | 8 | Go to b-page 9 |
10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /examples/overrides/r2-incremental-cache/app/globals.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | max-width: 100vw; 4 | overflow-x: hidden; 5 | height: 100vh; 6 | display: flex; 7 | flex-direction: column; 8 | } 9 | 10 | footer { 11 | padding: 1rem; 12 | display: flex; 13 | justify-content: end; 14 | } 15 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/app/parallel/@b/page.tsx: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | 3 | export default function B() { 4 | return ( 5 |
6 |

Parallel Route B

7 | 8 | Go to b-page 9 |
10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/app/not-found.tsx: -------------------------------------------------------------------------------- 1 | export default function NotFound() { 2 | return ( 3 |
4 |

Not Found

5 |

Could not find requested resource

6 |
7 | ); 8 | } 9 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | typescript: { ignoreBuildErrors: true }, 4 | eslint: { ignoreDuringBuilds: true }, 5 | experimental: { 6 | ppr: true, 7 | }, 8 | }; 9 | 10 | module.exports = nextConfig; 11 | -------------------------------------------------------------------------------- /examples/playground14/pages/api/pages.ts: -------------------------------------------------------------------------------- 1 | import type { NextApiRequest, NextApiResponse } from "next"; 2 | 3 | type Data = { 4 | hello: string; 5 | }; 6 | 7 | export default function handler(req: NextApiRequest, res: NextApiResponse) { 8 | res.status(200).json({ hello: "world" }); 9 | } 10 | -------------------------------------------------------------------------------- /examples/overrides/static-assets-incremental-cache/app/globals.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | max-width: 100vw; 4 | overflow-x: hidden; 5 | height: 100vh; 6 | display: flex; 7 | flex-direction: column; 8 | } 9 | 10 | footer { 11 | padding: 1rem; 12 | display: flex; 13 | justify-content: end; 14 | } 15 | -------------------------------------------------------------------------------- /examples/overrides/d1-tag-next/app/action.ts: -------------------------------------------------------------------------------- 1 | "use server"; 2 | 3 | import { revalidatePath, revalidateTag } from "next/cache"; 4 | 5 | export async function revalidateTagAction() { 6 | revalidateTag("date"); 7 | } 8 | 9 | export async function revalidatePathAction() { 10 | revalidatePath("/"); 11 | } 12 | -------------------------------------------------------------------------------- /examples/overrides/kv-tag-next/app/action.ts: -------------------------------------------------------------------------------- 1 | "use server"; 2 | 3 | import { revalidatePath, revalidateTag } from "next/cache"; 4 | 5 | export async function revalidateTagAction() { 6 | revalidateTag("date"); 7 | } 8 | 9 | export async function revalidatePathAction() { 10 | revalidatePath("/"); 11 | } 12 | -------------------------------------------------------------------------------- /examples/playground14/app/layout.js: -------------------------------------------------------------------------------- 1 | export const metadata = { 2 | title: "API hello-world", 3 | description: "a simple api hello-world app", 4 | }; 5 | 6 | export default function RootLayout({ children }) { 7 | return ( 8 | 9 | {children} 10 | 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /examples/playground15/app/layout.js: -------------------------------------------------------------------------------- 1 | export const metadata = { 2 | title: "API hello-world", 3 | description: "a simple api hello-world app", 4 | }; 5 | 6 | export default function RootLayout({ children }) { 7 | return ( 8 | 9 | {children} 10 | 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/app/image-optimization/page.tsx: -------------------------------------------------------------------------------- 1 | import Image from "next/image"; 2 | 3 | export default function ImageOptimization() { 4 | return ( 5 |
6 | Corporate Holiday Card 7 |
8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/pages/_document.tsx: -------------------------------------------------------------------------------- 1 | import { Head, Html, Main, NextScript } from "next/document"; 2 | 3 | export default function Document() { 4 | return ( 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/src/pages/_document.tsx: -------------------------------------------------------------------------------- 1 | import { Head, Html, Main, NextScript } from "next/document"; 2 | 3 | export default function Document() { 4 | return ( 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/components/cart-count.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useCartCount } from '#/components/cart-count-context'; 4 | 5 | export function CartCount({ initialCartCount }: { initialCartCount: number }) { 6 | const [count] = useCartCount(initialCartCount); 7 | return {count}; 8 | } 9 | -------------------------------------------------------------------------------- /examples/overrides/memory-queue/e2e/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../../common/config-e2e"; 2 | 3 | // Here we don't want to run the tests in parallel 4 | export default configurePlaywright("memory-queue", { 5 | isCI: !!process.env.CI, 6 | parallel: false, 7 | multipleBrowsers: false, 8 | }); 9 | -------------------------------------------------------------------------------- /packages/cloudflare/src/cli/build/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./copy-package-cli-files.js"; 2 | export * from "./create-config-files.js"; 3 | export * from "./ensure-cf-config.js"; 4 | export * from "./extract-project-env-vars.js"; 5 | export * from "./needs-experimental-react.js"; 6 | export * from "./normalize-path.js"; 7 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/headers/page.tsx: -------------------------------------------------------------------------------- 1 | import { headers } from "next/headers"; 2 | 3 | export default async function Headers() { 4 | const middlewareHeader = (await headers()).get("request-header"); 5 | return ( 6 |
7 |

Headers

8 |
{middlewareHeader}
9 |
10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /examples/bugs/gh-119/e2e/base.spec.ts: -------------------------------------------------------------------------------- 1 | import { test, expect } from "@playwright/test"; 2 | 3 | test.describe("bugs/gh-119", () => { 4 | test("the index page of the application shows the Next.js logo", async ({ page }) => { 5 | await page.goto("/"); 6 | await expect(page.getByAltText("Next.js logo")).toBeVisible(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /examples/bugs/gh-219/e2e/base.spec.ts: -------------------------------------------------------------------------------- 1 | import { test, expect } from "@playwright/test"; 2 | 3 | test.describe("bugs/gh-219", () => { 4 | test("the index page of the application shows the Next.js logo", async ({ page }) => { 5 | await page.goto("/"); 6 | await expect(page.getByAltText("Next.js logo")).toBeVisible(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /examples/overrides/static-assets-incremental-cache/app/action.ts: -------------------------------------------------------------------------------- 1 | "use server"; 2 | 3 | import { revalidatePath, revalidateTag } from "next/cache"; 4 | 5 | export async function revalidateTagAction() { 6 | revalidateTag("date"); 7 | } 8 | 9 | export async function revalidatePathAction() { 10 | revalidatePath("/"); 11 | } 12 | -------------------------------------------------------------------------------- /examples/overrides/static-assets-incremental-cache/e2e/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../../common/config-e2e"; 2 | 3 | // Here we don't want to run the tests in parallel 4 | export default configurePlaywright("static-assets-incremental-cache", { 5 | isCI: !!process.env.CI, 6 | parallel: false, 7 | }); 8 | -------------------------------------------------------------------------------- /examples/overrides/d1-tag-next/next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from "next"; 2 | import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare"; 3 | 4 | initOpenNextCloudflareForDev(); 5 | 6 | const nextConfig: NextConfig = { 7 | typescript: { ignoreBuildErrors: true }, 8 | }; 9 | 10 | export default nextConfig; 11 | -------------------------------------------------------------------------------- /examples/overrides/kv-tag-next/next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from "next"; 2 | import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare"; 3 | 4 | initOpenNextCloudflareForDev(); 5 | 6 | const nextConfig: NextConfig = { 7 | typescript: { ignoreBuildErrors: true }, 8 | }; 9 | 10 | export default nextConfig; 11 | -------------------------------------------------------------------------------- /examples/overrides/memory-queue/next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from "next"; 2 | import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare"; 3 | 4 | initOpenNextCloudflareForDev(); 5 | 6 | const nextConfig: NextConfig = { 7 | typescript: { ignoreBuildErrors: true }, 8 | }; 9 | 10 | export default nextConfig; 11 | -------------------------------------------------------------------------------- /examples/overrides/r2-incremental-cache/e2e/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { configurePlaywright } from "../../../common/config-e2e"; 2 | 3 | // Here we don't want to run the tests in parallel 4 | export default configurePlaywright("r2-incremental-cache", { 5 | isCI: !!process.env.CI, 6 | parallel: false, 7 | multipleBrowsers: false, 8 | }); 9 | -------------------------------------------------------------------------------- /examples/playground15/app/api/instrumentation/route.ts: -------------------------------------------------------------------------------- 1 | import { NextResponse } from "next/server"; 2 | 3 | export function GET() { 4 | return NextResponse.json({ 5 | "nodejs-instrumentation-setup": globalThis["__NODEJS_INSTRUMENTATION_SETUP"], 6 | "edge-instrumentation-setup": globalThis["__EDGE_INSTRUMENTATION_SETUP"], 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /examples/ssg-app/open-next.config.ts: -------------------------------------------------------------------------------- 1 | import { defineCloudflareConfig } from "@opennextjs/cloudflare"; 2 | import staticAssetsIncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/static-assets-incremental-cache"; 3 | 4 | export default defineCloudflareConfig({ 5 | incrementalCache: staticAssetsIncrementalCache, 6 | }); 7 | -------------------------------------------------------------------------------- /examples/create-next-app/e2e/base.spec.ts: -------------------------------------------------------------------------------- 1 | import { test, expect } from "@playwright/test"; 2 | 3 | test.describe("create-next-app", () => { 4 | test("the index page of the application shows the Next.js logo", async ({ page }) => { 5 | await page.goto("/"); 6 | await expect(page.getByAltText("Next.js logo")).toBeVisible(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/api/auth/[...better-auth]/route.ts: -------------------------------------------------------------------------------- 1 | import { NextResponse } from "next/server"; 2 | 3 | export async function GET(_req: Request, { params }: { params: Promise<{ "better-auth": string[] }> }) { 4 | const { "better-auth": slugs } = await params; 5 | 6 | return NextResponse.json({ 7 | slugs, 8 | }); 9 | } 10 | -------------------------------------------------------------------------------- /examples/prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | generator client { 2 | provider = "prisma-client-js" 3 | previewFeatures = ["driverAdapters"] 4 | } 5 | 6 | datasource db { 7 | provider = "sqlite" 8 | url = env("NOT_USED") 9 | } 10 | 11 | model users { 12 | id Int @id @default(autoincrement()) 13 | email String @unique 14 | name String? 15 | } -------------------------------------------------------------------------------- /examples/bugs/gh-223/e2e/base.spec.ts: -------------------------------------------------------------------------------- 1 | import { test, expect } from "@playwright/test"; 2 | 3 | test.describe("bugs/gh-223", () => { 4 | test("api route", async ({ page }) => { 5 | const res = await page.request.get("/api/image"); 6 | expect(res.status()).toEqual(200); 7 | expect((await res.json()).image).toEqual(""); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /examples/overrides/r2-incremental-cache/next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from "next"; 2 | import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare"; 3 | 4 | initOpenNextCloudflareForDev(); 5 | 6 | const nextConfig: NextConfig = { 7 | typescript: { ignoreBuildErrors: true }, 8 | }; 9 | 10 | export default nextConfig; 11 | -------------------------------------------------------------------------------- /examples/playground14/open-next.config.ts: -------------------------------------------------------------------------------- 1 | import { defineCloudflareConfig } from "@opennextjs/cloudflare"; 2 | import kvIncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/kv-incremental-cache"; 3 | 4 | export default defineCloudflareConfig({ 5 | incrementalCache: kvIncrementalCache, 6 | enableCacheInterception: true, 7 | }); 8 | -------------------------------------------------------------------------------- /examples/playground15/app/signal/page.tsx: -------------------------------------------------------------------------------- 1 | import SSE from "./_components/sse"; 2 | 3 | export const dynamic = "force-static"; 4 | 5 | export default function Page() { 6 | const date = new Date().toISOString(); 7 | 8 | return ( 9 |
10 |

{date}

11 | 12 | 13 |
14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /examples/vercel-blog-starter/open-next.config.ts: -------------------------------------------------------------------------------- 1 | import { defineCloudflareConfig } from "@opennextjs/cloudflare"; 2 | import staticAssetsIncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/static-assets-incremental-cache"; 3 | 4 | export default defineCloudflareConfig({ 5 | incrementalCache: staticAssetsIncrementalCache, 6 | }); 7 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/e2e/skip_trailing.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from "@playwright/test"; 2 | 3 | test("skipTrailingSlashRedirect redirect", async ({ page }) => { 4 | const response = await page.goto("/ssr"); 5 | 6 | expect(response?.request().redirectedFrom()).toBeNull(); 7 | expect(response?.request().url()).toMatch(/\/ssr$/); 8 | }); 9 | -------------------------------------------------------------------------------- /examples/vercel-blog-starter/public/favicon/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #000000 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /examples/vercel-blog-starter/src/interfaces/post.ts: -------------------------------------------------------------------------------- 1 | import { type Author } from "./author"; 2 | 3 | export type Post = { 4 | slug: string; 5 | title: string; 6 | date: string; 7 | coverImage: string; 8 | author: Author; 9 | excerpt: string; 10 | ogImage: { 11 | url: string; 12 | }; 13 | content: string; 14 | preview?: boolean; 15 | }; 16 | -------------------------------------------------------------------------------- /benchmarking/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@opennextjs-cloudflare/benchmarking", 3 | "private": true, 4 | "type": "module", 5 | "devDependencies": { 6 | "tsx": "catalog:", 7 | "@tsconfig/strictest": "catalog:", 8 | "@types/node": "catalog:", 9 | "ora": "^8.1.0" 10 | }, 11 | "scripts": { 12 | "benchmark": "tsx src/index.ts" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/config-redirect/dest/page.tsx: -------------------------------------------------------------------------------- 1 | export default async function Page({ 2 | searchParams, 3 | }: { 4 | searchParams: Promise<{ [key: string]: string | string[] | undefined }>; 5 | }) { 6 | const q = (await searchParams).q; 7 | 8 | return ( 9 | <> 10 |
q: {q}
11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/image-optimization/page.tsx: -------------------------------------------------------------------------------- 1 | import Image from "next/image"; 2 | 3 | export default function ImageOptimization() { 4 | return ( 5 |
6 | Open Next architecture 12 |
13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /examples/middleware/next.config.mjs: -------------------------------------------------------------------------------- 1 | import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare"; 2 | 3 | initOpenNextCloudflareForDev(); 4 | 5 | /** @type {import('next').NextConfig} */ 6 | const nextConfig = { 7 | typescript: { ignoreBuildErrors: true }, 8 | eslint: { ignoreDuringBuilds: true }, 9 | }; 10 | 11 | export default nextConfig; 12 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/open-next.config.ts: -------------------------------------------------------------------------------- 1 | import { defineCloudflareConfig } from '@opennextjs/cloudflare/config'; 2 | import staticAssetsIncrementalCache from '@opennextjs/cloudflare/overrides/incremental-cache/static-assets-incremental-cache'; 3 | 4 | export default defineCloudflareConfig({ 5 | incrementalCache: staticAssetsIncrementalCache, 6 | }); 7 | -------------------------------------------------------------------------------- /examples/create-next-app/next.config.mjs: -------------------------------------------------------------------------------- 1 | import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare"; 2 | 3 | initOpenNextCloudflareForDev(); 4 | 5 | /** @type {import('next').NextConfig} */ 6 | const nextConfig = { 7 | typescript: { ignoreBuildErrors: true }, 8 | eslint: { ignoreDuringBuilds: true }, 9 | }; 10 | 11 | export default nextConfig; 12 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/albums/@modal/(.)[album]/page.tsx: -------------------------------------------------------------------------------- 1 | import Modal from "@example/shared/components/Modal"; 2 | 3 | type Props = { 4 | params: Promise<{ 5 | artist: string; 6 | }>; 7 | }; 8 | export default async function ArtistPage(props: Props) { 9 | const params = await props.params; 10 | return Artists {params.artist}; 11 | } 12 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/ssr/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { PropsWithChildren } from "react"; 2 | 3 | export default function Layout({ children }: PropsWithChildren) { 4 | return ( 5 |
6 |

SSR

7 | {/* 16 kb seems necessary here to prevent any buffering*/} 8 | {/* */} 9 | {children} 10 |
11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /examples/playground14/app/api/env/route.ts: -------------------------------------------------------------------------------- 1 | // This test relies on using `.dev.vars` to set the environment to `development` 2 | // However `next build` is not passed an environment, so we do not want to cache 3 | // the output. 4 | export const dynamic = "force-dynamic"; 5 | 6 | export async function GET() { 7 | return new Response(JSON.stringify(process.env)); 8 | } 9 | -------------------------------------------------------------------------------- /examples/prisma/populate.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS users ( 2 | id INTEGER PRIMARY KEY AUTOINCREMENT, 3 | name TEXT NOT NULL, 4 | email TEXT NOT NULL, 5 | UNIQUE (email) ON CONFLICT REPLACE 6 | ); 7 | 8 | INSERT INTO users (name, email) VALUES 9 | ('Alice', 'alice@example.com'), 10 | ('Bob', 'bob@example.com'), 11 | ('Carol', 'carol@example.com'); -------------------------------------------------------------------------------- /examples/ssg-app/next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from "next"; 2 | import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare"; 3 | 4 | initOpenNextCloudflareForDev(); 5 | 6 | const nextConfig: NextConfig = { 7 | typescript: { ignoreBuildErrors: true }, 8 | eslint: { ignoreDuringBuilds: true }, 9 | }; 10 | 11 | export default nextConfig; 12 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/app/albums/@modal/(.)[album]/page.tsx: -------------------------------------------------------------------------------- 1 | import Modal from "@example/shared/components/Modal"; 2 | 3 | type Props = { 4 | params: Promise<{ 5 | artist: string; 6 | }>; 7 | }; 8 | export default async function ArtistPage(props: Props) { 9 | const params = await props.params; 10 | return Artists {params.artist}; 11 | } 12 | -------------------------------------------------------------------------------- /examples/overrides/static-assets-incremental-cache/open-next.config.ts: -------------------------------------------------------------------------------- 1 | import { defineCloudflareConfig } from "@opennextjs/cloudflare"; 2 | import staticAssetsIncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/static-assets-incremental-cache"; 3 | 4 | export default defineCloudflareConfig({ 5 | incrementalCache: staticAssetsIncrementalCache, 6 | }); 7 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/albums/page.tsx: -------------------------------------------------------------------------------- 1 | import { getAlbums } from "@example/shared/api"; 2 | import Album from "@example/shared/components/Album"; 3 | 4 | export default async function AlbumPage() { 5 | const albums = await getAlbums(); 6 | return ( 7 |
8 | {albums.map((album) => ( 9 | 10 | ))} 11 |
12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /examples/e2e/app-router/e2e/host.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from "@playwright/test"; 2 | 3 | /** 4 | * Tests that the request.url is correct 5 | */ 6 | test("Request.url is host", async ({ baseURL, page }) => { 7 | await page.goto("/api/host"); 8 | 9 | const el = page.getByText(`{"url":"${baseURL}/api/host"}`); 10 | await expect(el).toBeVisible(); 11 | }); 12 | -------------------------------------------------------------------------------- /examples/ssg-app/app/page.module.css: -------------------------------------------------------------------------------- 1 | .page { 2 | display: grid; 3 | grid-template-rows: 20px 1fr 20px; 4 | align-items: center; 5 | justify-items: center; 6 | flex: 1; 7 | border: 3px solid gray; 8 | margin: 1rem; 9 | margin-block-end: 0; 10 | } 11 | 12 | .main { 13 | display: flex; 14 | flex-direction: column; 15 | gap: 32px; 16 | grid-row-start: 2; 17 | } 18 | -------------------------------------------------------------------------------- /examples/vercel-blog-starter/src/lib/constants.ts: -------------------------------------------------------------------------------- 1 | export const EXAMPLE_PATH = "blog-starter"; 2 | export const CMS_NAME = "Markdown"; 3 | export const HOME_OG_IMAGE_URL = 4 | "https://og-image.vercel.app/Next.js%20Blog%20Starter%20Example.png?theme=light&md=1&fontSize=100px&images=https%3A%2F%2Fassets.vercel.com%2Fimage%2Fupload%2Ffront%2Fassets%2Fdesign%2Fnextjs-black-logo.svg"; 5 | -------------------------------------------------------------------------------- /examples/bugs/gh-119/wrangler.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "node_modules/wrangler/config-schema.json", 3 | "main": ".open-next/worker.js", 4 | "name": "gh-119", 5 | "compatibility_date": "2024-12-30", 6 | "compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"], 7 | "assets": { 8 | "directory": ".open-next/assets", 9 | "binding": "ASSETS" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/bugs/gh-219/wrangler.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "node_modules/wrangler/config-schema.json", 3 | "main": ".open-next/worker.js", 4 | "name": "gh-219", 5 | "compatibility_date": "2024-12-30", 6 | "compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"], 7 | "assets": { 8 | "directory": ".open-next/assets", 9 | "binding": "ASSETS" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/bugs/gh-223/wrangler.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "node_modules/wrangler/config-schema.json", 3 | "main": ".open-next/worker.js", 4 | "name": "gh-219", 5 | "compatibility_date": "2024-12-30", 6 | "compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"], 7 | "assets": { 8 | "directory": ".open-next/assets", 9 | "binding": "ASSETS" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/common/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["esnext"], 4 | "allowJs": true, 5 | "skipLibCheck": true, 6 | "strict": false, 7 | "noEmit": true, 8 | "incremental": true, 9 | "module": "esnext", 10 | "esModuleInterop": true, 11 | "moduleResolution": "node", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/e2e/host.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from "@playwright/test"; 2 | 3 | /** 4 | * Tests that the request.url is correct 5 | */ 6 | test("Request.url is host", async ({ baseURL, page }) => { 7 | await page.goto("/api/host"); 8 | 9 | const el = page.getByText(`{"url":"${baseURL}/api/host"}`); 10 | await expect(el).toBeVisible(); 11 | }); 12 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from "next"; 2 | 3 | const nextConfig: NextConfig = { 4 | poweredByHeader: false, 5 | cleanDistDir: true, 6 | output: "standalone", 7 | typescript: { 8 | ignoreBuildErrors: true, 9 | }, 10 | trailingSlash: true, 11 | skipTrailingSlashRedirect: true, 12 | }; 13 | 14 | export default nextConfig; 15 | -------------------------------------------------------------------------------- /packages/cloudflare/env.d.ts: -------------------------------------------------------------------------------- 1 | declare global { 2 | namespace NodeJS { 3 | interface ProcessEnv { 4 | __NEXT_PRIVATE_STANDALONE_CONFIG?: string; 5 | SKIP_NEXT_APP_BUILD?: string; 6 | SKIP_WRANGLER_CONFIG_CHECK?: string; 7 | NEXT_PRIVATE_DEBUG_CACHE?: string; 8 | OPEN_NEXT_ORIGIN: string; 9 | NODE_ENV?: string; 10 | } 11 | } 12 | } 13 | 14 | export {}; 15 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 110, 3 | "singleQuote": false, 4 | "semi": true, 5 | "useTabs": true, 6 | "trailingComma": "es5", 7 | "overrides": [ 8 | { 9 | "// comment": "wrangler doesn't seem to accept wrangler.jsonc with trailing commas", 10 | "files": ["**/wrangler.jsonc"], 11 | "options": { 12 | "trailingComma": "none" 13 | } 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/app/albums/page.tsx: -------------------------------------------------------------------------------- 1 | import { getAlbums } from "@example/shared/api"; 2 | import Album from "@example/shared/components/Album"; 3 | 4 | export default async function AlbumPage() { 5 | const albums = await getAlbums(); 6 | return ( 7 |
8 | {albums.map((album) => ( 9 | 10 | ))} 11 |
12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /examples/e2e/experimental/src/app/use-cache/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Suspense } from "react"; 2 | 3 | export default function Layout({ 4 | children, 5 | }: Readonly<{ 6 | // For some reason using ReactNode here causes a type error 7 | children: any; 8 | }>) { 9 | return ( 10 |
11 | Loading...

}>{children}
12 |
13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /examples/prisma/src/lib/db.ts: -------------------------------------------------------------------------------- 1 | import { PrismaClient } from "@prisma/client"; 2 | import { PrismaD1 } from "@prisma/adapter-d1"; 3 | import { getCloudflareContext } from "@opennextjs/cloudflare"; 4 | 5 | export const getDb = () => { 6 | const { env } = getCloudflareContext(); 7 | const adapter = new PrismaD1(env.DB); 8 | return new PrismaClient({ 9 | adapter, 10 | }); 11 | }; 12 | -------------------------------------------------------------------------------- /examples/create-next-app/wrangler.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "node_modules/wrangler/config-schema.json", 3 | "main": ".open-next/worker.js", 4 | "name": "create-next-app", 5 | "compatibility_date": "2024-12-30", 6 | "compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"], 7 | "assets": { 8 | "directory": ".open-next/assets", 9 | "binding": "ASSETS" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/pages/api/hello.ts: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction 2 | import type { NextApiRequest, NextApiResponse } from "next"; 3 | 4 | type Data = { 5 | hello: string; 6 | }; 7 | 8 | export default function handler(req: NextApiRequest, res: NextApiResponse) { 9 | res.status(200).json({ hello: "world" }); 10 | } 11 | -------------------------------------------------------------------------------- /examples/overrides/d1-tag-next/app/page.module.css: -------------------------------------------------------------------------------- 1 | .page { 2 | display: grid; 3 | grid-template-rows: 20px 1fr 20px; 4 | align-items: center; 5 | justify-items: center; 6 | flex: 1; 7 | border: 3px solid gray; 8 | margin: 1rem; 9 | margin-block-end: 0; 10 | } 11 | 12 | .main { 13 | display: flex; 14 | flex-direction: column; 15 | gap: 32px; 16 | grid-row-start: 2; 17 | } 18 | -------------------------------------------------------------------------------- /examples/overrides/kv-tag-next/app/page.module.css: -------------------------------------------------------------------------------- 1 | .page { 2 | display: grid; 3 | grid-template-rows: 20px 1fr 20px; 4 | align-items: center; 5 | justify-items: center; 6 | flex: 1; 7 | border: 3px solid gray; 8 | margin: 1rem; 9 | margin-block-end: 0; 10 | } 11 | 12 | .main { 13 | display: flex; 14 | flex-direction: column; 15 | gap: 32px; 16 | grid-row-start: 2; 17 | } 18 | -------------------------------------------------------------------------------- /examples/overrides/memory-queue/app/page.module.css: -------------------------------------------------------------------------------- 1 | .page { 2 | display: grid; 3 | grid-template-rows: 20px 1fr 20px; 4 | align-items: center; 5 | justify-items: center; 6 | flex: 1; 7 | border: 3px solid gray; 8 | margin: 1rem; 9 | margin-block-end: 0; 10 | } 11 | 12 | .main { 13 | display: flex; 14 | flex-direction: column; 15 | gap: 32px; 16 | grid-row-start: 2; 17 | } 18 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/src/pages/api/dynamic/catch-all/[...slug].ts: -------------------------------------------------------------------------------- 1 | import type { NextApiRequest, NextApiResponse } from "next"; 2 | 3 | export default function handler(req: NextApiRequest, res: NextApiResponse) { 4 | const { slug } = req.query; 5 | if (!Array.isArray(slug)) { 6 | return res.status(500).json({ error: "Invalid" }); 7 | } 8 | res.status(200).json({ slug }); 9 | } 10 | -------------------------------------------------------------------------------- /examples/playground14/app/api/buildid/route.ts: -------------------------------------------------------------------------------- 1 | // Use headers to force a dynamic response 2 | import { headers } from "next/headers"; 3 | 4 | export async function GET() { 5 | const nextConfig = process.env.__NEXT_PRIVATE_STANDALONE_CONFIG 6 | ? JSON.parse(process.env.__NEXT_PRIVATE_STANDALONE_CONFIG) 7 | : undefined; 8 | return Response.json({ nextConfig, headers: headers() }); 9 | } 10 | -------------------------------------------------------------------------------- /examples/playground14/app/api/instrumentation/route.ts: -------------------------------------------------------------------------------- 1 | import { NextResponse } from "next/server"; 2 | 3 | export const dynamic = "force-dynamic"; 4 | 5 | export function GET() { 6 | return NextResponse.json({ 7 | "nodejs-instrumentation-setup": globalThis["__NODEJS_INSTRUMENTATION_SETUP"], 8 | "edge-instrumentation-setup": globalThis["__EDGE_INSTRUMENTATION_SETUP"], 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /examples/e2e/experimental/src/app/page.tsx: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | import styles from "./page.module.css"; 3 | 4 | export default function Home() { 5 | return ( 6 |
7 |
8 | 9 |

Incremental PPR

10 | 11 |
12 |
13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /examples/overrides/r2-incremental-cache/app/page.module.css: -------------------------------------------------------------------------------- 1 | .page { 2 | display: grid; 3 | grid-template-rows: 20px 1fr 20px; 4 | align-items: center; 5 | justify-items: center; 6 | flex: 1; 7 | border: 3px solid gray; 8 | margin: 1rem; 9 | margin-block-end: 0; 10 | } 11 | 12 | .main { 13 | display: flex; 14 | flex-direction: column; 15 | gap: 32px; 16 | grid-row-start: 2; 17 | } 18 | -------------------------------------------------------------------------------- /examples/overrides/static-assets-incremental-cache/next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from "next"; 2 | import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare"; 3 | 4 | initOpenNextCloudflareForDev(); 5 | 6 | const nextConfig: NextConfig = { 7 | typescript: { ignoreBuildErrors: true }, 8 | eslint: { ignoreDuringBuilds: true }, 9 | }; 10 | 11 | export default nextConfig; 12 | -------------------------------------------------------------------------------- /examples/vercel-blog-starter/src/app/_components/date-formatter.tsx: -------------------------------------------------------------------------------- 1 | import { parseISO, format } from "date-fns"; 2 | 3 | type Props = { 4 | dateString: string; 5 | }; 6 | 7 | const DateFormatter = ({ dateString }: Props) => { 8 | const date = parseISO(dateString); 9 | return ; 10 | }; 11 | 12 | export default DateFormatter; 13 | -------------------------------------------------------------------------------- /examples/vercel-blog-starter/src/app/_components/markdown-styles.module.css: -------------------------------------------------------------------------------- 1 | .markdown { 2 | @apply text-lg leading-relaxed; 3 | } 4 | 5 | .markdown p, 6 | .markdown ul, 7 | .markdown ol, 8 | .markdown blockquote { 9 | @apply my-6; 10 | } 11 | 12 | .markdown h2 { 13 | @apply text-3xl mt-12 mb-4 leading-snug; 14 | } 15 | 16 | .markdown h3 { 17 | @apply text-2xl mt-8 mb-4 leading-snug; 18 | } 19 | -------------------------------------------------------------------------------- /packages/cloudflare/templates/open-next.config.ts: -------------------------------------------------------------------------------- 1 | // default open-next.config.ts file created by @opennextjs/cloudflare 2 | import { defineCloudflareConfig } from "@opennextjs/cloudflare/config"; 3 | import r2IncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/r2-incremental-cache"; 4 | 5 | export default defineCloudflareConfig({ 6 | incrementalCache: r2IncrementalCache, 7 | }); 8 | -------------------------------------------------------------------------------- /examples/playground15/app/api/buildid/route.ts: -------------------------------------------------------------------------------- 1 | // Use headers to force a dynamic response 2 | import { headers } from "next/headers"; 3 | 4 | export async function GET() { 5 | const nextConfig = process.env.__NEXT_PRIVATE_STANDALONE_CONFIG 6 | ? JSON.parse(process.env.__NEXT_PRIVATE_STANDALONE_CONFIG) 7 | : undefined; 8 | return Response.json({ nextConfig, headers: await headers() }); 9 | } 10 | -------------------------------------------------------------------------------- /examples/bugs/gh-119/public/window.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/bugs/gh-219/public/window.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/overrides/static-assets-incremental-cache/app/page.module.css: -------------------------------------------------------------------------------- 1 | .page { 2 | display: grid; 3 | grid-template-rows: 20px 1fr 20px; 4 | align-items: center; 5 | justify-items: center; 6 | flex: 1; 7 | border: 3px solid gray; 8 | margin: 1rem; 9 | margin-block-end: 0; 10 | } 11 | 12 | .main { 13 | display: flex; 14 | flex-direction: column; 15 | gap: 32px; 16 | grid-row-start: 2; 17 | } 18 | -------------------------------------------------------------------------------- /examples/vercel-blog-starter/wrangler.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "node_modules/wrangler/config-schema.json", 3 | "main": ".open-next/worker.js", 4 | "name": "vercel-blog-starter-on-workers", 5 | "compatibility_date": "2024-12-30", 6 | "compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"], 7 | "assets": { 8 | "directory": ".open-next/assets", 9 | "binding": "ASSETS" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /create-cloudflare/next/public/window.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/bugs/gh-119/public/file.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/bugs/gh-219/public/file.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/wrangler.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "node_modules/wrangler/config-schema.json", 3 | "main": ".open-next/worker.js", 4 | "name": "next-partial-prerendering", 5 | "compatibility_date": "2024-12-30", 6 | "compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"], 7 | "assets": { 8 | "directory": ".open-next/assets", 9 | "binding": "ASSETS", 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /create-cloudflare/next/public/file.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/open-next.config.ts: -------------------------------------------------------------------------------- 1 | import { defineCloudflareConfig } from "@opennextjs/cloudflare"; 2 | import r2IncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/r2-incremental-cache"; 3 | import memoryQueue from "@opennextjs/cloudflare/overrides/queue/memory-queue"; 4 | 5 | export default defineCloudflareConfig({ 6 | incrementalCache: r2IncrementalCache, 7 | queue: memoryQueue, 8 | }); 9 | -------------------------------------------------------------------------------- /examples/vercel-blog-starter/src/app/_components/header.tsx: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | 3 | const Header = () => { 4 | return ( 5 |

6 | 7 | Blog 8 | 9 | . 10 |

11 | ); 12 | }; 13 | 14 | export default Header; 15 | -------------------------------------------------------------------------------- /examples/vercel-blog-starter/src/app/_components/post-body.tsx: -------------------------------------------------------------------------------- 1 | import markdownStyles from "./markdown-styles.module.css"; 2 | 3 | type Props = { 4 | content: string; 5 | }; 6 | 7 | export function PostBody({ content }: Props) { 8 | return ( 9 |
10 |
11 |
12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/methods/get/query/route.ts: -------------------------------------------------------------------------------- 1 | import type { NextRequest } from "next/server"; 2 | 3 | export function GET(request: NextRequest) { 4 | const searchParams = request.nextUrl.searchParams; 5 | const query = searchParams.get("query"); 6 | if (query === "OpenNext is awesome!") { 7 | return Response.json({ query }); 8 | } 9 | return new Response("Internal Server Error", { status: 500 }); 10 | } 11 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/src/pages/api/hello.ts: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/pages/building-your-application/routing/api-routes 2 | import type { NextApiRequest, NextApiResponse } from "next"; 3 | 4 | type Data = { 5 | hello: string; 6 | }; 7 | 8 | export default function handler(req: NextApiRequest, res: NextApiResponse) { 9 | res.status(200).json({ hello: "OpenNext rocks!" }); 10 | } 11 | -------------------------------------------------------------------------------- /examples/overrides/memory-queue/open-next.config.ts: -------------------------------------------------------------------------------- 1 | import { defineCloudflareConfig } from "@opennextjs/cloudflare"; 2 | import kvIncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/kv-incremental-cache"; 3 | import memoryQueue from "@opennextjs/cloudflare/overrides/queue/memory-queue"; 4 | 5 | export default defineCloudflareConfig({ 6 | incrementalCache: kvIncrementalCache, 7 | queue: memoryQueue, 8 | }); 9 | -------------------------------------------------------------------------------- /examples/playground14/middleware.js: -------------------------------------------------------------------------------- 1 | import { NextResponse } from "next/server"; 2 | 3 | export function middleware() { 4 | return NextResponse.json({ 5 | "nodejs-instrumentation-setup": globalThis["__NODEJS_INSTRUMENTATION_SETUP"], 6 | "edge-instrumentation-setup": globalThis["__EDGE_INSTRUMENTATION_SETUP"], 7 | }); 8 | } 9 | 10 | export const config = { 11 | matcher: ["/middleware-instrumentation"], 12 | }; 13 | -------------------------------------------------------------------------------- /examples/playground15/middleware.js: -------------------------------------------------------------------------------- 1 | import { NextResponse } from "next/server"; 2 | 3 | export function middleware() { 4 | return NextResponse.json({ 5 | "nodejs-instrumentation-setup": globalThis["__NODEJS_INSTRUMENTATION_SETUP"], 6 | "edge-instrumentation-setup": globalThis["__EDGE_INSTRUMENTATION_SETUP"], 7 | }); 8 | } 9 | 10 | export const config = { 11 | matcher: ["/middleware-instrumentation"], 12 | }; 13 | -------------------------------------------------------------------------------- /examples/vercel-blog-starter/src/app/_components/post-title.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from "react"; 2 | 3 | type Props = { 4 | children?: ReactNode; 5 | }; 6 | 7 | export function PostTitle({ children }: Props) { 8 | return ( 9 |

10 | {children} 11 |

12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/pages/pages_ssr/index.tsx: -------------------------------------------------------------------------------- 1 | import type { InferGetServerSidePropsType } from "next"; 2 | 3 | export async function getServerSideProps() { 4 | return { 5 | props: { 6 | time: new Date().toISOString(), 7 | }, 8 | }; 9 | } 10 | 11 | export default function Page({ time }: InferGetServerSidePropsType) { 12 | return
Time: {time}
; 13 | } 14 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/components/product-low-stock-warning.tsx: -------------------------------------------------------------------------------- 1 | export const ProductLowStockWarning = ({ stock }: { stock: number }) => { 2 | if (stock > 3) { 3 | return null; 4 | } 5 | 6 | if (stock === 0) { 7 | return
Out of stock
; 8 | } 9 | 10 | return ( 11 |
Only {stock} left in stock
12 | ); 13 | }; 14 | -------------------------------------------------------------------------------- /examples/ssg-app/wrangler.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "node_modules/wrangler/config-schema.json", 3 | "main": ".open-next/worker.js", 4 | "name": "ssg-app", 5 | "compatibility_date": "2025-02-04", 6 | "compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"], 7 | "assets": { 8 | "directory": ".open-next/assets", 9 | "binding": "ASSETS" 10 | }, 11 | "vars": { 12 | "APP_VERSION": "1.2.345" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/app/rewrite-destination/page.tsx: -------------------------------------------------------------------------------- 1 | export default async function RewriteDestination(props: { 2 | searchParams: Promise<{ a: string; multi?: string[] }>; 3 | }) { 4 | const searchParams = await props.searchParams; 5 | return ( 6 |
7 |
Rewritten Destination
8 |
a: {searchParams.a}
9 |
multi: {searchParams.multi?.join(", ")}
10 |
11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/pages/pages_isr/index.tsx: -------------------------------------------------------------------------------- 1 | import type { InferGetStaticPropsType } from "next"; 2 | 3 | export async function getStaticProps() { 4 | return { 5 | props: { 6 | time: new Date().toISOString(), 7 | }, 8 | revalidate: 10, 9 | }; 10 | } 11 | 12 | export default function Page({ time }: InferGetStaticPropsType) { 13 | return
Time: {time}
; 14 | } 15 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/api/after/ssg/route.ts: -------------------------------------------------------------------------------- 1 | import { unstable_cache } from "next/cache"; 2 | import { NextResponse } from "next/server"; 3 | 4 | export const dynamic = "force-static"; 5 | 6 | export async function GET() { 7 | const dateFn = unstable_cache(async () => new Date().toISOString(), ["date"], { 8 | tags: ["date"], 9 | }); 10 | const date = await dateFn(); 11 | return NextResponse.json({ date }); 12 | } 13 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/e2e/middleware.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from "playwright/test"; 2 | 3 | test("should return 500 on middleware error", async ({ request }) => { 4 | const response = await request.get("/", { 5 | headers: { 6 | "x-throw": "true", 7 | }, 8 | }); 9 | const body = await response.text(); 10 | expect(response.status()).toBe(500); 11 | expect(body).toContain("Internal Server Error"); 12 | }); 13 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/src/pages/api/revalidate.ts: -------------------------------------------------------------------------------- 1 | import type { NextApiRequest, NextApiResponse } from "next"; 2 | 3 | export default async function handler(req: NextApiRequest, res: NextApiResponse) { 4 | try { 5 | await res.revalidate("/ssg/"); 6 | return res.json({ hello: "OpenNext rocks!" }); 7 | } catch (e) { 8 | console.error(e); 9 | return res.status(500).json({ error: "An error occurred" }); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/middleware/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | 3 | export default function RootLayout({ children }: { children: React.ReactNode }) { 4 | return ( 5 | 6 | {children} 7 | 8 | ); 9 | } 10 | 11 | export const metadata: Metadata = { 12 | title: "Next.js Middleware example", 13 | description: "Redirect and rewrite pages using Next.js Middleware.", 14 | }; 15 | -------------------------------------------------------------------------------- /examples/overrides/static-assets-incremental-cache/wrangler.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "node_modules/wrangler/config-schema.json", 3 | "main": ".open-next/worker.js", 4 | "name": "static-assets-incremental-cache", 5 | "compatibility_date": "2025-02-04", 6 | "compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"], 7 | "assets": { 8 | "directory": ".open-next/assets", 9 | "binding": "ASSETS" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/prisma/next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from "next"; 2 | 3 | const nextConfig: NextConfig = { 4 | /* config options here */ 5 | serverExternalPackages: ["@prisma/client", ".prisma/client"], 6 | typescript: { 7 | ignoreBuildErrors: true, 8 | }, 9 | }; 10 | 11 | import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare"; 12 | initOpenNextCloudflareForDev(); 13 | 14 | export default nextConfig; 15 | -------------------------------------------------------------------------------- /examples/vercel-blog-starter/src/app/_components/avatar.tsx: -------------------------------------------------------------------------------- 1 | type Props = { 2 | name: string; 3 | picture: string; 4 | }; 5 | 6 | const Avatar = ({ name, picture }: Props) => { 7 | return ( 8 |
9 | {name} 10 |
{name}
11 |
12 | ); 13 | }; 14 | 15 | export default Avatar; 16 | -------------------------------------------------------------------------------- /examples/overrides/d1-tag-next/open-next.config.ts: -------------------------------------------------------------------------------- 1 | import { defineCloudflareConfig } from "@opennextjs/cloudflare"; 2 | import kvIncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/kv-incremental-cache"; 3 | import d1NextTagCache from "@opennextjs/cloudflare/overrides/tag-cache/d1-next-tag-cache"; 4 | 5 | export default defineCloudflareConfig({ 6 | incrementalCache: kvIncrementalCache, 7 | tagCache: d1NextTagCache, 8 | }); 9 | -------------------------------------------------------------------------------- /examples/overrides/kv-tag-next/open-next.config.ts: -------------------------------------------------------------------------------- 1 | import { defineCloudflareConfig } from "@opennextjs/cloudflare"; 2 | import kvIncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/kv-incremental-cache"; 3 | import kvNextTagCache from "@opennextjs/cloudflare/overrides/tag-cache/kv-next-tag-cache"; 4 | 5 | export default defineCloudflareConfig({ 6 | incrementalCache: kvIncrementalCache, 7 | tagCache: kvNextTagCache, 8 | }); 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@3.0.3/schema.json", 3 | "changelog": [ 4 | "@changesets/changelog-github", 5 | { 6 | "repo": "opennextjs/opennextjs-cloudflare" 7 | } 8 | ], 9 | "commit": false, 10 | "fixed": [], 11 | "linked": [], 12 | "access": "public", 13 | "baseBranch": "main", 14 | "updateInternalDependencies": "patch", 15 | "ignore": [], 16 | "privatePackages": false 17 | } 18 | -------------------------------------------------------------------------------- /examples/playground15/app/api/env/route.ts: -------------------------------------------------------------------------------- 1 | // This test relies on using `.dev.vars` to set the environment to `development` 2 | // However `next build` is not passed an environment, so we do not want to cache 3 | // the output. 4 | export const dynamic = "force-dynamic"; 5 | 6 | export async function GET() { 7 | return new Response(JSON.stringify(process.env, null, 2), { 8 | headers: { "content-type": "application/json" }, 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /create-cloudflare/next/next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from "next"; 2 | 3 | const nextConfig: NextConfig = { 4 | /* config options here */ 5 | }; 6 | 7 | export default nextConfig; 8 | 9 | // Enable calling `getCloudflareContext()` in `next dev`. 10 | // See https://opennext.js.org/cloudflare/bindings#local-access-to-bindings. 11 | import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare"; 12 | initOpenNextCloudflareForDev(); 13 | -------------------------------------------------------------------------------- /examples/bugs/gh-119/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --background: #ffffff; 7 | --foreground: #171717; 8 | } 9 | 10 | @media (prefers-color-scheme: dark) { 11 | :root { 12 | --background: #0a0a0a; 13 | --foreground: #ededed; 14 | } 15 | } 16 | 17 | body { 18 | color: var(--foreground); 19 | background: var(--background); 20 | font-family: Arial, Helvetica, sans-serif; 21 | } 22 | -------------------------------------------------------------------------------- /examples/bugs/gh-119/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | 3 | export default { 4 | content: [ 5 | "./pages/**/*.{js,ts,jsx,tsx,mdx}", 6 | "./components/**/*.{js,ts,jsx,tsx,mdx}", 7 | "./app/**/*.{js,ts,jsx,tsx,mdx}", 8 | ], 9 | theme: { 10 | extend: { 11 | colors: { 12 | background: "var(--background)", 13 | foreground: "var(--foreground)", 14 | }, 15 | }, 16 | }, 17 | plugins: [], 18 | } satisfies Config; 19 | -------------------------------------------------------------------------------- /examples/bugs/gh-219/src/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --background: #ffffff; 7 | --foreground: #171717; 8 | } 9 | 10 | @media (prefers-color-scheme: dark) { 11 | :root { 12 | --background: #0a0a0a; 13 | --foreground: #ededed; 14 | } 15 | } 16 | 17 | body { 18 | color: var(--foreground); 19 | background: var(--background); 20 | font-family: Arial, Helvetica, sans-serif; 21 | } 22 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/open-next.config.ts: -------------------------------------------------------------------------------- 1 | import { defineCloudflareConfig } from "@opennextjs/cloudflare"; 2 | import r2IncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/r2-incremental-cache"; 3 | import memoryQueue from "@opennextjs/cloudflare/overrides/queue/memory-queue"; 4 | 5 | export default defineCloudflareConfig({ 6 | incrementalCache: r2IncrementalCache, 7 | queue: memoryQueue, 8 | enableCacheInterception: true, 9 | }); 10 | -------------------------------------------------------------------------------- /create-cloudflare/next/open-next.config.ts: -------------------------------------------------------------------------------- 1 | import { defineCloudflareConfig } from "@opennextjs/cloudflare"; 2 | 3 | export default defineCloudflareConfig({ 4 | // Uncomment to enable R2 cache, 5 | // It should be imported as: 6 | // `import r2IncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/r2-incremental-cache";` 7 | // See https://opennext.js.org/cloudflare/caching for more details 8 | // incrementalCache: r2IncrementalCache, 9 | }); 10 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/src/middleware.ts: -------------------------------------------------------------------------------- 1 | import type { NextRequest } from "next/server"; 2 | import { NextResponse } from "next/server"; 3 | 4 | export function middleware(request: NextRequest) { 5 | if (request.headers.get("x-throw")) { 6 | throw new Error("Middleware error"); 7 | } 8 | return NextResponse.next({ 9 | headers: { 10 | "x-from-middleware": "true", 11 | }, 12 | }); 13 | } 14 | 15 | export const config = { 16 | matcher: ["/"], 17 | }; 18 | -------------------------------------------------------------------------------- /examples/e2e/experimental/src/app/ppr/page.tsx: -------------------------------------------------------------------------------- 1 | import { DynamicComponent } from "@/components/dynamic"; 2 | import { StaticComponent } from "@/components/static"; 3 | import { Suspense } from "react"; 4 | 5 | export const experimental_ppr = true; 6 | 7 | export default function PPRPage() { 8 | return ( 9 |
10 | 11 | Loading...
}> 12 | 13 | 14 |
15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/e2e/404.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from "@playwright/test"; 2 | 3 | test("should return 404 on a route not corresponding to any route", async ({ page }) => { 4 | const result = await page.goto("/not-existing/route"); 5 | expect(result).toBeDefined(); 6 | expect(result?.status()).toBe(404); 7 | const headers = result?.headers(); 8 | expect(headers?.["cache-control"]).toBe("private, no-cache, no-store, max-age=0, must-revalidate"); 9 | }); 10 | -------------------------------------------------------------------------------- /examples/e2e/shared/components/Album/Album.tsx: -------------------------------------------------------------------------------- 1 | import type { Album } from "../../api/index"; 2 | import Song from "./Song"; 3 | 4 | type Props = { 5 | album: Album; 6 | }; 7 | export default function Album({ album }: Props) { 8 | return ( 9 |
10 |
Album: {album.album}
11 |
Artist: {album.artist}
12 | {album.songs.map((song) => ( 13 | 14 | ))} 15 |
16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /examples/e2e/shared/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/shared", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "clean": "rm -rf .turbo && rm -rf node_modules" 7 | }, 8 | "dependencies": { 9 | "react": "catalog:e2e", 10 | "react-dom": "catalog:e2e" 11 | }, 12 | "devDependencies": { 13 | "@types/react": "catalog:e2e", 14 | "@types/react-dom": "catalog:e2e" 15 | }, 16 | "peerDependencies": { 17 | "next": "catalog:e2e" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /benchmarking/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "extends": "@tsconfig/strictest/tsconfig.json", 4 | "compilerOptions": { 5 | "target": "ESNext", 6 | "module": "ESNext", 7 | "lib": ["ESNext"], 8 | "types": ["node"], 9 | "moduleResolution": "Bundler", 10 | "forceConsistentCasingInFileNames": true, 11 | "noImplicitReturns": false, 12 | "exactOptionalPropertyTypes": false 13 | }, 14 | "include": ["./src/**/*.ts"] 15 | } 16 | -------------------------------------------------------------------------------- /create-cloudflare/next/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { dirname } from "path"; 2 | import { fileURLToPath } from "url"; 3 | import { FlatCompat } from "@eslint/eslintrc"; 4 | 5 | const __filename = fileURLToPath(import.meta.url); 6 | const __dirname = dirname(__filename); 7 | 8 | const compat = new FlatCompat({ 9 | baseDirectory: __dirname, 10 | }); 11 | 12 | const eslintConfig = [...compat.extends("next/core-web-vitals", "next/typescript")]; 13 | 14 | export default eslintConfig; 15 | -------------------------------------------------------------------------------- /examples/bugs/gh-219/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { dirname } from "path"; 2 | import { fileURLToPath } from "url"; 3 | import { FlatCompat } from "@eslint/eslintrc"; 4 | 5 | const __filename = fileURLToPath(import.meta.url); 6 | const __dirname = dirname(__filename); 7 | 8 | const compat = new FlatCompat({ 9 | baseDirectory: __dirname, 10 | }); 11 | 12 | const eslintConfig = [...compat.extends("next/core-web-vitals", "next/typescript")]; 13 | 14 | export default eslintConfig; 15 | -------------------------------------------------------------------------------- /examples/bugs/gh-219/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | 3 | export default { 4 | content: [ 5 | "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", 6 | "./src/components/**/*.{js,ts,jsx,tsx,mdx}", 7 | "./src/app/**/*.{js,ts,jsx,tsx,mdx}", 8 | ], 9 | theme: { 10 | extend: { 11 | colors: { 12 | background: "var(--background)", 13 | foreground: "var(--foreground)", 14 | }, 15 | }, 16 | }, 17 | plugins: [], 18 | } satisfies Config; 19 | -------------------------------------------------------------------------------- /examples/middleware/wrangler.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "node_modules/wrangler/config-schema.json", 3 | "main": ".open-next/worker.js", 4 | "name": "middleware", 5 | "compatibility_date": "2024-12-30", 6 | "compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"], 7 | "assets": { 8 | "directory": ".open-next/assets", 9 | "binding": "ASSETS" 10 | }, 11 | "vars": { 12 | "MY_VAR": "my-var" 13 | }, 14 | "kv_namespaces": [{ "binding": "MY_KV", "id": "" }] 15 | } 16 | -------------------------------------------------------------------------------- /examples/bugs/gh-223/app/api/image/route.ts: -------------------------------------------------------------------------------- 1 | import { NextRequest, NextResponse } from "next/server"; 2 | 3 | import { getImageUrl } from "../../../src/utils/s3Bucket"; 4 | 5 | export async function GET(request: NextRequest) { 6 | const searchParams = request.nextUrl.searchParams; 7 | const fileName = searchParams.get("fileName"); 8 | return NextResponse.json( 9 | { 10 | image: fileName ? await getImageUrl(fileName) : "", 11 | }, 12 | { 13 | status: 200, 14 | } 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /examples/create-next-app/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | 3 | const config: Config = { 4 | content: [ 5 | "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", 6 | "./src/components/**/*.{js,ts,jsx,tsx,mdx}", 7 | "./src/app/**/*.{js,ts,jsx,tsx,mdx}", 8 | ], 9 | theme: { 10 | extend: { 11 | colors: { 12 | background: "var(--background)", 13 | foreground: "var(--foreground)", 14 | }, 15 | }, 16 | }, 17 | plugins: [], 18 | }; 19 | export default config; 20 | -------------------------------------------------------------------------------- /examples/vercel-blog-starter/public/favicon/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Next.js", 3 | "short_name": "Next.js", 4 | "icons": [ 5 | { 6 | "src": "/favicons/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/favicons/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#000000", 17 | "background_color": "#000000", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/src/pages/fallback-intercepted/ssg.tsx: -------------------------------------------------------------------------------- 1 | import type { InferGetStaticPropsType } from "next"; 2 | 3 | export function getStaticProps() { 4 | return { 5 | props: { 6 | message: "This is a static ssg page.", 7 | }, 8 | }; 9 | } 10 | 11 | export default function Page({ message }: InferGetStaticPropsType) { 12 | return ( 13 |
14 |

Static Fallback Page

15 |

{message}

16 |
17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/components/ping.tsx: -------------------------------------------------------------------------------- 1 | export function Ping() { 2 | return ( 3 |
4 |
5 | 6 | 7 | 8 | 9 |
10 |
11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /examples/prisma/wrangler.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "node_modules/wrangler/config-schema.json", 3 | "main": ".open-next/worker.js", 4 | "name": "api", 5 | "compatibility_date": "2024-12-30", 6 | "compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"], 7 | "assets": { 8 | "directory": ".open-next/assets", 9 | "binding": "ASSETS" 10 | }, 11 | "d1_databases": [ 12 | { 13 | "binding": "DB", 14 | "database_name": "db", 15 | "database_id": "" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /examples/e2e/app-router/e2e/isr.revalidate.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from "@playwright/test"; 2 | 3 | test("Test revalidate", async ({ request }) => { 4 | const result = await request.get("/api/isr"); 5 | 6 | expect(result.status()).toEqual(200); 7 | const json = await result.json(); 8 | const body = json.body; 9 | 10 | expect(json.status).toEqual(200); 11 | expect(body.result).toEqual(true); 12 | expect(body.cacheControl).toEqual("private, no-cache, no-store, max-age=0, must-revalidate"); 13 | }); 14 | -------------------------------------------------------------------------------- /examples/e2e/app-router/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | 3 | const config: Config = { 4 | content: ["./app/**/*.{js,ts,jsx,tsx,mdx}", "../../examples/shared/**/*.{jsx,tsx}"], 5 | theme: { 6 | extend: { 7 | backgroundImage: { 8 | "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", 9 | "gradient-conic": "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", 10 | }, 11 | }, 12 | }, 13 | plugins: [], 14 | }; 15 | export default config; 16 | -------------------------------------------------------------------------------- /examples/e2e/experimental/next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from "next"; 2 | 3 | const nextConfig: NextConfig = { 4 | /* config options here */ 5 | cleanDistDir: true, 6 | output: "standalone", 7 | eslint: { 8 | ignoreDuringBuilds: true, 9 | }, 10 | typescript: { 11 | // Ignore type errors during build for now, we'll need to figure this out later 12 | ignoreBuildErrors: true, 13 | }, 14 | experimental: { 15 | cacheComponents: true, 16 | }, 17 | }; 18 | 19 | export default nextConfig; 20 | -------------------------------------------------------------------------------- /examples/e2e/experimental/src/components/dynamic.tsx: -------------------------------------------------------------------------------- 1 | import { setTimeout } from "node:timers/promises"; 2 | import { headers } from "next/headers"; 3 | 4 | export async function DynamicComponent() { 5 | const _headers = await headers(); 6 | // Simulate a delay to mimic server-side calls 7 | await setTimeout(1000, new Date().toString()); 8 | return ( 9 |
10 |

Dynamic Component

11 |

This component should be SSR

12 |

{_headers.get("referer")}

13 |
14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/src/pages/ssg/index.tsx: -------------------------------------------------------------------------------- 1 | import type { InferGetStaticPropsType } from "next"; 2 | 3 | export async function getStaticProps() { 4 | return { 5 | props: { 6 | time: new Date().toISOString(), 7 | }, 8 | }; 9 | } 10 | 11 | export default function Page({ time }: InferGetStaticPropsType) { 12 | return ( 13 |
14 |
15 | Time: {time} 16 |
17 | Home 18 |
19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/lib/delay.ts: -------------------------------------------------------------------------------- 1 | // Times are in milliseconds 2 | export const delayShippingEstimate = 2000; 3 | export const delayRecommendedProducts = 5000; 4 | export const delayReviews = 6000; 5 | 6 | export async function withDelay( 7 | promise: Promise, 8 | delay: number, 9 | ): Promise { 10 | // Ensure we throw if this throws 11 | const ret = await promise; 12 | return new Promise((resolve) => { 13 | setTimeout(() => { 14 | resolve(ret); 15 | }, delay); 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | 3 | const config: Config = { 4 | content: ["./app/**/*.{js,ts,jsx,tsx,mdx}", "../../examples/shared/**/*.{jsx,tsx}"], 5 | theme: { 6 | extend: { 7 | backgroundImage: { 8 | "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", 9 | "gradient-conic": "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", 10 | }, 11 | }, 12 | }, 13 | plugins: [], 14 | }; 15 | export default config; 16 | -------------------------------------------------------------------------------- /examples/playground15/e2e/image.test.ts: -------------------------------------------------------------------------------- 1 | import { test, expect } from "@playwright/test"; 2 | 3 | test.describe("next/image with trailing slash", () => { 4 | test("next/image with trailing slash", async ({ page }) => { 5 | await page.goto("/image"); 6 | await expect(page.getByAltText("Picture of Tomine")).toBeVisible(); 7 | // The trailing slash should only be there if trailingSlash is enabled in next.config.ts 8 | expect(await page.getAttribute("img", "src")).toMatch(/^\/_next\/image\//); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/api/after/revalidate/route.ts: -------------------------------------------------------------------------------- 1 | import { revalidateTag } from "next/cache"; 2 | import { NextResponse, after } from "next/server"; 3 | 4 | export function POST() { 5 | after( 6 | () => 7 | new Promise((resolve) => 8 | setTimeout(() => { 9 | revalidateTag("date", { 10 | // We want to expire the "date" tag immediately 11 | expire: 0, 12 | }); 13 | resolve(); 14 | }, 5000) 15 | ) 16 | ); 17 | 18 | return NextResponse.json({ success: true }); 19 | } 20 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/methods/post/formdata/route.ts: -------------------------------------------------------------------------------- 1 | export async function POST(request: Request) { 2 | const formData = await request.formData(); 3 | const name = formData.get("name"); 4 | const email = formData.get("email"); 5 | if (name === "OpenNext [] () %&#!%$#" && email === "opennext@opennext.com") { 6 | return Response.json( 7 | { 8 | message: "ok", 9 | }, 10 | { 11 | status: 202, 12 | } 13 | ); 14 | } 15 | return Response.json({ message: "forbidden" }, { status: 403 }); 16 | } 17 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/components/product-rating.tsx: -------------------------------------------------------------------------------- 1 | import { StarIcon } from '@heroicons/react/24/solid'; 2 | import clsx from 'clsx'; 3 | 4 | export const ProductRating = ({ rating }: { rating: number }) => { 5 | return ( 6 |
7 | {Array.from({ length: 5 }).map((_, i) => { 8 | return ( 9 | 13 | ); 14 | })} 15 |
16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /examples/middleware/e2e/cloudflare-context.spec.ts: -------------------------------------------------------------------------------- 1 | import { test, expect } from "@playwright/test"; 2 | 3 | test.describe("middleware/cloudflare-context", () => { 4 | test("middlewares have access to the cloudflare context", async ({ page }) => { 5 | await page.goto("/middleware"); 6 | const cloudflareContextHeaderElement = page.getByTestId("cloudflare-context-header"); 7 | expect(await cloudflareContextHeaderElement.textContent()).toContain( 8 | "typeof `cloudflareContext.env` = object" 9 | ); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/src/pages/fallback-intercepted/[...slugs].tsx: -------------------------------------------------------------------------------- 1 | import type { InferGetServerSidePropsType } from "next"; 2 | 3 | export function getServerSideProps() { 4 | return { 5 | props: { 6 | message: "This is a dynamic fallback page.", 7 | }, 8 | }; 9 | } 10 | 11 | export default function Page({ message }: InferGetServerSidePropsType) { 12 | return ( 13 |
14 |

Dynamic Fallback Page

15 |

{message}

16 |
17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/src/pages/isr/index.tsx: -------------------------------------------------------------------------------- 1 | import type { InferGetStaticPropsType } from "next"; 2 | import Link from "next/link"; 3 | 4 | export async function getStaticProps() { 5 | return { 6 | props: { 7 | time: new Date().toISOString(), 8 | }, 9 | revalidate: 10, 10 | }; 11 | } 12 | 13 | export default function Page({ time }: InferGetStaticPropsType) { 14 | return ( 15 |
16 |
Time: {time}
17 | Home 18 |
19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /examples/ssg-app/app/page.tsx: -------------------------------------------------------------------------------- 1 | import styles from "./page.module.css"; 2 | import { getCloudflareContext } from "@opennextjs/cloudflare"; 3 | 4 | export default async function Home() { 5 | const cloudflareContext = await getCloudflareContext({ 6 | async: true, 7 | }); 8 | 9 | return ( 10 |
11 |
12 |

Hello from a Statically generated page

13 |

{cloudflareContext.env.MY_SECRET}

14 |
15 |
16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /packages/cloudflare/src/cli/build/utils/version.ts: -------------------------------------------------------------------------------- 1 | import { createRequire } from "node:module"; 2 | import { join } from "node:path"; 3 | import { fileURLToPath, URL } from "node:url"; 4 | 5 | export function getVersion() { 6 | const require = createRequire(import.meta.url); 7 | const __dirname = fileURLToPath(new URL(".", import.meta.url)); 8 | const pkgJson = require(join(__dirname, "../../../../package.json")); 9 | return { 10 | cloudflare: pkgJson.version, 11 | aws: pkgJson.dependencies["@opennextjs/aws"], 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/revalidate-tag/layout.tsx: -------------------------------------------------------------------------------- 1 | import { unstable_cache } from "next/cache"; 2 | import type { ReactNode } from "react"; 3 | 4 | export default async function Layout({ children }: { children: ReactNode }) { 5 | const fakeFetch = unstable_cache(async () => new Date().getTime(), ["fakeFetch"], { 6 | tags: ["revalidate"], 7 | }); 8 | const fetchedDate = await fakeFetch(); 9 | return ( 10 |
11 |
Fetched time: {new Date(fetchedDate).toISOString()}
12 | {children} 13 |
14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /examples/playground15/e2e/cloudflare.spec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Cloudflare specific tests. 3 | * 4 | * The tests in this file do not run on Node (`next dev`). 5 | */ 6 | 7 | import { test, expect } from "@playwright/test"; 8 | 9 | test.describe("playground/cloudflare", () => { 10 | test("NextConfig", async ({ page }) => { 11 | const res = await page.request.get("/api/buildid"); 12 | expect(res.status()).toEqual(200); 13 | const { nextConfig } = await res.json(); 14 | expect(nextConfig.output).toEqual("standalone"); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /examples/overrides/memory-queue/app/page.tsx: -------------------------------------------------------------------------------- 1 | import styles from "./page.module.css"; 2 | 3 | export const revalidate = 5; 4 | 5 | export default async function Home() { 6 | // We purposefully wait for 2 seconds to allow deduplication to occur 7 | await new Promise((resolve) => setTimeout(resolve, 2000)); 8 | return ( 9 |
10 |
11 |

Hello from a Statically generated page

12 |

{Date.now()}

13 |
14 |
15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /examples/create-next-app/src/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --background: #ffffff; 7 | --foreground: #171717; 8 | } 9 | 10 | @media (prefers-color-scheme: dark) { 11 | :root { 12 | --background: #0a0a0a; 13 | --foreground: #ededed; 14 | } 15 | } 16 | 17 | body { 18 | color: var(--foreground); 19 | background: var(--background); 20 | font-family: Arial, Helvetica, sans-serif; 21 | } 22 | 23 | @layer utilities { 24 | .text-balance { 25 | text-wrap: balance; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/overrides/r2-incremental-cache/app/page.tsx: -------------------------------------------------------------------------------- 1 | import styles from "./page.module.css"; 2 | 3 | export const revalidate = 5; 4 | 5 | export default async function Home() { 6 | // We purposefully wait for 2 seconds to allow deduplication to occur 7 | await new Promise((resolve) => setTimeout(resolve, 2000)); 8 | return ( 9 |
10 |
11 |

Hello from a Statically generated page

12 |

{Date.now()}

13 |
14 |
15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /examples/playground14/pages/head.tsx: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | 3 | export function getServerSideProps() { 4 | return { 5 | props: { 6 | time: new Date().toISOString(), 7 | }, 8 | }; 9 | } 10 | export default function Page({ time }) { 11 | return ( 12 |
13 | 14 | SSR Head 15 | 16 | 17 | 18 |
19 | Time: {time} 20 |
21 |
22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /examples/playground15/pages/head.tsx: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | 3 | export function getServerSideProps() { 4 | return { 5 | props: { 6 | time: new Date().toISOString(), 7 | }, 8 | }; 9 | } 10 | export default function Page({ time }) { 11 | return ( 12 |
13 | 14 | SSR Head 15 | 16 | 17 | 18 |
19 | Time: {time} 20 |
21 |
22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import "./globals.css"; 2 | 3 | import type { Metadata } from "next"; 4 | import { Inter } from "next/font/google"; 5 | 6 | const inter = Inter({ subsets: ["latin"] }); 7 | 8 | export const metadata: Metadata = { 9 | title: "Nextjs App Router", 10 | description: "Generated by create next app", 11 | }; 12 | 13 | export default function RootLayout({ children }: { children: React.ReactNode }) { 14 | return ( 15 | 16 | {children} 17 | 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/src/pages/ssr/index.tsx: -------------------------------------------------------------------------------- 1 | import type { InferGetServerSidePropsType } from "next"; 2 | 3 | export async function getServerSideProps() { 4 | return { 5 | props: { 6 | time: new Date().toISOString(), 7 | envVar: process.env.SOME_PROD_VAR, 8 | }, 9 | }; 10 | } 11 | 12 | export default function Page({ time, envVar }: InferGetServerSidePropsType) { 13 | return ( 14 | <> 15 |

SSR

16 |
Time: {time}
17 |
Env: {envVar}
18 | 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /examples/e2e/app-router/e2e/dynamic.catch-all.hypen.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from "@playwright/test"; 2 | 3 | // https://github.com/opennextjs/opennextjs-cloudflare/issues/942 4 | test("Dynamic catch-all API route with hyphen param", async ({ request }) => { 5 | const res = await request.get("/api/auth/opennext/is/really/cool"); 6 | expect(res.status()).toBe(200); 7 | expect(res.headers()["content-type"]).toBe("application/json"); 8 | const json = await res.json(); 9 | expect(json).toStrictEqual({ slugs: ["opennext", "is", "really", "cool"] }); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/cloudflare/src/cli/utils/ask-confirmation.ts: -------------------------------------------------------------------------------- 1 | import { randomUUID } from "node:crypto"; 2 | 3 | import Enquirer from "enquirer"; 4 | 5 | export async function askConfirmation(message: string): Promise { 6 | const questionName = randomUUID(); 7 | 8 | const enquirerAnswersObject = await Enquirer.prompt>({ 9 | name: questionName, 10 | message, 11 | type: "confirm", 12 | initial: "y", 13 | }); 14 | 15 | console.log(""); 16 | 17 | const answer = !!enquirerAnswersObject[questionName]; 18 | return answer; 19 | } 20 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/e2e/headers.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from "@playwright/test"; 2 | 3 | test("does not set x-opennext-requestid header on cache interceptor response", async ({ page }) => { 4 | const result = await page.goto("/ssg"); 5 | expect(result).toBeDefined(); 6 | expect(result?.status()).toBe(200); 7 | const headers = result?.headers(); 8 | 9 | // This header should not be defined even when its a cached response from the cache interception in the external middleware 10 | expect(headers?.["x-opennext-requestid"]).toBeUndefined(); 11 | }); 12 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/components/product-currency-symbol.tsx: -------------------------------------------------------------------------------- 1 | import { toFormat, type Dinero } from 'dinero.js'; 2 | 3 | export const ProductCurrencySymbol = ({ 4 | dinero, 5 | }: { 6 | dinero: Dinero; 7 | }) => { 8 | let symbol = ''; 9 | switch (toFormat(dinero, ({ currency }) => currency.code)) { 10 | case 'GBP': { 11 | symbol = '£'; 12 | break; 13 | } 14 | 15 | case 'EUR': { 16 | symbol = '€'; 17 | break; 18 | } 19 | 20 | default: { 21 | symbol = '$'; 22 | break; 23 | } 24 | } 25 | 26 | return <>{symbol}; 27 | }; 28 | -------------------------------------------------------------------------------- /packages/cloudflare/src/utils/get-package-templates-dir-path.ts: -------------------------------------------------------------------------------- 1 | import path from "node:path"; 2 | import url from "node:url"; 3 | 4 | const __filename = url.fileURLToPath(import.meta.url); 5 | const __dirname = path.dirname(__filename); 6 | const templatesDirPath = path.join(__dirname, "/../../templates"); 7 | 8 | /** 9 | * Utility for getting the resolved path to the package's templates directory 10 | * 11 | * @returns the resolved path of the templates directory 12 | */ 13 | export function getPackageTemplatesDirPath(): string { 14 | return templatesDirPath; 15 | } 16 | -------------------------------------------------------------------------------- /examples/bugs/gh-223/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | import { Inter } from "next/font/google"; 3 | import "./globals.css"; 4 | 5 | const inter = Inter({ subsets: ["latin"] }); 6 | 7 | export const metadata: Metadata = { 8 | title: "Create Next App", 9 | description: "Generated by create next app", 10 | }; 11 | 12 | export default function RootLayout({ 13 | children, 14 | }: Readonly<{ 15 | children: React.ReactNode; 16 | }>) { 17 | return ( 18 | 19 | {children} 20 | 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /examples/bugs/gh-223/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | 3 | const config: Config = { 4 | content: [ 5 | "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", 6 | "./src/components/**/*.{js,ts,jsx,tsx,mdx}", 7 | "./src/app/**/*.{js,ts,jsx,tsx,mdx}", 8 | ], 9 | theme: { 10 | extend: { 11 | backgroundImage: { 12 | "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", 13 | "gradient-conic": "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", 14 | }, 15 | }, 16 | }, 17 | plugins: [], 18 | }; 19 | export default config; 20 | -------------------------------------------------------------------------------- /examples/e2e/experimental/src/app/use-cache/isr/page.tsx: -------------------------------------------------------------------------------- 1 | import { FullyCachedComponent, ISRComponent } from "@/components/cached"; 2 | import { Suspense } from "react"; 3 | 4 | export default async function Page() { 5 | // Not working for now, need a patch in next to disable full revalidation during ISR revalidation 6 | return ( 7 |
8 |

Cache

9 | Loading...

}> 10 | 11 |
12 | Loading...

}> 13 | 14 |
15 |
16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /examples/middleware/app/page.tsx: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | 3 | export default function Home() { 4 | return ( 5 |
6 |

Index

7 |

8 | Go to about page (will redirect) 9 |

10 |

11 | Go to another page (will rewrite) 12 |

13 |

14 | Go to about 2 page (no redirect or rewrite) 15 |

16 |

17 | Go to middleware page (using NextResponse.next()) 18 |

19 |
20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/app/ssr/page.tsx: -------------------------------------------------------------------------------- 1 | import { headers } from "next/headers"; 2 | 3 | async function getTime() { 4 | const res = await new Promise((resolve) => { 5 | setTimeout(() => { 6 | resolve(new Date().toISOString()); 7 | }, 1500); 8 | }); 9 | return res; 10 | } 11 | 12 | export default async function SSR() { 13 | const time = await getTime(); 14 | const headerList = await headers(); 15 | return ( 16 |
17 |

Time: {time}

18 |
{headerList.get("host")}
19 |
Env: {process.env.SOME_ENV_VAR}
20 |
21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /examples/playground14/e2e/head.spec.ts: -------------------------------------------------------------------------------- 1 | import { test, expect } from "@playwright/test"; 2 | 3 | test.describe("head properly populated", () => { 4 | test("should properly populate the ", async ({ page }) => { 5 | await page.goto("/head"); 6 | const title = await page.title(); 7 | const description = await page.locator('meta[name="description"]').getAttribute("content"); 8 | const favicon = await page.locator('link[rel="icon"]').getAttribute("href"); 9 | expect(title).toBe("SSR Head"); 10 | expect(description).toBe("SSR"); 11 | expect(favicon).toBe("/favicon.ico"); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /examples/playground15/app/other-app/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import testImage from "../../public/test.jpg"; 3 | import Image from "next/image"; 4 | 5 | export default function Page() { 6 | return ( 7 | <> 8 |

other app

9 | test 10 |

{process.env.NEXT_DEPLOYMENT_ID}

11 | 12 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /examples/playground15/e2e/head.spec.ts: -------------------------------------------------------------------------------- 1 | import { test, expect } from "@playwright/test"; 2 | 3 | test.describe("head properly populated", () => { 4 | test("should properly populate the ", async ({ page }) => { 5 | await page.goto("/head"); 6 | const title = await page.title(); 7 | const description = await page.locator('meta[name="description"]').getAttribute("content"); 8 | const favicon = await page.locator('link[rel="icon"]').getAttribute("href"); 9 | expect(title).toBe("SSR Head"); 10 | expect(description).toBe("SSR"); 11 | expect(favicon).toBe("/favicon.ico"); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /examples/e2e/shared/components/Album/index.tsx: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | 3 | import type { Album } from "../../api/index"; 4 | import Song from "./Song"; 5 | 6 | type Props = { 7 | album: Album; 8 | }; 9 | export default function Album({ album }: Props) { 10 | return ( 11 |
12 |
Album: {album.album}
13 |
Artist: {album.artist}
14 | {album.songs.map((song) => ( 15 | 16 | 17 | 18 | ))} 19 |
20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import "./globals.css"; 2 | 3 | import type { Metadata } from "next"; 4 | import { Inter } from "next/font/google"; 5 | 6 | const inter = Inter({ subsets: ["latin"] }); 7 | 8 | export const metadata: Metadata = { 9 | title: "Nextjs App Router", 10 | description: "Generated by create next app", 11 | }; 12 | 13 | export default function RootLayout({ children }: { children: React.ReactNode }) { 14 | return ( 15 | 16 | 17 |
Header
18 | {children} 19 | 20 | 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /examples/e2e/shared/components/Album/Song.tsx: -------------------------------------------------------------------------------- 1 | import type { Song } from "../../api/index"; 2 | 3 | type Props = { 4 | song: Song; 5 | play?: boolean; 6 | }; 7 | export default function Song({ song, play }: Props) { 8 | return ( 9 |
10 |
Song: {song.title}
11 |
Year: {song.year}
12 | {play && ( 13 | 20 | )} 21 |
22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /packages/cloudflare/src/cli/build/utils/test-patch.ts: -------------------------------------------------------------------------------- 1 | import { patchCode } from "@opennextjs/aws/build/patch/astCodePatcher.js"; 2 | import { createPatch } from "diff"; 3 | 4 | /** 5 | * Compute the diff resulting of applying the `rule` to `src`. 6 | * 7 | * @param filename Filename used in the patch output 8 | * @param src Content of the source code 9 | * @param rule ASTgrep rule 10 | * @returns diff in unified diff format 11 | */ 12 | export function computePatchDiff(filename: string, src: string, rule: string): string { 13 | const dst = patchCode(src, rule); 14 | return createPatch(filename, src, dst); 15 | } 16 | -------------------------------------------------------------------------------- /packages/cloudflare/src/cli/project-options.ts: -------------------------------------------------------------------------------- 1 | import type { WranglerTarget } from "./utils/run-wrangler.js"; 2 | 3 | export type ProjectOptions = { 4 | // Next app root folder 5 | sourceDir: string; 6 | // Whether the Next.js build should be skipped (i.e. if the `.next` dir is already built) 7 | skipNextBuild: boolean; 8 | // Whether the check to see if a wrangler config file exists should be skipped 9 | skipWranglerConfigCheck: boolean; 10 | // Whether minification of the worker should be enabled 11 | minify: boolean; 12 | populateCache?: { mode: WranglerTarget; onlyPopulateWithoutBuilding: boolean }; 13 | }; 14 | -------------------------------------------------------------------------------- /create-cloudflare/next/src/app/globals.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss"; 2 | 3 | :root { 4 | --background: #ffffff; 5 | --foreground: #171717; 6 | } 7 | 8 | @theme inline { 9 | --color-background: var(--background); 10 | --color-foreground: var(--foreground); 11 | --font-sans: var(--font-geist-sans); 12 | --font-mono: var(--font-geist-mono); 13 | } 14 | 15 | @media (prefers-color-scheme: dark) { 16 | :root { 17 | --background: #0a0a0a; 18 | --foreground: #ededed; 19 | } 20 | } 21 | 22 | body { 23 | background: var(--background); 24 | color: var(--foreground); 25 | font-family: Arial, Helvetica, sans-serif; 26 | } 27 | -------------------------------------------------------------------------------- /examples/overrides/memory-queue/wrangler.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "node_modules/wrangler/config-schema.json", 3 | "main": ".open-next/worker.js", 4 | "name": "memory-queue", 5 | "compatibility_date": "2025-02-04", 6 | "compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"], 7 | "assets": { 8 | "directory": ".open-next/assets", 9 | "binding": "ASSETS" 10 | }, 11 | "kv_namespaces": [ 12 | { 13 | "binding": "NEXT_INC_CACHE_KV", 14 | "id": "" 15 | } 16 | ], 17 | "services": [ 18 | { 19 | "binding": "WORKER_SELF_REFERENCE", 20 | "service": "memory-queue" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/config-redirect/page.tsx: -------------------------------------------------------------------------------- 1 | export default function RedirectDestination() { 2 | return ( 3 |
4 |

I was redirected from next.config.js

5 |

/next-config-redirect => /config-redirect

6 | 7 | /next-config-redirect-encoding?q=äöå€ 8 | 9 | 13 | /next-config-redirect-encoding?q=%C3%A4%C3%B6%C3%A5%E2%82%AC 14 | 15 |
16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --foreground-rgb: 0, 0, 0; 7 | --background-start-rgb: 214, 219, 220; 8 | --background-end-rgb: 255, 255, 255; 9 | } 10 | 11 | @media (prefers-color-scheme: dark) { 12 | :root { 13 | --foreground-rgb: 255, 255, 255; 14 | --background-start-rgb: 0, 0, 0; 15 | --background-end-rgb: 0, 0, 0; 16 | } 17 | } 18 | 19 | body { 20 | color: rgb(var(--foreground-rgb)); 21 | background: linear-gradient(to bottom, transparent, rgb(var(--background-end-rgb))) 22 | rgb(var(--background-start-rgb)); 23 | } 24 | -------------------------------------------------------------------------------- /examples/prisma/src/app/page.tsx: -------------------------------------------------------------------------------- 1 | import styles from "./page.module.css"; 2 | import { getDb } from "@/lib/db"; 3 | 4 | export const dynamic = "force-dynamic"; 5 | 6 | export default async function Home() { 7 | const db = getDb(); 8 | const allUsers = await db.users.findMany(); 9 | return ( 10 |
11 |
    12 | {allUsers.map((user) => ( 13 |
  • 14 | {user.name} 15 |
    16 | {user.email} 17 |
  • 18 | ))} 19 |
20 |
21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --foreground-rgb: 0, 0, 0; 7 | --background-start-rgb: 214, 219, 220; 8 | --background-end-rgb: 255, 255, 255; 9 | } 10 | 11 | @media (prefers-color-scheme: dark) { 12 | :root { 13 | --foreground-rgb: 255, 255, 255; 14 | --background-start-rgb: 0, 0, 0; 15 | --background-end-rgb: 0, 0, 0; 16 | } 17 | } 18 | 19 | body { 20 | color: rgb(var(--foreground-rgb)); 21 | background: linear-gradient(to bottom, transparent, rgb(var(--background-end-rgb))) 22 | rgb(var(--background-start-rgb)); 23 | } 24 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/methods/post/cookies/route.ts: -------------------------------------------------------------------------------- 1 | import { cookies } from "next/headers"; 2 | 3 | export async function POST(request: Request) { 4 | const formData = await request.formData(); 5 | const username = formData.get("username"); 6 | const password = formData.get("password"); 7 | if (username === "hakuna" && password === "matata") { 8 | (await cookies()).set("auth_session", "SUPER_SECRET_SESSION_ID_1234"); 9 | return Response.json( 10 | { 11 | message: "ok", 12 | }, 13 | { 14 | status: 202, 15 | } 16 | ); 17 | } 18 | return Response.json({ message: "you must login" }, { status: 401 }); 19 | } 20 | -------------------------------------------------------------------------------- /examples/vercel-blog-starter/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | 38 | #cf workers 39 | .wrangler 40 | .worker-next -------------------------------------------------------------------------------- /.github/workflows/checks.yml: -------------------------------------------------------------------------------- 1 | name: Code checks 2 | 3 | on: 4 | push: 5 | branches: [main, experimental] 6 | pull_request: 7 | 8 | jobs: 9 | checks: 10 | name: ${{ matrix.script }} 11 | runs-on: ubuntu-latest 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | script: ["prettier:check", "lint:check", "ts:check", "test"] 16 | steps: 17 | - name: Check out code 18 | uses: actions/checkout@v4 19 | 20 | - name: Install Dependencies 21 | uses: ./.github/actions/install-dependencies 22 | 23 | - name: ${{ matrix.script }} 24 | run: pnpm run ${{ matrix.script }} 25 | -------------------------------------------------------------------------------- /examples/bugs/gh-223/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/revalidate-path/page.tsx: -------------------------------------------------------------------------------- 1 | export default async function Page() { 2 | const responseSST = await fetch("https://sst.dev", { 3 | next: { 4 | tags: ["path"], 5 | }, 6 | }); 7 | // This one doesn't have a tag 8 | const responseOpenNext = await fetch("https://opennext.js.org"); 9 | const reqIdSst = responseSST.headers.get("x-amz-cf-id"); 10 | const dateInOpenNext = responseOpenNext.headers.get("date"); 11 | return ( 12 |
13 |

Request id from SST

14 |

RequestID: {reqIdSst}

15 |

Date from from OpenNext

16 |

Date: {dateInOpenNext}

17 |
18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /examples/overrides/memory-queue/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | import "./globals.css"; 3 | 4 | import { getCloudflareContext } from "@opennextjs/cloudflare"; 5 | 6 | export const metadata: Metadata = { 7 | title: "SSG App", 8 | description: "An app in which all the routes are SSG'd", 9 | }; 10 | 11 | export default async function RootLayout({ 12 | children, 13 | }: Readonly<{ 14 | children: React.ReactNode; 15 | }>) { 16 | const cloudflareContext = await getCloudflareContext({ 17 | async: true, 18 | }); 19 | 20 | return ( 21 | 22 | {children} 23 | 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /examples/create-next-app/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/components/product-used-price.tsx: -------------------------------------------------------------------------------- 1 | import { Product } from '#/types/product'; 2 | import { dinero, toUnit, up, type DineroSnapshot } from 'dinero.js'; 3 | 4 | export const ProductUsedPrice = ({ 5 | usedPrice: usedPriceRaw, 6 | }: { 7 | usedPrice: Product['usedPrice']; 8 | }) => { 9 | const usedPrice = dinero(usedPriceRaw as DineroSnapshot); 10 | 11 | return ( 12 |
13 |
More buying choices
14 |
15 | ${toUnit(usedPrice, { digits: 0, round: up })} (used) 16 |
17 |
18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | /.yarn 8 | 9 | # testing 10 | /coverage 11 | playwright-report 12 | test-results 13 | 14 | # next.js 15 | /.next/ 16 | /out/ 17 | 18 | # production 19 | /build 20 | 21 | # misc 22 | .DS_Store 23 | *.pem 24 | 25 | # debug 26 | npm-debug.log* 27 | yarn-debug.log* 28 | yarn-error.log* 29 | .pnpm-debug.log* 30 | 31 | # local env files 32 | .env* 33 | !.env*.example 34 | 35 | # vercel 36 | .vercel 37 | 38 | # typescript 39 | *.tsbuildinfo 40 | next-env.d.ts 41 | -------------------------------------------------------------------------------- /examples/overrides/d1-tag-next/app/components/revalidationButtons.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { revalidateTagAction, revalidatePathAction } from "../action"; 4 | 5 | export default function RevalidationButtons() { 6 | return ( 7 |
8 | 16 | 17 | 25 |
26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /examples/overrides/kv-tag-next/app/components/revalidationButtons.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { revalidateTagAction, revalidatePathAction } from "../action"; 4 | 5 | export default function RevalidationButtons() { 6 | return ( 7 |
8 | 16 | 17 | 25 |
26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /examples/overrides/r2-incremental-cache/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | import "./globals.css"; 3 | 4 | import { getCloudflareContext } from "@opennextjs/cloudflare"; 5 | 6 | export const metadata: Metadata = { 7 | title: "SSG App", 8 | description: "An app in which all the routes are SSG'd", 9 | }; 10 | 11 | export default async function RootLayout({ 12 | children, 13 | }: Readonly<{ 14 | children: React.ReactNode; 15 | }>) { 16 | const cloudflareContext = await getCloudflareContext({ 17 | async: true, 18 | }); 19 | 20 | return ( 21 | 22 | {children} 23 | 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/albums/[album]/[song]/page.tsx: -------------------------------------------------------------------------------- 1 | import { getSong } from "@example/shared/api"; 2 | 3 | type Props = { 4 | params: Promise<{ 5 | album: string; 6 | song: string; 7 | }>; 8 | }; 9 | export default async function Song(props: Props) { 10 | const params = await props.params; 11 | const song = await getSong(params.album, params.song); 12 | 13 | return ( 14 |
15 |

Not Modal

16 | {decodeURIComponent(params.album)} 17 | 23 |
24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /examples/e2e/shared/components/Filler/index.tsx: -------------------------------------------------------------------------------- 1 | interface FillerProps { 2 | // Size in kb of the filler 3 | size: number; 4 | } 5 | 6 | //This component is there to demonstrate how you could bypass streaming buffering in aws lambda. 7 | //Hopefully, this will be fixed in the future and this component will be removed. 8 | // https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/issues/94 9 | export default function Filler({ size }: FillerProps) { 10 | const str = "a".repeat(size * 1024); 11 | const byteSize = new TextEncoder().encode(str).length; 12 | return ; 13 | } 14 | -------------------------------------------------------------------------------- /examples/playground15/next.config.ts: -------------------------------------------------------------------------------- 1 | import { initOpenNextCloudflareForDev, getDeploymentId } from "@opennextjs/cloudflare"; 2 | import { NextConfig } from "next"; 3 | 4 | initOpenNextCloudflareForDev(); 5 | 6 | const nextConfig: NextConfig = { 7 | typescript: { ignoreBuildErrors: true }, 8 | eslint: { ignoreDuringBuilds: true }, 9 | experimental: { 10 | // Generate source map to validate the fix for opennextjs/opennextjs-cloudflare#341 11 | serverSourceMaps: true, 12 | }, 13 | deploymentId: getDeploymentId(), 14 | trailingSlash: true, 15 | images: { 16 | formats: ["image/avif", "image/webp"], 17 | }, 18 | }; 19 | 20 | export default nextConfig; 21 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/e2e/trailing.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from "@playwright/test"; 2 | 3 | test("trailingSlash redirect", async ({ page }) => { 4 | const response = await page.goto("/ssr"); 5 | 6 | expect(response?.request().redirectedFrom()?.url()).toMatch(/\/ssr$/); 7 | expect(response?.request().url()).toMatch(/\/ssr\/$/); 8 | }); 9 | 10 | test("trailingSlash redirect with search parameters", async ({ page }) => { 11 | const response = await page.goto("/ssr?happy=true"); 12 | 13 | expect(response?.request().redirectedFrom()?.url()).toMatch(/\/ssr\?happy=true$/); 14 | expect(response?.request().url()).toMatch(/\/ssr\/\?happy=true$/); 15 | }); 16 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/app/albums/[album]/[song]/page.tsx: -------------------------------------------------------------------------------- 1 | import { getSong } from "@example/shared/api"; 2 | 3 | type Props = { 4 | params: Promise<{ 5 | album: string; 6 | song: string; 7 | }>; 8 | }; 9 | export default async function Song(props: Props) { 10 | const params = await props.params; 11 | const song = await getSong(params.album, params.song); 12 | 13 | return ( 14 |
15 |

Not Modal

16 | {decodeURIComponent(params.album)} 17 | 23 |
24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/e2e/i18n.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from "@playwright/test"; 2 | 3 | test("Next config headers with i18n", async ({ page }) => { 4 | const responsePromise = page.waitForResponse((response) => { 5 | return response.status() === 200; 6 | }); 7 | await page.goto("/"); 8 | 9 | const response = await responsePromise; 10 | // Response header should be set 11 | const headers = response.headers(); 12 | // Headers from next.config.js should be set 13 | expect(headers["x-custom-header"]).toEqual("my custom header value"); 14 | 15 | // Headers from middleware should be set 16 | expect(headers["x-from-middleware"]).toEqual("true"); 17 | }); 18 | -------------------------------------------------------------------------------- /examples/overrides/static-assets-incremental-cache/app/components/revalidationButtons.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { revalidateTagAction, revalidatePathAction } from "../action"; 4 | 5 | export default function RevalidationButtons() { 6 | return ( 7 |
8 | 16 | 17 | 25 |
26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | .open-next 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | 38 | # playwright 39 | /test-results/ 40 | /playwright-report/ 41 | /blob-report/ 42 | /playwright/.cache/ -------------------------------------------------------------------------------- /examples/middleware/app/middleware/page.tsx: -------------------------------------------------------------------------------- 1 | import { headers } from "next/headers"; 2 | 3 | export default async function MiddlewarePage() { 4 | const cloudflareContextHeader = (await headers()).get("x-cloudflare-context"); 5 | 6 | return ( 7 | <> 8 |

Via middleware

9 |

10 | The value of the x-cloudflare-context header is:
11 | 20 | {cloudflareContextHeader} 21 | 22 |

23 | 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/components/product-estimated-arrival.tsx: -------------------------------------------------------------------------------- 1 | import { add, format, isTomorrow } from 'date-fns'; 2 | 3 | export const ProductEstimatedArrival = ({ 4 | leadTime, 5 | hasDeliveryTime = false, 6 | }: { 7 | leadTime: number; 8 | hasDeliveryTime?: boolean; 9 | }) => { 10 | const date = add(new Date(), { 11 | days: leadTime, 12 | }); 13 | 14 | return ( 15 |
16 | Get it{' '} 17 | 18 | {isTomorrow(date) ? 'tomorrow, ' : null} 19 | {format(date, 'MMM d')} 20 | 21 | {hasDeliveryTime ? <> by 5pm : null} 22 |
23 | ); 24 | }; 25 | -------------------------------------------------------------------------------- /examples/overrides/kv-tag-next/wrangler.e2e.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "node_modules/wrangler/config-schema.json", 3 | "main": ".open-next/worker.js", 4 | "name": "ssg-app", 5 | "compatibility_date": "2025-02-04", 6 | "compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"], 7 | "assets": { 8 | "directory": ".open-next/assets", 9 | "binding": "ASSETS", 10 | }, 11 | "vars": { 12 | "APP_VERSION": "1.2.345", 13 | }, 14 | "kv_namespaces": [ 15 | { 16 | "binding": "NEXT_INC_CACHE_KV", 17 | "id": "INC-CACHE", 18 | "preview_id": "", 19 | }, 20 | { 21 | "binding": "NEXT_TAG_CACHE_KV", 22 | "id": "TAG-CACHE", 23 | }, 24 | ], 25 | } 26 | -------------------------------------------------------------------------------- /examples/e2e/app-router/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | .open-next 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | 38 | # playwright 39 | /test-results/ 40 | /playwright-report/ 41 | /blob-report/ 42 | /playwright/.cache/ 43 | 44 | -------------------------------------------------------------------------------- /examples/e2e/experimental/src/app/use-cache/fetch/page.tsx: -------------------------------------------------------------------------------- 1 | import { ISRComponent } from "@/components/cached"; 2 | import { Suspense } from "react"; 3 | 4 | async function getFromFetch() { 5 | "use cache"; 6 | // This is a simple fetch to ensure that the cache is working with IO inside 7 | const res = await fetch("https://opennext.js.org"); 8 | return res.headers.get("Date"); 9 | } 10 | 11 | export default async function Page() { 12 | const date = await getFromFetch(); 13 | return ( 14 |
15 |

Cache

16 |

{date}

17 | Loading...

}> 18 | 19 |
20 |
21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/components/product-split-payments.tsx: -------------------------------------------------------------------------------- 1 | import { ProductCurrencySymbol } from '#/components/product-currency-symbol'; 2 | import { allocate, toUnit, up, type Dinero } from 'dinero.js'; 3 | 4 | export const ProductSplitPayments = ({ price }: { price: Dinero }) => { 5 | // only offer split payments for more expensive items 6 | if (toUnit(price) < 150) { 7 | return null; 8 | } 9 | 10 | const [perMonth] = allocate(price, [1, 2]); 11 | return ( 12 |
13 | Or 14 | {toUnit(perMonth, { digits: 0, round: up })}/month for 3 months 15 |
16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /examples/playground15/open-next.config.ts: -------------------------------------------------------------------------------- 1 | import { defineCloudflareConfig, type OpenNextConfig } from "@opennextjs/cloudflare"; 2 | import r2IncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/r2-incremental-cache"; 3 | import doQueue from "@opennextjs/cloudflare/overrides/queue/do-queue"; 4 | import d1NextTagCache from "@opennextjs/cloudflare/overrides/tag-cache/d1-next-tag-cache"; 5 | 6 | export default { 7 | ...defineCloudflareConfig({ 8 | incrementalCache: r2IncrementalCache, 9 | queue: doQueue, 10 | tagCache: d1NextTagCache, 11 | }), 12 | cloudflare: { 13 | skewProtection: { 14 | enabled: false, 15 | }, 16 | }, 17 | } satisfies OpenNextConfig; 18 | -------------------------------------------------------------------------------- /examples/ssg-app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "preserve", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./*"] 23 | } 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 26 | "exclude": ["node_modules"] 27 | } 28 | -------------------------------------------------------------------------------- /examples/middleware/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | 38 | # playwright 39 | /test-results/ 40 | /playwright-report/ 41 | /blob-report/ 42 | /playwright/.cache/ 43 | -------------------------------------------------------------------------------- /create-cloudflare/next/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2024", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "preserve", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./src/*"] 23 | } 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 26 | "exclude": ["node_modules"] 27 | } 28 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/src/pages/fallback/[slug].tsx: -------------------------------------------------------------------------------- 1 | import type { InferGetStaticPropsType } from "next"; 2 | 3 | export function getStaticPaths() { 4 | return { 5 | paths: [ 6 | { 7 | params: { 8 | slug: "fallback", 9 | }, 10 | }, 11 | ], 12 | fallback: false, 13 | }; 14 | } 15 | 16 | export function getStaticProps() { 17 | return { 18 | props: { 19 | message: "This is a static fallback page.", 20 | }, 21 | }; 22 | } 23 | 24 | export default function Page({ message }: InferGetStaticPropsType) { 25 | return ( 26 |
27 |

Static Fallback Page

28 |

{message}

29 |
30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/wrangler.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "node_modules/wrangler/config-schema.json", 3 | "main": ".open-next/worker.js", 4 | "name": "pages-router", 5 | "compatibility_date": "2024-12-30", 6 | "compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"], 7 | "assets": { 8 | "directory": ".open-next/assets", 9 | "binding": "ASSETS" 10 | }, 11 | "r2_buckets": [ 12 | { 13 | "binding": "NEXT_INC_CACHE_R2_BUCKET", 14 | "bucket_name": "cache" 15 | } 16 | ], 17 | "services": [ 18 | { 19 | "binding": "WORKER_SELF_REFERENCE", 20 | "service": "pages-router" 21 | } 22 | ], 23 | "vars": { 24 | "OPEN_NEXT_REQUEST_ID_HEADER": "true" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/playground14/app/api/hello/route.ts: -------------------------------------------------------------------------------- 1 | import { headers } from "next/headers"; 2 | 3 | import { getCloudflareContext } from "@opennextjs/cloudflare"; 4 | 5 | export async function GET() { 6 | const headersList = headers(); 7 | 8 | const fromCloudflareContext = headersList.has("from-cloudflare-context"); 9 | 10 | if (!fromCloudflareContext) { 11 | return new Response("Hello World!"); 12 | } 13 | 14 | // Retrieve the bindings defined in wrangler.json 15 | return new Response(getCloudflareContext().env.hello); 16 | } 17 | 18 | export async function POST(request: Request) { 19 | const text = await request.text(); 20 | return new Response(`Hello post-World! body=${text}`); 21 | } 22 | -------------------------------------------------------------------------------- /examples/e2e/experimental/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "preserve", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./src/*"] 23 | } 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 26 | "exclude": ["node_modules"] 27 | } 28 | -------------------------------------------------------------------------------- /examples/playground15/app/api/hello/route.ts: -------------------------------------------------------------------------------- 1 | import { headers } from "next/headers"; 2 | 3 | import { getCloudflareContext } from "@opennextjs/cloudflare"; 4 | 5 | export async function GET() { 6 | const headersList = await headers(); 7 | 8 | const fromCloudflareContext = headersList.has("from-cloudflare-context"); 9 | 10 | if (!fromCloudflareContext) { 11 | return new Response("Hello World!"); 12 | } 13 | 14 | // Retrieve the bindings defined in wrangler.json 15 | return new Response(getCloudflareContext().env.hello); 16 | } 17 | 18 | export async function POST(request: Request) { 19 | const text = await request.text(); 20 | return new Response(`Hello post-World! body=${text}`); 21 | } 22 | -------------------------------------------------------------------------------- /examples/vercel-blog-starter/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "dom.iterable", "esnext"], 4 | "allowJs": true, 5 | "skipLibCheck": true, 6 | "strict": true, 7 | "noEmit": true, 8 | "esModuleInterop": true, 9 | "module": "esnext", 10 | "moduleResolution": "bundler", 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "jsx": "preserve", 14 | "incremental": true, 15 | "plugins": [ 16 | { 17 | "name": "next" 18 | } 19 | ], 20 | "paths": { 21 | "@/*": ["./src/*"] 22 | } 23 | }, 24 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 25 | "exclude": ["node_modules", "open-next.config.ts"] 26 | } 27 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | .open-next 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | .pnpm-debug.log* 28 | 29 | # local env files 30 | .env*.local 31 | 32 | # vercel 33 | .vercel 34 | 35 | # typescript 36 | *.tsbuildinfo 37 | next-env.d.ts 38 | 39 | # playwright 40 | /test-results/ 41 | /playwright-report/ 42 | /blob-report/ 43 | /playwright/.cache/ 44 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/src/pages/fallback-intercepted/[slug].tsx: -------------------------------------------------------------------------------- 1 | import type { InferGetStaticPropsType } from "next"; 2 | 3 | export function getStaticPaths() { 4 | return { 5 | paths: [ 6 | { 7 | params: { 8 | slug: "fallback", 9 | }, 10 | }, 11 | ], 12 | fallback: false, 13 | }; 14 | } 15 | 16 | export function getStaticProps() { 17 | return { 18 | props: { 19 | message: "This is a static fallback page.", 20 | }, 21 | }; 22 | } 23 | 24 | export default function Page({ message }: InferGetStaticPropsType) { 25 | return ( 26 |
27 |

Static Fallback Page

28 |

{message}

29 |
30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /examples/playground14/wrangler.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "node_modules/wrangler/config-schema.json", 3 | "main": "worker.ts", 4 | "name": "playground14", 5 | "compatibility_date": "2024-12-30", 6 | "compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"], 7 | "assets": { 8 | "directory": ".open-next/assets", 9 | "binding": "ASSETS" 10 | }, 11 | "kv_namespaces": [ 12 | { 13 | "binding": "NEXT_INC_CACHE_KV", 14 | "id": "" 15 | } 16 | ], 17 | "vars": { 18 | "hello": "Hello World from the cloudflare context!", 19 | "PROCESS_ENV_VAR": "process.env", 20 | "NEXT_INC_CACHE_KV_PREFIX": "custom_prefix" 21 | }, 22 | "images": { 23 | "binding": "IMAGES" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/bugs/gh-119/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "preserve", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./*"] 23 | } 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 26 | "exclude": ["node_modules", "open-next.config.ts"] 27 | } 28 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/wrangler.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "node_modules/wrangler/config-schema.json", 3 | "main": ".open-next/worker.js", 4 | "name": "app-pages-router", 5 | "compatibility_date": "2024-12-30", 6 | "compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"], 7 | "assets": { 8 | "directory": ".open-next/assets", 9 | "binding": "ASSETS" 10 | }, 11 | "r2_buckets": [ 12 | { 13 | "binding": "NEXT_INC_CACHE_R2_BUCKET", 14 | "bucket_name": "cache" 15 | } 16 | ], 17 | "services": [ 18 | { 19 | "binding": "WORKER_SELF_REFERENCE", 20 | "service": "app-pages-router" 21 | } 22 | ], 23 | "vars": { 24 | "NEXT_INC_CACHE_R2_PREFIX": "custom_prefix" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/e2e/app-router/app/ssr/page.tsx: -------------------------------------------------------------------------------- 1 | import { headers } from "next/headers"; 2 | 3 | async function getTime() { 4 | const res = await new Promise((resolve) => { 5 | setTimeout(() => { 6 | resolve(new Date().toISOString()); 7 | }, 1500); 8 | }); 9 | return res; 10 | } 11 | 12 | export default async function SSR() { 13 | const time = await getTime(); 14 | const headerList = await headers(); 15 | const responseOpenNext = await fetch("https://opennext.js.org", { 16 | cache: "force-cache", 17 | }); 18 | return ( 19 |
20 |

Time: {time}

21 |
{headerList.get("host")}
22 |

Cached fetch: {responseOpenNext.headers.get("date")}

23 |
24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /examples/playground14/worker.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore `.open-next/worker.ts` is generated at build time 2 | import { default as handler } from "./.open-next/worker.js"; 3 | 4 | export default { 5 | fetch: handler.fetch, 6 | 7 | /** 8 | * Scheduled Handler 9 | * 10 | * Can be tested with: 11 | * - `wrangler dev --test-scheduled` 12 | * - `curl "http://localhost:8787/__scheduled?cron=*+*+*+*+*"` 13 | * @param event 14 | */ 15 | async scheduled(event) { 16 | console.log("Scheduled event", event); 17 | }, 18 | } satisfies ExportedHandler; 19 | 20 | // @ts-ignore `.open-next/worker.ts` is generated at build time 21 | export { DOQueueHandler, DOShardedTagCache } from "./.open-next/worker.js"; 22 | -------------------------------------------------------------------------------- /examples/bugs/gh-219/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "preserve", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./src/*"] 23 | } 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 26 | "exclude": ["node_modules", "open-next.config.ts"] 27 | } 28 | -------------------------------------------------------------------------------- /examples/bugs/gh-223/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --foreground-rgb: 0, 0, 0; 7 | --background-start-rgb: 214, 219, 220; 8 | --background-end-rgb: 255, 255, 255; 9 | } 10 | 11 | @media (prefers-color-scheme: dark) { 12 | :root { 13 | --foreground-rgb: 255, 255, 255; 14 | --background-start-rgb: 0, 0, 0; 15 | --background-end-rgb: 0, 0, 0; 16 | } 17 | } 18 | 19 | body { 20 | color: rgb(var(--foreground-rgb)); 21 | background: linear-gradient(to bottom, transparent, rgb(var(--background-end-rgb))) 22 | rgb(var(--background-start-rgb)); 23 | } 24 | 25 | @layer utilities { 26 | .text-balance { 27 | text-wrap: balance; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /examples/create-next-app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "dom.iterable", "esnext"], 4 | "allowJs": true, 5 | "skipLibCheck": true, 6 | "strict": true, 7 | "noEmit": true, 8 | "esModuleInterop": true, 9 | "module": "esnext", 10 | "moduleResolution": "bundler", 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "jsx": "preserve", 14 | "incremental": true, 15 | "plugins": [ 16 | { 17 | "name": "next" 18 | } 19 | ], 20 | "paths": { 21 | "@/*": ["./src/*"] 22 | }, 23 | "target": "ES2017" 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 26 | "exclude": ["node_modules", "open-next.config.ts"] 27 | } 28 | -------------------------------------------------------------------------------- /examples/middleware/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmit": true, 10 | "esModuleInterop": true, 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "jsx": "preserve", 16 | "incremental": true, 17 | "plugins": [ 18 | { 19 | "name": "next" 20 | } 21 | ] 22 | }, 23 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 24 | "exclude": ["node_modules", "open-next.config.ts", "worker.ts"] 25 | } 26 | -------------------------------------------------------------------------------- /examples/next-partial-prerendering/components/product-review-card.tsx: -------------------------------------------------------------------------------- 1 | import type { Review } from '#/types/review'; 2 | import { ProductRating } from '#/components/product-rating'; 3 | 4 | export const ProductReviewCard = ({ review }: { review: Review }) => { 5 | return ( 6 |
7 |
8 |
9 |
10 |
{review.name}
11 |
12 | 13 | {review.rating ? : null} 14 |
15 | 16 |
{review.text}
17 |
18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /examples/playground15/app/from-app/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import Link from "next/link"; 4 | import Image from "next/image"; 5 | import testImage from "../../public/test.jpg"; 6 | 7 | export default function Page() { 8 | return ( 9 | <> 10 |

hello app

11 | test 12 |

{process.env.NEXT_DEPLOYMENT_ID}

13 | 14 | 24 | 25 | other app 26 | 27 | 28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /examples/prisma/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "react-jsx", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./src/*"] 23 | } 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", ".next/dev/types/**/*.ts"], 26 | "exclude": ["node_modules"] 27 | } 28 | -------------------------------------------------------------------------------- /packages/cloudflare/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "extends": "@tsconfig/strictest/tsconfig.json", 4 | "compilerOptions": { 5 | "declaration": true, 6 | "esModuleInterop": true, 7 | "exactOptionalPropertyTypes": false, 8 | "forceConsistentCasingInFileNames": true, 9 | "lib": ["ESNext"], 10 | "module": "ESNext", 11 | "moduleResolution": "node", 12 | "noImplicitReturns": false, 13 | "noPropertyAccessFromIndexSignature": false, 14 | "outDir": "./dist", 15 | "target": "ES2022", 16 | "types": ["@cloudflare/workers-types", "@opennextjs/aws/types/global.d.ts"] 17 | }, 18 | "include": ["src/**/*.ts", "env.d.ts"], 19 | "exclude": ["src/**/*.spec.ts"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/playground14/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "dom.iterable", "esnext"], 4 | "allowJs": true, 5 | "skipLibCheck": true, 6 | "strict": false, 7 | "noEmit": true, 8 | "incremental": true, 9 | "module": "esnext", 10 | "esModuleInterop": true, 11 | "moduleResolution": "node", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "preserve", 15 | "plugins": [ 16 | { 17 | "name": "next" 18 | } 19 | ], 20 | "strictNullChecks": true, 21 | "target": "ES2017" 22 | }, 23 | "include": ["next-env.d.ts", ".next/types/**/*.ts", "**/*.ts", "**/*.tsx", "worker-configuration.d.ts"], 24 | "exclude": ["node_modules", "open-next.config.ts"] 25 | } 26 | -------------------------------------------------------------------------------- /examples/playground15/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "dom.iterable", "esnext"], 4 | "allowJs": true, 5 | "skipLibCheck": true, 6 | "strict": false, 7 | "noEmit": true, 8 | "incremental": true, 9 | "module": "esnext", 10 | "esModuleInterop": true, 11 | "moduleResolution": "node", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "preserve", 15 | "plugins": [ 16 | { 17 | "name": "next" 18 | } 19 | ], 20 | "target": "ES2017", 21 | "strictNullChecks": true 22 | }, 23 | "include": ["next-env.d.ts", ".next/types/**/*.ts", "**/*.ts", "**/*.tsx", "worker-configuration.d.ts"], 24 | "exclude": ["node_modules", "open-next.config.ts"] 25 | } 26 | -------------------------------------------------------------------------------- /examples/vercel-blog-starter/src/app/_components/intro.tsx: -------------------------------------------------------------------------------- 1 | import { CMS_NAME } from "@/lib/constants"; 2 | 3 | export function Intro() { 4 | return ( 5 |
6 |

Blog.

7 |

8 | A statically generated blog example using{" "} 9 | 13 | Next.js 14 | {" "} 15 | and {CMS_NAME}. 16 |

17 |
18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /examples/create-next-app/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | 38 | # wrangler 39 | .wrangler 40 | 41 | # playwright 42 | /test-results/ 43 | /playwright-report/ 44 | /blob-report/ 45 | /playwright/.cache/ 46 | -------------------------------------------------------------------------------- /examples/e2e/app-pages-router/e2e/middleware.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from "@playwright/test"; 2 | 3 | test("should return correctly on HEAD request with an empty body", async ({ request }) => { 4 | const response = await request.head("/head"); 5 | expect(response.status()).toBe(200); 6 | const body = await response.text(); 7 | expect(body).toBe(""); 8 | expect(response.headers()["x-from-middleware"]).toBe("true"); 9 | }); 10 | 11 | test("should return correctly for directly returning a fetch response", async ({ request }) => { 12 | const response = await request.get("/fetch"); 13 | expect(response.status()).toBe(200); 14 | const body = await response.json(); 15 | expect(body).toEqual({ hello: "world" }); 16 | }); 17 | -------------------------------------------------------------------------------- /examples/overrides/d1-tag-next/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "react-jsx", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./*"] 23 | } 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", ".next/dev/types/**/*.ts"], 26 | "exclude": ["node_modules"] 27 | } 28 | -------------------------------------------------------------------------------- /examples/overrides/kv-tag-next/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "react-jsx", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./*"] 23 | } 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", ".next/dev/types/**/*.ts"], 26 | "exclude": ["node_modules"] 27 | } 28 | -------------------------------------------------------------------------------- /examples/overrides/memory-queue/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "react-jsx", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./*"] 23 | } 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", ".next/dev/types/**/*.ts"], 26 | "exclude": ["node_modules"] 27 | } 28 | -------------------------------------------------------------------------------- /examples/playground14/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | 38 | # wrangler 39 | .wrangler 40 | 41 | # playwright 42 | /test-results/ 43 | /playwright-report/ 44 | /blob-report/ 45 | /playwright/.cache/ 46 | -------------------------------------------------------------------------------- /examples/playground15/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | 38 | # wrangler 39 | .wrangler 40 | 41 | # playwright 42 | /test-results/ 43 | /playwright-report/ 44 | /blob-report/ 45 | /playwright/.cache/ 46 | -------------------------------------------------------------------------------- /examples/e2e/pages-router/e2e/header.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from "@playwright/test"; 2 | 3 | test("should test if poweredByHeader adds the correct headers ", async ({ page }) => { 4 | const result = await page.goto("/"); 5 | expect(result).toBeDefined(); 6 | expect(result?.status()).toBe(200); 7 | const headers = result?.headers(); 8 | 9 | // Both these headers should be present cause poweredByHeader is true in pagesRouter 10 | expect(headers?.["x-powered-by"]).toBe("Next.js"); 11 | expect(headers?.["x-opennext"]).toBe("1"); 12 | // This header should be defined cause we have set the `OPEN_NEXT_REQUEST_ID_HEADER` env variable in wrangler.jsonc 13 | expect(headers?.["x-opennext-requestid"]).not.toBeUndefined(); 14 | }); 15 | -------------------------------------------------------------------------------- /examples/ssg-app/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | import "./globals.css"; 3 | 4 | import { getCloudflareContext } from "@opennextjs/cloudflare"; 5 | 6 | export const metadata: Metadata = { 7 | title: "SSG App", 8 | description: "An app in which all the routes are SSG'd", 9 | }; 10 | 11 | export default async function RootLayout({ 12 | children, 13 | }: Readonly<{ 14 | children: React.ReactNode; 15 | }>) { 16 | const cloudflareContext = await getCloudflareContext({ 17 | async: true, 18 | }); 19 | 20 | return ( 21 | 22 | 23 | {children} 24 | 25 | 26 | 27 | ); 28 | } 29 | --------------------------------------------------------------------------------