Using Next Middleware to access geolocation
I don’t use Middleware from Next.js often, but I have dabbled a few times. Recently someone in another Developer’s Discord, I also have a Discord if you want to chat Jamstack, asked about how to add the Geolocation to a non-dynamic page.
What is _middleware
?
Middleware allows you to use code over configuration. This gives you so much more flexibility over how your applications act when a user visits. The Middleware runs before the incoming request is completed, this allows you to modify the response by rewriting, redirecting, adding headers, or even streaming HTML.
Adding Geolocation
Depending on your situation, depends on where you need your _middleware.(js.tsx)
for this example it will run on every page. However, you can use it in nested routes to run for specific pages or dynamic routes.
Create your file where you need it, inside that file you need to import {NextResponse} from “next/server”
Then create export async function middleware(req){}
this is where we are going to be doing the work to add our user's location.
The Middleware from Next.js has access to cookies
, nextUrl
, i18n
, ua
, geo
, ip
in the request which means we can use this to add geolocation to our application.
To rewrite our request we are going to need to access the nextUrl
and geo
from our request.
For example const { nextUrl: url, geo } = req
now we can modify the nextUrl
to add searchParams
(query parameters) to our request.
Then finally return our new URL using NextResponse
below is the full request.
import { NextResponse } from 'next/server'
export async function middleware(req) {
const { nextUrl: url, geo } = req
const country = geo.country || 'US'
url.searchParams.set('country', country)
return NextResponse.rewrite(url)
}
Updating our page
Now we need to add and use our geolocation to the page, to do that we need to first pass the middleware
through getServerSideProps
to pass it to the page. Currently, the _middleware
has all the info on the server.
// pass the _middleware to the index.js
export const getServerSideProps = ({ query }) => ({
props: query,
})
Finally, we can use it on the page, however, we want by passing the props to the page:
import Head from 'next/head'
import Image from 'next/image'
import styles from '../styles/Home.module.css'
import { useRouter } from 'next/router'
// pass the _middleware to the index.js
export const getServerSideProps = ({ query }) => ({
props: query,
})
export default function Home(props) {
// use it right from the props
console.log(props.country)
// or you can grab it from the router.
const router = useRouter();
console.log(router.query);
return (
<div className={styles.container}>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className={styles.main}>
<h1 className={styles.title}>
Welcome to {props.country}
</h1>
</main>
</div>
)
}
Now you can handle whatever you need knowing the geolocation.
One thing to note, geolocation made not be available so just be cautious, that is why we have a back up plan of
US