Embed OpenStreetMap in a Next.js Project

Chris Achinga

Embed OpenStreetMap in a Next.js project

OpenStreetMap is an open-source, editable world map. It is free to use in any project and requires no API keys or authentication.

This post outlines how to embed a map image with a map pin of coordinates in a Next.js application, using Node.js packages such as React Leaflet. The image will contain a marker pinning to the set of coordinates defined.

Demo

A live demo is available on CodeSandbox:

1<CodeSandbox id="osm-next-js" title="Embedding OpenStreetMap in Nuxt.js"/>

A complete demo of the project is also available on GitHub:

https://github.com/achingachris/openstreetmap-nextjs

Prerequisites

To get this done, you’ll need basic knowledge about:

Starting a Next.js project

To start a Next.js project, run the following on a terminal/command prompt (cmd):

1npx create-next-app openstreetmap-nextjs
2 &&
3 cd openstreetmap-nextjs

To access OpenStreetMap in our Next.js application, we will use Leaflet, an open-source JavaScript library for interactive maps. To use Leaflet in our Next.js application, we’ll use the React Leaflet, which comes with React components for Leaflet.

To install React Leaflet, run the following:

1npm install react-leaflet

React Leaflet components

To successfully use React Leaflet, we’ll wrap all the code inside the <MapContainer><MapContainer />, which wraps all the embedded maps. In addition, we need to have an attribution to OpenStreetMap using the TileLayer component:

1<TileLayer
2 attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
3 url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
4/>

The TileLayer component takes in attribution and url props. These are used to attribute the map source, OpenStreetMap.

Let’s create a new component, OpenStreetMap.js, and update it with the code below:

1import React, { useState, useRef } from 'react'
2import { MapContainer, TileLayer, Marker } from 'react-leaflet'
3import 'leaflet/dist/leaflet.css'
4
5const OpenStreetMap = () => {
6 const [center, setCenter] = useState({ lat: -4.043477, lng: 39.668205 })
7 const ZOOM_LEVEL = 9
8 const mapRef = useRef()
9
10 return (
11 <>
12 <div className='container'>
13 <div className='container'>
14 <h1 className='text-center-mt-5'>OpenStreetMap Embeded</h1>
15 </div>
16 <div className='row'>
17 <div className='col'>
18 <div className='container'>
19 <MapContainer center={center} zoom={ZOOM_LEVEL} ref={mapRef}>
20 <TileLayer
21 attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
22 url='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
23 />
24 {location.loaded && !location.error && (
25 <Marker
26 position={[
27 location.coordinates.lat,
28 location.coordinates.lng,
29 ]}
30 ></Marker>
31 )}
32 </MapContainer>
33 </div>
34 </div>
35 </div>
36 </div>
37 </>
38 )
39}
40
41export default OpenStreetMap

We imported the components MapContainer, TileLayer, and Marker from React Leafet in the above snippet.

The MapContainer wraps all the embedded maps. The Marker focuses the map on the given coordinates, as given below:

1const [center, setCenter] = useState({ lat: -4.043477, lng: 39.668205 })

Import the OpenStreetMap component in the pages/index.js file, for us to view it from the home page.

1import OpenStreetMap from '../component/OpenStreetMap'
2
3 const index = () => {
4 return (
5 <>
6 <h1 className='text-center'>OpenStreetMap</h1>
7 <OpenStreetMap />
8 </>
9 )
10 }
11 export default index

When we run the development server: npm run dev, we will get an error:

1Server Error
2 ReferenceError: window is not defined
3 This error happened while generating the page. Any console logs will be displayed in the terminal window.

To fix that, we need to import the OpenStreetMap component dynamically. Therefore, we update the index.js file to contain:

1import dynamic from 'next/dynamic'
2 // import OpenStreetMap from '../component/OpenStreetMap'
3 const OpenStreetMap = dynamic(() => import('../component/OpenStreetMap'), {
4 ssr: false,
5 })
6 const index = () => {
7 return (
8 <>
9 <h1 className='text-center'>OpenStreetMap</h1>
10 <OpenStreetMap />
11 </>
12 )
13 }
14 export default index

If we rerun the development server, we see the map:

Conclusion

This article covers how to use React Leaflet to embed OpenStreetMaps into a Next.js project.

Useful resources:

Chris Achinga

Technical Writer