Amazon Location Service and AWS Amplify to Use Various Map Library
Tags: amazonlocationservice, amplify, aws, foss4g
Published: 2023-01-05 11:21:47

This article is an English translation of an article published in the AWS Japan official web magazine "builders.flash".
https://aws.amazon.com/jp/builders-flash/202301/use-map-library-location-service
![img](https://day-journal.com/memo/images/builders-flash/202301_use-map-library-location-service/page.png) 

<br>

This is a very exciting announcement for me personally, as there has never been a hero category for front-end technologies before. If there are any of you who like the "Front-End Web & Mobile" category, let's liven it up together!

<br>

Today, I wrote an article about location-based technologies and the "Front-End Web & Mobile" category, which are my area of expertise. This article is about combining various map libraries with the Amazon Location Service and AWS Amplify, which allow you to build location-based applications in an AWS environment.

![img](https://day-journal.com/memo/images/builders-flash/202301_use-map-library-location-service/all.png)  

<br>

I will build a location-based application using and comparing three open-source map libraries: [MapLibre GL JS](https://maplibre.org), [OpenLayers](https://openlayers.org), and [Leaflet](https://leafletjs.com).

- MapLibre GL JS: A map library using WebGL, recommended for intermediate users.
- OpenLayers: A map library that can be flexibly customized, recommended for advanced users.
- Leaflet: A map library that allows you to build location-based applications, recommended for beginners easily.

MapLibre GL JS is recommended when using Amazon Location Service, but you can choose any map library you like! I hope to introduce the advantages and disadvantages of each map library at another time. 

<br>

## Advance Preparation
Install Amplify CLI referring to [Amplify Documentation](https://docs.amplify.aws/start/getting-started/installation/q/integration/js).

Verified version at the time of writing
- node v18.1.0
- npm v8.19.2
- Amplify CLI v10.3.2

Install Amplify CLI.

```sh
npm install -g @aws-amplify/cli@10.3.2
```

Confirm the version of Amplify CLI.

```sh
amplify -v
```

Configure the initial settings of Amplify CLI.

```sh
amplify configure
```

<br>

## Starter to be used
I will extend the existing starter to build an Amazon Location Service environment. This starter is configured to allow easy use of the map library. Please try to fork or download the starter and see how it works in your environment.

### MapLibre GL JS Starter  
### [maplibregljs-starter](https://github.com/dayjournal/maplibregljs-starter)  
![img](https://day-journal.com/memo/images/builders-flash/202301_use-map-library-location-service/maplibregljs.png)  

### OpenLayers Starter  
### [openlayers-starter](https://github.com/dayjournal/openlayers-starter)  
![img](https://day-journal.com/memo/images/builders-flash/202301_use-map-library-location-service/openlayers2.png)  

### Leaflet Starter
### [leaflet-starter](https://github.com/dayjournal/leaflet-starter)  
![img](https://day-journal.com/memo/images/builders-flash/202301_use-map-library-location-service/leaflet.png)  

### How to use the starter
Install the packages

```bash
npm install
```

Start local server

```bash
npm run dev
```

![img](https://day-journal.com/memo/images/builders-flash/202301_use-map-library-location-service/starter.png)  

<br>

## Add libraries
Next, install the additional libraries required for the starter. For each starter, install the AWS Amplify and MapLibre GL JS wrapper libraries in common. AWS Amplify and the wrapper libraries make it easy to build an Amazon Location Service environment. Also, install other libraries for OpenLayers and Leaflet. Leaflet uses the "MapLibre GL Leaflet" library, so it is necessary to specify some library versions.

### MapLibre GL JS

```sh
npm install aws-amplify
npm install maplibre-gl-js-amplify
```

#### package.json

```json
{
  "name": "maplibregljs-starter",
  "version": "2.4.0",
  "description": "",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview"
  },
  "keywords": [],
  "author": "Yasunori Kirimoto",
  "license": "ISC",
  "devDependencies": {
    "typescript": "^4.8.4",
    "vite": "^3.2.1"
  },
  "dependencies": {
    "aws-amplify": "^4.3.42",
    "maplibre-gl": "^2.4.0",
    "maplibre-gl-js-amplify": "^2.1.0"
  }
}
```

<br>

### OpenLayers

```sh
npm install aws-amplify
npm install maplibre-gl-js-amplify
npm install @geoblocks/ol-maplibre-layer
```

#### package.json

```json
{
  "name": "openlayers-starter",
  "version": "7.1.0",
  "description": "",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview"
  },
  "keywords": [],
  "author": "Yasunori Kirimoto",
  "license": "ISC",
  "devDependencies": {
    "typescript": "^4.8.4",
    "vite": "^3.2.1"
  },
  "dependencies": {
    "@geoblocks/ol-maplibre-layer": "^0.0.4",
    "aws-amplify": "^4.3.42",
    "maplibre-gl-js-amplify": "^2.1.0",
    "ol": "^7.1.0"
  }
}
```

<br>

### Leaflet

```sh
npm install aws-amplify
npm install maplibre-gl-js-amplify@1.6.0
npm install maplibre-gl@1.15.3
npm install @maplibre/maplibre-gl-leaflet
```

#### package.json

```json
{
  "name": "leaflet-starter",
  "version": "1.9.2",
  "description": "",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview"
  },
  "keywords": [],
  "author": "Yasunori Kirimoto",
  "license": "ISC",
  "devDependencies": {
    "typescript": "^4.8.4",
    "vite": "^3.2.1"
  },
  "dependencies": {
    "@maplibre/maplibre-gl-leaflet": "^0.0.17",
    "@types/leaflet": "^1.8.0",
    "aws-amplify": "^4.3.42",
    "leaflet": "^1.9.2",
    "maplibre-gl": "^1.15.3",
    "maplibre-gl-js-amplify": "^1.6.0"
  }
}
```

<br>

## Configure AWS Amplify
Next, configure AWS Amplify. The settings can be configured in the same way for each starter. This time, I will configure Amazon Location Service with Amplify Geo, which can be built more easily. Please refer to [this article](https://dev.to/aws-builders/a-summary-of-how-to-build-amplify-geo-and-amazon-location-service-5hal) to compare Amazon Location Service and Amplify Geo.

Configure initial settings for AWS Amplify.

```sh
amplify init
```

```sh
? Enter a name for the project xxxxx
The following configuration will be applied:

Project information
| Name: xxxxx
| Environment: dev
| Default editor: xxxxx
| App type: javascript
| Javascript framework: none
| Source Directory Path: src
| Distribution Directory Path: dist
| Build Command: npm run-script build
| Start Command: npm run-script start

? Initialize the project with the above configuration? Yes
Using default provider  awscloudformation
? Select the authentication method you want to use: AWS profile

For more information on AWS Profiles, see:
https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html

? Please choose the profile you want to use xxxxx
Adding backend environment dev to AWS Amplify app: xxxxx

Deployment completed.
Deployed root stack maplibregljsstarter [ ======================================== ] 4/4
 amplify-maplibregljsstarter-d… AWS::CloudFormation::Stack     CREATE_COMPLETE
 AuthRole                       AWS::IAM::Role                 CREATE_COMPLETE
 UnauthRole                     AWS::IAM::Role                 CREATE_COMPLETE
 DeploymentBucket               AWS::S3::Bucket                CREATE_COMPLETE

✔ Help improve Amplify CLI by sharing non sensitive configurations on failures (y/N) · yes
Deployment bucket fetched.
✔ Initialized provider successfully.
✅ Initialized your environment successfully.

Your project has been successfully initialized and connected to the cloud!

Some next steps:
"amplify status" will show you what you've added already and if it's locally configured or deployed
"amplify add <category>" will allow you to add features like user login or a backend API
"amplify push" will build all your local backend resources and provision it in the cloud
"amplify console" to open the Amplify Console and view your project status
"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud

Pro tip:
Try "amplify add api" to create a backend API and then "amplify push" to deploy everything
```

Configure the authentication settings. Default settings are used this time.

```sh
amplify add auth
```

```sh
Using service: Cognito, provided by: awscloudformation

 The current configured provider is Amazon Cognito.

 Do you want to use the default authentication and security configuration? Default configuration
 Warning: you will not be able to edit these selections.
 How do you want users to be able to sign in? Username
 Do you want to configure advanced settings? No, I am done.
✅ Successfully added auth resource xxxxx locally

✅ Some next steps:
"amplify push" will build all your local backend resources and provision it in the cloud
"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud
```

Configure the map function. This time, select "HERE Explore" for the Japanese language support style.

```sh
amplify add geo
```

```sh
? Select which capability you want to add: Map (visualize the geospatial data)
✔ Provide a name for the Map: · xxxxx
✔ Who can access this Map? · Authorized and Guest users
Available advanced settings:
- Map style & Map data provider (default: Streets provided by Esri)

✔ Do you want to configure advanced settings? (y/N) · yes
✔ Specify the map style. Refer https://docs.aws.amazon.com/location-maps/latest/APIReference/API_MapConfiguration.html · Explore (data provided by HERE)

⚠️ Auth configuration is required to allow unauthenticated users, but it is not configured properly.
✅ Successfully updated auth resource locally.
✅ Successfully added resource xxxxx locally.

✅ Next steps:
"amplify push" builds all of your local backend resources and provisions them in the cloud
"amplify publish" builds all of your local backend and front-end resources (if you added hosting category) and provisions them in the cloud
```

After completing the settings, deploy the environment.

```sh
amplify push
```

```sh
⠋ Fetching updates to backend environment: dev from the cloud.⠋ Building resource auth/xxxxx
✔ Successfully pulled backend environment dev from the cloud.

    Current Environment: dev

┌──────────┬─────────────────────────────┬───────────┬───────────────────┐
│ Category │ Resource name               │ Operation │ Provider plugin   │
├──────────┼─────────────────────────────┼───────────┼───────────────────┤
│ Auth     │ xxxxx                       │ Create    │ awscloudformation │
├──────────┼─────────────────────────────┼───────────┼───────────────────┤
│ Geo      │ xxxxx                       │ Create    │ awscloudformation │
└──────────┴─────────────────────────────┴───────────┴───────────────────┘
? Are you sure you want to continue? Yes

Deployment completed.
Deployed root stack xxxxx [ ======================================== ] 3/3
 amplify-xxxxx                  AWS::CloudFormation::Stack     UPDATE_COMPLETE
 authxxxxx                      AWS::CloudFormation::Stack     CREATE_COMPLETE
 geomapxxxxx                    AWS::CloudFormation::Stack     CREATE_COMPLETE
Deployed auth xxxxxx [ ======================================== ] 10/
 UserPool                       AWS::Cognito::UserPool         CREATE_COMPLETE
 UserPoolClientWeb              AWS::Cognito::UserPoolClient   CREATE_COMPLETE
 UserPoolClient                 AWS::Cognito::UserPoolClient   CREATE_COMPLETE
 UserPoolClientRole             AWS::IAM::Role                 CREATE_COMPLETE
 UserPoolClientLambda           AWS::Lambda::Function          CREATE_COMPLETE
 UserPoolClientLambdaPolicy     AWS::IAM::Policy               CREATE_COMPLETE
 UserPoolClientLogPolicy        AWS::IAM::Policy               CREATE_COMPLETE
 UserPoolClientInputs           Custom::LambdaCallout          CREATE_COMPLETE
 IdentityPool                   AWS::Cognito::IdentityPool     CREATE_COMPLETE
 IdentityPoolRoleMap            AWS::Cognito::IdentityPoolRol… CREATE_COMPLETE
Deployed geo mapxxxxx [ ======================================== ] 5/5
 CustomMapLambdaServiceRolexxx  AWS::IAM::Role                 CREATE_COMPLETE
 CustomMapLambdaServiceRolexxx  AWS::IAM::Policy               CREATE_COMPLETE
 CustomMapLambdaxxx             AWS::Lambda::Function          CREATE_COMPLETE
 CustomMap                      Custom::LambdaCallout          CREATE_COMPLETE
 MapPolicy                      AWS::IAM::Policy               CREATE_COMPLETE
```

Accessing the management console, you will see that the map has been registered.

![img](https://day-journal.com/memo/images/builders-flash/202301_use-map-library-location-service/console.png)  

<br>

## Building the Application
Finally, we will show you how to display the Amazon Location Service map. Update "main.ts" and "vite.config.ts" for each starter. Also, create a new "@geoblocks/ol-maplibre-layer.d.ts" only for OpenLayers.

### MapLibre GL JS

#### File Configuration

```sh
.
├── LICENSE
├── README.md
├── amplify
├── dist
│   ├── assets
│   └── index.html
├── docs
├── img
├── index.html
├── package-lock.json
├── package.json
├── src
│   ├── aws-exports.js
│   ├── main.ts
│   ├── style.css
│   └── vite-env.d.ts
├── tsconfig.json
└── vite.config.ts
```

#### main.ts

```typescript
import './style.css'
import 'maplibre-gl/dist/maplibre-gl.css';
import maplibregl from 'maplibre-gl';
import { createMap } from "maplibre-gl-js-amplify";
import { Amplify } from 'aws-amplify';
import awsconfig from './aws-exports';
Amplify.configure(awsconfig);

async function mapCreate() {
    const map = await createMap({
        container: 'map',
        center: [139.767, 35.681],
        zoom: 11,
    });
    map.addControl(
        new maplibregl.NavigationControl({
            visualizePitch: true,
        })
    );
}
mapCreate();
```

#### vite.config.ts

```typescript
import { defineConfig } from 'vite'

export default defineConfig({
  resolve: {
    alias: {
      './runtimeConfig': './runtimeConfig.browser',
    },
  },
  define: {
    'window.global': {}
  },
})
```

Start local server

```bash
npm run dev
```

![img](https://day-journal.com/memo/images/builders-flash/202301_use-map-library-location-service/maplibregljs_als.png)  

<br>

### OpenLayers

#### File Configuration

```sh
.
├── LICENSE
├── README.md
├── amplify
├── dist
│   ├── assets
│   └── index.html
├── docs
├── img
├── index.html
├── package-lock.json
├── package.json
├── src
│   ├── @geoblocks:ol-maplibre-layer.d.ts
│   ├── aws-exports.js
│   ├── main.ts
│   ├── style.css
│   └── vite-env.d.ts
├── tsconfig.json
└── vite.config.ts
```

#### main.ts

```typescript
import './style.css'
import 'ol/ol.css';
import Map from 'ol/Map';
import View from 'ol/View';
import Source from 'ol/source/Source';
import { fromLonLat } from 'ol/proj';
import { ScaleLine } from 'ol/control';
import MapLibreLayer from '@geoblocks/ol-maplibre-layer';
import { Amplify } from 'aws-amplify';
import { Auth } from 'aws-amplify';
import { Geo, AmazonLocationServiceMapStyle } from '@aws-amplify/geo';
import awsconfig from './aws-exports';
import { AmplifyMapLibreRequest } from 'maplibre-gl-js-amplify';

Amplify.configure(awsconfig);
const credentials = await Auth.currentCredentials();
const defaultMap = Geo.getDefaultMap() as AmazonLocationServiceMapStyle;
const { transformRequest } = new AmplifyMapLibreRequest(
    credentials,
    defaultMap.region
);

const map = new Map({
    target: 'map',
    layers: [
        new MapLibreLayer({
            maplibreOptions: {
                style: Geo.getDefaultMap().mapName,
                transformRequest: transformRequest,
            },
            source: new Source({
                attributions: [
                    '© 2022 HERE',
                ],
                attributionsCollapsible: false,
            }),
        }),
    ],
    view: new View({
        center: fromLonLat([139.767, 35.681]),
        zoom: 11,
    }),
});

map.addControl(new ScaleLine({
    units: 'metric'
}));
```

#### vite.config.ts

```typescript
import { defineConfig } from 'vite'

export default defineConfig({
  resolve: {
    alias: {
      './runtimeConfig': './runtimeConfig.browser',
    },
  },
  define: {
    'window.global': {}
  },
  build: {
    target: 'esnext'
  },
})
```

#### @geoblocks/ol-maplibre-layer.d.ts

```typescript
declare module '@geoblocks/ol-maplibre-layer';
```

Start local server

```bash
npm run dev
```

![img](https://day-journal.com/memo/images/builders-flash/202301_use-map-library-location-service/openlayers_als.png)  

<br>

### Leaflet

#### File Configuration

```sh
.
├── LICENSE
├── README.md
├── amplify
├── dist
│   ├── assets
│   ├── img
│   └── index.html
├── docs
├── img
├── index.html
├── package-lock.json
├── package.json
├── public
├── src
│   ├── aws-exports.js
│   ├── main.ts
│   ├── style.css
│   └── vite-env.d.ts
├── tsconfig.json
└── vite.config.ts
```

#### main.ts

```typescript
import './style.css';
import 'leaflet/dist/leaflet.css';
import L from 'leaflet';
import '@maplibre/maplibre-gl-leaflet';
import { Amplify } from '@aws-amplify/core';
import { Auth } from '@aws-amplify/auth';
import { Geo, AmazonLocationServiceMapStyle } from '@aws-amplify/geo';
import awsconfig from './aws-exports';
import { AmplifyMapLibreRequest } from 'maplibre-gl-js-amplify';
L.Icon.Default.imagePath = 'img/icon/';

Amplify.configure(awsconfig);
const credentials = await Auth.currentCredentials();
const defaultMap = Geo.getDefaultMap() as AmazonLocationServiceMapStyle;
const { transformRequest } = new AmplifyMapLibreRequest(
    credentials,
    defaultMap.region
);

const map = L.map('map', {
    center: [35.681, 139.767],
    zoom: 11,
    layers: [
        L.maplibreGL({
            style: Geo.getDefaultMap().mapName,
            transformRequest: transformRequest,
        })
    ],
});
map.attributionControl.addAttribution(
    '© 2022 HERE'
);
```

#### vite.config.ts

```typescript
import { defineConfig } from 'vite'

export default defineConfig({
  resolve: {
    alias: {
      './runtimeConfig': './runtimeConfig.browser',
    },
  },
  define: {
    'window.global': {}
  },
  build: {
    target: 'esnext',
    commonjsOptions: {
      ignoreDynamicRequires: true
    }
  }
})
```

Start local server

```bash
npm run dev
```

![img](https://day-journal.com/memo/images/builders-flash/202301_use-map-library-location-service/leaflet_als.png)  

<br>

## Summary

With Amazon Location Service and AWS Amplify, it is possible to build location-based applications using a variety of map libraries. By having a wider choice of map libraries, you can introduce the Amazon Location Service to existing applications and choose the technology you want when building a new application. I hope this example will be helpful to those building location-based applications on AWS!

<br>

The pre-built samples introduced here are available on the official AWS repository and other sites, so please look at them for reference.

MapLibre GL JS & Amazon Location Service & AWS Amplify
[amazon-location-service-starter](https://github.com/dayjournal/amazon-location-service-starter)
OpenLayers & Amazon Location Service & AWS Amplify
[openlayers-amplify](https://github.com/aws-samples/amazon-location-samples/tree/main/openlayers-amplify)
Leaflet & Amazon Location Service & AWS Amplify
[leaflet-amplify](https://github.com/aws-samples/amazon-location-samples/tree/main/leaflet-amplify)

<br>

Unofficially, I distribute monthly updates of Amazon Location Service.
[Monthly Amazon Location Service Updates (JPN)](https://day-journal.com/memo/tags/Monthly-Amazon-Location-Service-Updates)
[Monthly Amazon Location Service Updates (ENG)](https://dev.to/t/amazonlocationserviceupdates)

<br>

Related Articles
{% link https://dev.to/aws-heroes/building-a-map-application-with-amazon-location-service-leaflet-and-aws-amplify-5gbe %}
{% link https://dev.to/aws-heroes/building-a-map-application-with-amazon-location-service-openlayers-and-aws-amplify-2f54 %}
{% link https://dev.to/aws-heroes/vite-support-for-various-map-library-starters-4m82 %}
{% link https://dev.to/aws-builders/a-summary-of-how-to-build-amplify-geo-and-amazon-location-service-5hal %}

<br>

References
[Amazon Location Service](https://aws.amazon.com/location)
[AWS Amplify](https://aws.amazon.com/amplify)
[MapLibre GL JS](https://maplibre.org)
[OpenLayers](https://openlayers.org)
[Leaflet](https://leafletjs.com)