#NextJs 15 vs nextJs 14
1 messages · Page 1 of 1 (latest)
Hi @cunning herald. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
If your Stripe webhook route handlers worked in Next.js 14 but are not working after upgrading to Next.js 15.4.3 (using the App Router), there are a few important changes and considerations:
-
Route Handler Caching Behavior Changed in v15
In Next.js 15, the default caching forGETroute handlers changed from static to dynamic. However, for Stripe webhooks, you should be using aPOSThandler, which is not cached by default in either version. So, this change should not directly affect your webhook route, but it's important to be aware of for other handlers. If you have anyGEThandlers that need to be cached, you now need to explicitly opt-in usingexport const dynamic = 'force-static'in your route file How to upgrade to version 15 > Route Handlers. -
No Need for
bodyParserorexport const configin App Router
In the App Router, you do not need to usebodyParserorexport const configto access the raw request body. This was required in the Pages Router, but in the App Router, you can use the standard Web APIs directly. If you try to useexport const configin your App Router route handler, you will get a build error STRIPE WEBHOOK - Cannot access request raw body with Javascript (request vs NextApiRequest).
Example for Stripe Webhook in App Router:
// app/api/webhook/route.ts
export async function POST(request: Request) {
try {
const rawBody = await request.text();
// Use rawBody and request.headers['stripe-signature'] for Stripe verification
} catch (error) {
return new Response(`Webhook error: ${error.message}`, { status: 400 });
}
return new Response('Success!', { status: 200 });
}
You do not need to use any special config or body parser—just use the standard request.text() or request.json() as needed Webhooks Example.
- Check for Other Breaking Changes
If your route handlers are still not working, double-check that:- Your route files are named correctly (e.g.,
route.tsorroute.js). - They are placed inside the
appdirectory, notpages. - You are using the correct HTTP method (
POSTfor Stripe webhooks). - You are not using any deprecated configuration from the Pages Router.
- Your route files are named correctly (e.g.,
If you follow the above, your Stripe webhook route handlers should work in Next.js 15 with the App Router. If you are still experiencing issues, please check for any error messages in your build or runtime logs, as they may indicate misconfiguration or other problems.
Summary:
- Remove any
export const configorbodyParserusage. - Use the standard Web API to read the request body.
- Ensure your route handler is correctly placed and named.
If you need a working example, see the official docs for webhook route handlers and the related GitHub issue.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@cunning herald Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@worthy wyvern write a simple ping route so i can test if its working in nextjs 15
Let me check the knowledge base for you again. Give me one moment! :books:
Certainly! Here’s a simple example of a "ping" route handler for Next.js 15 using the App Router. Place this file at app/api/ping/route.ts or app/api/ping/route.js:
export async function GET() {
return Response.json({ message: 'pong' })
}
This will respond to a GET request at /api/ping with a JSON object { message: 'pong' }. This example follows the official Next.js 15 route handler conventions route.js API reference.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@cunning herald Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@worthy wyvern
import { getSettingsByOrgId } from '@/app/data/organization_availability/get-availibilities'
import { getOrgIdByHash } from '@/app/data/route_logic/retrieve_orgId_by_hash'
import AppointmentBooking from '@/components/appointment'
import { notFound } from 'next/navigation'
type Params = {
hashedOrgId: string
}
export default async function BookingPage({ params }: { params: Params }) {
const { hashedOrgId } = params
const org = await getOrgIdByHash(hashedOrgId)
if (!org) notFound()
const business_settings = await getSettingsByOrgId(org.id)
if (!business_settings) notFound()
return (
<div>
<AppointmentBooking settings={business_settings} />
</div>
)
}
app/booking/[hashedOrgId]/page.tsx
Type error: Type '{ params: Params; }' does not satisfy the constraint 'PageProps'.
Types of property 'params' are incompatible.
Type 'Params' is missing the following properties from type 'Promise<any>': then, catch, finally, [Symbol.toStringTag]
Next.js build worker exited with code: 1 and signal: null
Let me check the knowledge base for you again. Give me one moment! :books:
In Next.js 15, the params prop for dynamic routes is now a Promise rather than a plain object. This is a breaking change from Next.js 14. Your current code expects params to be an object, but the generated types expect it to be a Promise, which is why you see the type error:
Type '{ params: Params; }' does not satisfy the constraint 'PageProps'.
Types of property 'params' are incompatible.
Type 'Params' is missing the following properties from type 'Promise<any>': then, catch, finally, [Symbol.toStringTag]
How to fix:
Update your page component to expect params as a Promise<Params>, and use await to access its value:
type Params = {
hashedOrgId: string
}
export default async function BookingPage({ params }: { params: Promise<Params> }) {
const { hashedOrgId } = await params
const org = await getOrgIdByHash(hashedOrgId)
if (!org) notFound()
const business_settings = await getSettingsByOrgId(org.id)
if (!business_settings) notFound()
return (
<div>
<AppointmentBooking settings={business_settings} />
</div>
)
}
This change is required for compatibility with Next.js 15 dynamic route pages, as documented in the official Next.js docs and confirmed by multiple community reports and GitHub issues Minimal Next.js Type Pollution Reproduction, params typed as Promise<any> in .next/types when using dynamic route server component.
Summary:
- Change
{ params: Params }to{ params: Promise<Params> } - Use
const { hashedOrgId } = await params