In this iteration we will add an API to our app.
Adding the API is simple
//src/app/api/greet/route.ts
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const username = searchParams.get("username");
return Response.json({ greeting: `hello ${username}` });
}
// Not needed since we use the search params
// export const dynamic = "force-dynamic"; // defaults to force-static
Now let’s call it from the second page src/app/[lng]/second-page/page.tsx
using a form.
<form
action="/api/greet"
style={{ display: "flex", flexDirection: "column", gap: "0.5em" }}
method="get"
>
<label for="username">Name:</label>
<input type="text" id="username" name="username" />
<button type="submit" style={{ width: "fit-content" }}>
Submit
</button>
</form>
We need to make a few other changes so the API plays nice with the I18N we added earlier.
In the withInternationalization.ts
make sure it ignors the /api/*
paths by adding:
// Redirect if lng in path is not supported
if (
!languages.some((loc: string) =>
request.nextUrl.pathname.startsWith(`/${loc}`)
) &&
!request.nextUrl.pathname.startsWith("/_next") &&
!request.nextUrl.pathname.startsWith("/api")
) {
return NextResponse.redirect(
new URL(`/${lng}${request.nextUrl.pathname}`, request.url)
);
}
And change the middleware config if we want to log the API endpoints.
export const config = {
matcher: [
/*
* Match all request paths except for the ones starting with:
* - _next/static (static files)
* - _next/image (image optimization files)
* - _next/assets (asset files)
* - favicon.ico (favicon file)
*/
"/((?!_next/static|_next/image|assets|favicon.ico|sw.js).*)",
],
}