Co-authored by
Hayden Bleaselnext-forge
David MyttonArcjet

next-forge uses Arcjet for application security which includes IP details and geolocation information you can use in your application.

In the app application, Arcjet is called in the apps/app/app/(authenticated)/layout.tsx file which runs on every authenticated route.

For the web application, Arcjet is called in the middleware, which runs on every request except for static assets.

In both cases you could apply app-/website-wide rules based on the IP details, such as showing different content based on the user’s location.

Accessing IP location data

The IP details are available in the Arcjet decision object, which is returned from the all to aj.protect(). The IP location fields may be undefined, so you can use various utility functions to retrieve the data.

// ...
const decision = await aj.protect(req);

if (decision.ip.hasCity() && decision.ip.city === "San Francisco") {
  // Create a custom response for San Francisco
}

if (decision.ip.hasRegion() && decision.ip.region === "California") {
  // Create a custom response for California
}

if (decision.ip.hasCountry() && decision.ip.country === "US") {
  // Create a custom response for the United States
}

if (decision.ip.hasContinent() && decision.ip.continent === "NA") {
  // Create a custom response for North America
}

See the Arcjet IP analysis reference for more information on the fields available.

Accessing IP details elsewhere

Next.js does not allow passing data from the root layout or middleware to other pages in your application. To access the IP details in other parts of your application, you need to remove the Arcjet call from the root layout (app) or middleware (web) and call it in the specific page where you need the IP details.

See the Arcjet documentation on how to call aj.protect() in route handlers, pages / server components, and server actions.

If you remove the Arcjet call from apps/app/app/(authenticated)/layout.tsx or middleware.ts it will no longer run on every request. You will need to call aj.protect() everywhere you wish to apply Arcjet rules, even if you don’t need the IP details.