gfw-mapbuilder
A library to build custom Forest Atlas web applications.
https://github.com/wri/gfw-mapbuilder
Category: Biosphere
Sub Category: Forest Observation and Management
Keywords
esri-js gfw website
Keywords from Contributors
gfw-fires forest-atlas
Last synced: about 19 hours ago
JSON representation
Repository metadata
Template for the GFW Map Builder that is available through ArcGIS Online, as a stand-alone web application, & a library to build custom Forest Atlas web applications
- Host: GitHub
- URL: https://github.com/wri/gfw-mapbuilder
- Owner: wri
- License: mit
- Created: 2016-03-04T20:08:54.000Z (almost 10 years ago)
- Default Branch: develop
- Last Pushed: 2025-12-05T22:05:36.000Z (20 days ago)
- Last Synced: 2025-12-07T15:40:16.433Z (18 days ago)
- Topics: esri-js, gfw, website
- Language: TypeScript
- Homepage: https://my.gfw-mapbuilder.org/v1.latest/
- Size: 63.2 MB
- Stars: 35
- Watchers: 19
- Forks: 11
- Open Issues: 42
- Releases: 27
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
README.md
GFW Mapbuilder Project Overview
This document provides a comprehensive overview of the GFW Mapbuilder application, including its architecture, project structure, and primary functionalities.
1. High-Level Summary
The GFW Mapbuilder is a web application designed to display and interact with geospatial data through a configurable map interface. It is built as a template for ArcGIS Online, allowing for easy deployment and customization. The application leverages the Esri ArcGIS API for JavaScript to handle map rendering and data visualization, with a frontend built on React and TypeScript.
The core philosophy of the Mapbuilder is to be highly configurable. Most of the application's features, including the layers displayed on the map, the layout of the UI, and even language translations, are controlled by external configuration files. This allows for the creation of different map applications for various regions or purposes without modifying the core source code.
GFW Map Builder ArcGIS Online Template
Template for the GFW Map Builder that will be available through ArcGIS Online.
Getting Started
Before you can begin, make sure you have node.js.
Env variables
Create .env file at the root of the project and add REACT_APP_PLANET_API_KEY checkout .env.examples file.
Reach out to point of contact for Mapbuilder and ask for api key
Make sure you are using Node version 16x or greater
Install all the javascript dependencies.
npm install
Start the server and then the app will be served at http://localhost:3000.
npm start
Generating a build
You will need node.js installed for these steps
Run the following command to generate a build to the webpackBuild directory.
npm run build
Configuring
This application has a general (resources.js). file that contains things controlled by the developers. Also, the Resources file contains configurations that are controlled via ArcGIS Online or whomever may be deploying the application. You can control things like the layers in the accordion, their source urls, their order on the map and in the UI, service urls (print, geometry, map, etc.), which layers to include in the analysis, and even the configurations for slope analysis and other aspects of the analysis. Anything that needs to be controlled from ArcGIS Online or the person deploying it, should be placed in resources.js.
Adding or updating core layers for MapBuilder
Layer configuration is located atconfigs/layers/*
To Update layer config:
- To update layer configuration navigate to the
configs/layers/, open the index.ts file - If you were to update ** Glad Alerts ** layer label for example, navigate to
configs/layers/glad-alerts/index.ts
To Add a new layer config:
-
For consistency folder name is the same as layer name,
glad-alerts -
Navigate to
configs/, create a folder inside layers folder, make sure folder name matches the layer name for consistency. -
Once folder created, create an
index.tsfile and add your new layer configuration. -
If you are not sure about the expected config schema, you can also reference any of the other layers OR
there is also a a schema example of what is expected inconfigs/layers/types/index.tsthat you can also reference. -
Once new config layer is created, you need to import your new layer configuration to
configs/layers/layers-content-config.ts. -
import your new layer configuration from here, for example:
import newLayerConfig from './new-layer-config' -
Lastly, add your imported layer configuration to
layersContentConfiglist
Configuring Layers and Accordions
The layers and the accordion are now more easily configurable via the resources.js file. Layers that you want to appear on the map but not in the accordion should be placed under extraLayers. The configuration structure is as follows:
GROUP_LCD: {
order: 1,
label: {
en: 'Land Cover Dynamics',
fr: 'Evolution de l\'occupation des sols',
es: 'Dinámica de la Cobertura del Suelo',
pt: 'Land Cover Dynamics',
id: 'Land Cover Dynamics',
zh: '土地覆盖动态数据'
},
layers: [{
order: 1,
id: 'TREE_COVER_LOSS',
type: 'image',
url: 'https://gis-treecover.wri.org/arcgis/rest/services/ForestCover_lossyear_density/ImageServer',
technicalName: 'tree_cover_loss',
legendLayer: 0,
colormap: [[1, 219, 101, 152]],
inputRange: [1, 15],
outputRange: [1],
label: {
en: 'Tree cover loss',
fr: 'Perte en couvert arboré',
es: 'Pérdida de la cobertura arbórea',
pt: 'Tree cover loss',
id: 'Tree cover loss',
zh: '森林覆盖损失'
},
sublabel: {
en: '(annual, 30m, global, Hansen/UMD/Google/USGS/NASA)',
fr: '(annuel, 30m, global, Hansen/UMD/Google/USGS/NASA)',
es: '(anual, 30m, global, Hansen/UMD/Google/USGS/NASA)',
pt: '(annual, 30m, global, Hansen/UMD/Google/USGS/NASA)',
id: '(annual, 30m, global, Hansen/UMD/Google/USGS/NASA)',
zh: '(每年更新, 30米, 全球覆盖, 汉森/马里兰大学/谷歌/美国地质测量局(USGS)/美国宇航局(NASA))'
}
}]
}
Properties for the groups and layers are described in detail in the resources file, but here is a brief description of what you see above as well:
GROUP_LCD- Unique key to contain all the properties for the group, this is an accordion section in the layer panelorder- Order that the group will appear in the UI and the order in which it's layers will appear on the map. Anorderof 1 will be above anorderof 2 in the UI and the map. MINIMUM is 1, value of 0 may result in layers being placed under the basemap.label- Object containing keys for various languages, this is the label in the UI for the accordion section.layers- an array of layers that will appear in this accordion. Some layers have custom configurations and some support different options for different types of layers.order- order of the layer in the accordion and on the the map. This order is relative to this section. Layers more or less will be stacked similar to how they appear in the UI with the exception of feature/graphics layers as they always go on top. In the below example, layer A will be on top even though it has a higher order because the group it belongs to has a lower order, meaning the group and the layer will appear first:- Group 1 - order 1
- Layer A - order 5
- Group 2 - order 2
- Layer B - order 1
- Group 1 - order 1
id- Unique ID for the layer, this must be unique across the whole app, not just the grouptype- Type of layer. Currentlytiled,webtiled,image,dynamic,feature,graphic,glad, andterraare supported types.visible- default layer visibility. Default value if not supplied is false.url- required for all layers except graphics layers.technicalName- key for this layer to retrieve metadata about it from the GFW metadata APIlegendLayer- If this layer has no legend or a bad legend, and has an alternative one available here,http://gis-gfw.wri.org/arcgis/rest/services/legends/MapServer, you can provide the layer id of it's legend here so the app can pull that legend in.layerIds- An array of layer ids for dynamic layers, should look like this:[0, 1, 2, 3]or[1].label- An object of keys representing various languages, this is the label that shows in the UIsublabel- An object of keys representing various languages, this is the sublabel that shows in the UIpopup- See below for more explanation and an example of how to use this
Adding Additional Groups
We are now supporting the ability to add additional group accordions to the layer panel. To add a new group, simply add another entry into the layerPanel object (described above in the 'Configuring' section). Below is an example group that you can copy and paste into the layerPanel object and edit to the configuration that you need. Follow any instructions/suggestions in the commented lines (preceded by //), then be sure to delete any commented lines before you save. Any properties that are commented out are optional, you may safely delete those if they are not needed for your group (exceptions will be noted below).
// Change the group name to something descriptive and unique. It should be all caps with words separated by underscores.
GROUP_NAME: {
// Properties must not be duplicated. One groupType is required. Choose one and uncomment it, then delete the others.
// groupType: 'checkbox',
// groupType: 'radio',
// groupType: 'nested',
// Edit the order of this group and the other groups. This determines the order they appear in the layer panel.
order: 1,
label: {
// Edit the group label, this can be anything you want it to be
en: 'Group Label',
// Optionally add labels for additional languages (see the section on Strings and Translations below).
// fr: 'Label for French Language'
},
layers: [
// Uncomment the layer item under the corresponding groupType that you selected earlier, then duplicate for any additional layers in this group.
// CHECKBOX
// {
// Required - the layer id generated from your AGOL webmap
// id: 'layer_id_1234',
// Required - the order that you would like this layer to appear within the group accordion section (1 will appear ABOVE 2)
// order: 1,
// Optional - sublabel for the layer
// sublabel: {
// en: 'Layer sublabel',
// fr: 'Sublabel for French Language'
// }
// }
// RADIO
// {
// Required - the layer id generated from your AGOL webmap
// id: 'layer_id_1234',
// Required - the order that you would like this layer to appear within the group accordion section
// order: 1,
// If this is a MapServiceLayer you must include the following property. This lets the application know which sublayers you would like included in this group.
// includedSublayers: [0, 1, 2, 3],
// Optional - the sublabel for the layer.
// sublabel: {
// en: 'Layer Sublabel',
// fr: 'Sublabel for French Language'
// }
// Note: If this is a MapServiceLayer, the sublayer that the sublabel belongs to must be specified.
// sublabel: {
// 0: {
// en: 'Sublayer 0 Sublabel',
// fr: 'Sublayer 0 Sublabel for French Language'
// },
// 1: {
// en: 'Sublayer 1 Sublabel',
// fr: 'Sublayer 1 Sublabel for French Language'
// }
// }
// }
// NESTED
// {
// Required - the order that you would like this layer grouping to appear within the group accordion section
// order: 1,
// Required - the label of the nested layer grouping
// label: {
// en: 'Nested grouping label',
// fr: 'Nested grouping label for French Language'
// },
// Required - the layers that will appear in this grouping
// nestedLayers: [
// {
// Required - the layer id generated from your AGOL webmap
// id: 'layer_id_1234',
// Required - the order that you would like this layer to appear within the nested grouping
// order: 1,
// Optional - sublabel for the layer
// sublabel: {
// en: 'Layer sublabel',
// fr: 'Sublabel for French Language'
// }
// }
// ]
// }
]
},
Configuring Popups for layers not in Webmaps
This is currently only supported for dynamic layers and feature layers. A popup configuration has some elements it must contain to keep the styling looking appropriate and they are outlined below. Here is an example layer configuration that contains a popup configuration (NOTE the addition of popup at the bottom):
order: 6,
id: 'ACTIVE_FIRES',
type: 'dynamic',
url: 'http://gis-potico.wri.org/arcgis/rest/services/Fires/Global_Fires/MapServer',
technicalName: 'noaa18_fires',
layerIds: [0, 1, 2, 3],
label: {
...
},
sublabel: {
...
},
popup: {
title: {
en: 'Active Fires'
},
content: {
en: [
{'label': 'Brightness', 'fieldExpression': 'BRIGHTNESS'},
{'label': 'Confidence', 'fieldExpression': 'CONFIDENCE'},
{'label': 'Latitude', 'fieldExpression': 'LATITUDE'},
{'label': 'Longitude', 'fieldExpression': 'LONGITUDE'},
{'label': 'Acquisition Date', 'fieldExpression': 'ACQ_DATE:DateString(hideTime:true)'},
{'label': 'Acquisition Time', 'fieldExpression': 'ACQ_TIME'}
]
}
}
This way you can add more languages and also use modifiers on fields. fieldExpression get's used in the same manner the JSAPI uses fields for popup content, in a string like so: '${BRIGHTNESS}'. This is why we can use modifiers like ACQ_DATE:DateString(hideTime:true). You can see a list of available modifiers here: Format info window content
Core Technologies
The application is built with a modern web stack:
- Frontend Framework: React with TypeScript for building a component-based, type-safe user interface.
- State Management: Redux for centralized and predictable application state management.
- Mapping Library: ArcGIS API for JavaScript for all geospatial functionality, including map rendering, layer management, and spatial analysis.
- Build System: Webpack is used to bundle the application for development and production, with configurations for code splitting, optimization, and asset management.
- Styling: SCSS and Styled Components for styling the application.
- End-to-End Testing: Cypress for automated end-to-end testing of the application.
Project Structure
The project is organized into several key directories:
-
/src: This is the main directory for the application's source code./src/js: Contains the core TypeScript and React code./components: This directory holds the React components that make up the UI. It is further subdivided by feature, such asheader,leftPanel,mapview, andreport./store: The Redux store is defined here, with subdirectories foractions,reducers, andtypes. This manages the global state of the application./layers: Contains definitions and logic for the various types of map layers the application can display (e.g.,GladLayer,TreeCoverLossLayer)./helpers: A collection of utility functions and helper classes used throughout the application. Key helpers includeLayerFactory.tsfor creating layer instances andmapController.tsfor managing the map./controllers: Contains the main application logic, such as themapController.tswhich orchestrates map interactions.index.tsx: The main entry point of the application, where the React application is rendered and the Redux store is initialized.
/src/css: Contains the SCSS stylesheets for the application./src/assetsand/src/images: Static assets like icons, images, and fonts.index.html: The main HTML file that serves as the entry point for the web application.
-
/configs: This directory is central to the application's configurability.resources.js: The main configuration file for the application. It defines the web map ID, layers, UI elements, themes, and other application-level settings./layers: Contains detailed configurations for individual data layers./translations: Holds the language files for internationalization./countryConfigs: Provides specific configurations for different countries or regions.
-
/webpack.*.js: Webpack configuration files for different environments (common,development,production). -
/cypress: Contains the end-to-end tests for the application. -
package.json: Defines the project's dependencies, scripts, and metadata. -
tsconfig.json: The configuration file for the TypeScript compiler.
Architecture and Data Flow
The application follows a modern, component-based architecture with a centralized state management pattern.
-
Application Initialization: The application starts with
src/js/index.tsx. This file renders the mainAppcomponent and injects the Redux store, making the application state available to all components. -
Configuration Loading: On startup, the application loads its configuration from
configs/resources.jsand other files in the/configsdirectory. This configuration object dictates which layers are available, how the UI is structured, and what tools are enabled. -
State Management (Redux): The Redux store serves as the single source of truth for the application state. This includes the current language, the visibility of layers, user information, and the state of various UI components. Actions are dispatched to update the state, and reducers specify how the state changes in response to these actions.
-
Component-Based UI (React): The user interface is built as a tree of React components. These components are organized by feature in the
/src/js/componentsdirectory. Components can subscribe to the Redux store to access and display application state, and they can dispatch actions to trigger state changes. -
Map Interaction (ArcGIS API): The
mapController.tsis a key component that manages the ArcGIS map. It is responsible for:- Initializing the map with the configured basemaps and extent.
- Using the
LayerFactory.tsto create instances of map layers based on the configuration inresources.js. - Handling user interactions with the map, such as clicks, zooms, and pans.
- Toggling the visibility of layers based on user input from the UI.
-
Dynamic Layer Generation: One of the primary capabilities of the Mapbuilder is its ability to dynamically generate and manage map layers. The
LayerFactory.tsreads the layer configurations fromresources.jsand creates the appropriate layer objects using the ArcGIS API. This allows for a flexible and easily customizable map experience.
Deployment
see deployment.md
Owner metadata
- Name: World Resources Institute
- Login: wri
- Email: datalab@wri.org
- Kind: organization
- Description:
- Website: https://wri.org
- Location: Washington, DC
- Twitter:
- Company:
- Icon url: https://avatars.githubusercontent.com/u/4615146?v=4
- Repositories: 207
- Last ynced at: 2024-04-14T16:16:20.039Z
- Profile URL: https://github.com/wri
GitHub Events
Total
- Watch event: 2
- Delete event: 19
- Issue comment event: 6
- Push event: 49
- Pull request review comment event: 1
- Pull request review event: 7
- Pull request event: 44
- Fork event: 1
- Create event: 24
Last Year
- Watch event: 2
- Delete event: 18
- Issue comment event: 6
- Push event: 42
- Pull request review comment event: 1
- Pull request review event: 6
- Pull request event: 42
- Fork event: 1
- Create event: 23
Committers metadata
Last synced: 17 days ago
Total Commits: 4,149
Total Committers: 28
Avg Commits per committer: 148.179
Development Distribution Score (DDS): 0.798
Commits in past year: 141
Committers in past year: 4
Avg Commits per committer in past year: 35.25
Development Distribution Score (DDS) in past year: 0.319
| Name | Commits | |
|---|---|---|
| Vaidotas Piekus | v****p@g****m | 837 |
| Kayla Kremer | k****a@g****m | 715 |
| Lucas Cotner | l****7@u****u | 666 |
| Eden | e****n@g****m | 385 |
| Patrick Moran | p****n@b****m | 300 |
| Robert Winterbottom | r****m@b****m | 197 |
| Anthony Amaro | a****o@A****l | 184 |
| dstarr | d****r@b****m | 176 |
| Anthony Amaro | a****5@g****m | 140 |
| Jennifer Boyd | j****d@b****m | 124 |
| davidlstarr | d****r@h****m | 120 |
| Timur Girgin | t****n@b****m | 78 |
| Nick Bumbarger | n****r@g****m | 61 |
| Thomas Maschler | t****r@w****g | 40 |
| dependabot[bot] | 4****] | 34 |
| Anthony | a****o@A****l | 30 |
| Richard Barad | r****d@w****g | 15 |
| bzivkovic | b****c@b****m | 9 |
| Djoan | d****s@w****g | 8 |
| Timur Girgin | g****r@g****m | 8 |
| swingley | s****y@g****m | 5 |
| Eric M Kerney | 9****y | 5 |
| Lucas Cotner | l****r@c****m | 3 |
| Caio de Araujo Barbosa | c****a@g****m | 3 |
| Asa Strong | a****g@w****g | 2 |
| mweisse | m****e | 2 |
| Thomas Maschler | T****r@w****g | 1 |
| Christina Phang | c****g@b****m | 1 |
Committer domains:
- blueraster.com: 7
- wri.org: 5
- climate.com: 1
- uw.edu: 1
Issue and Pull Request metadata
Last synced: 19 days ago
Total issues: 495
Total pull requests: 980
Average time to close issues: 4 months
Average time to close pull requests: 11 days
Total issue authors: 12
Total pull request authors: 19
Average comments per issue: 2.37
Average comments per pull request: 0.26
Merged pull request: 875
Bot issues: 0
Bot pull requests: 53
Past year issues: 0
Past year pull requests: 42
Past year average time to close issues: N/A
Past year average time to close pull requests: 12 days
Past year issue authors: 0
Past year pull request authors: 3
Past year average comments per issue: 0
Past year average comments per pull request: 0.05
Past year merged pull request: 26
Past year bot issues: 0
Past year bot pull requests: 7
Top Issue Authors
- richardbarad (141)
- csphang (127)
- vaidotasp (97)
- eyosef (64)
- SwampGuzzler (36)
- k-kresek (19)
- davidlstarr (4)
- palmernet (2)
- KaylaKremer (2)
- pkmoran (1)
- jenboyd (1)
- jequihua (1)
Top Pull Request Authors
- vaidotasp (170)
- SwampGuzzler (165)
- KaylaKremer (123)
- anthonyamaro15 (121)
- pkmoran (111)
- eyosef (102)
- davidlstarr (68)
- dependabot[bot] (53)
- jenboyd (25)
- tgirgin23 (18)
- thomas-maschler (7)
- Robert-W (4)
- nbumbarger (3)
- eKerney (3)
- richardbarad (2)
Top Issue Labels
- 4.x Upgrade (151)
- high priority (49)
- bug (36)
- low priority (27)
- medium priority (19)
- HOLD (17)
- in-contract (13)
- HIGHEST priority (10)
- Code Cleanup (9)
- share-functionality (5)
- WCS (4)
- quick PR (3)
- performance (2)
- typescript (2)
- hacktoberfest (1)
- blocked (1)
Top Pull Request Labels
- 4.x Upgrade (218)
- READY FOR REVIEW (91)
- dependencies (54)
- DO NOT MERGE (17)
- bug (16)
- quick PR (8)
- HOLD (8)
- javascript (7)
- Client Testing (5)
- WCS (5)
- Code Cleanup (4)
- high priority (3)
- share-functionality (3)
- Exemplar (3)
- HIGHEST priority (2)
- typescript (2)
- hacktoberfest (1)
Package metadata
- Total packages: 1
- Total downloads: unknown
- Total dependent packages: 0
- Total dependent repositories: 0
- Total versions: 34
proxy.golang.org: github.com/wri/gfw-mapbuilder
- Homepage:
- Documentation: https://pkg.go.dev/github.com/wri/gfw-mapbuilder#section-documentation
- Licenses: mit
- Latest release: v1.5.1 (published almost 5 years ago)
- Last Synced: 2025-12-08T12:09:41.177Z (17 days ago)
- Versions: 34
- Dependent Packages: 0
- Dependent Repositories: 0
-
Rankings:
- Dependent packages count: 5.395%
- Average: 5.576%
- Dependent repos count: 5.758%
Dependencies
- 1950 dependencies
- @types/lodash-es ^4.17.3 development
- @types/node ^13.1.4 development
- @types/rc-slider ^8.6.6 development
- @types/react ^16.9.17 development
- @types/react-datepicker ^4.1.3 development
- @types/react-dom ^16.9.4 development
- @types/react-measure ^2.0.6 development
- @types/react-redux ^7.1.5 development
- @types/react-select ^3.0.11 development
- @types/redux-logger ^3.0.7 development
- @typescript-eslint/eslint-plugin ^2.15.0 development
- @typescript-eslint/parser ^2.15.0 development
- clean-webpack-plugin ^3.0.0 development
- compression-webpack-plugin ^3.0.1 development
- copy-webpack-plugin ^5.1.1 development
- css-loader ^3.4.1 development
- cypress ^6.9.1 development
- enzyme ^3.11.0 development
- eslint ^6.8.0 development
- eslint-config-prettier ^6.9.0 development
- eslint-plugin-jsx-a11y ^6.2.3 development
- eslint-plugin-react ^7.17.0 development
- eslint-plugin-react-hooks ^2.3.0 development
- file-loader ^6.2.0 development
- html-loader ^0.5.5 development
- html-webpack-plugin ^3.2.0 development
- husky ^4.0.0 development
- mini-css-extract-plugin ^0.9.0 development
- node-sass ^4.13.0 development
- prettier ^2.6.2 development
- pretty-quick ^2.0.1 development
- redux-devtools-extension ^2.13.8 development
- redux-logger ^3.0.6 development
- resolve-url-loader ^3.1.1 development
- sass-loader ^8.0.0 development
- style-loader ^1.1.2 development
- terser-webpack-plugin ^2.3.1 development
- ts-loader ^8.0.17 development
- tslib ^1.10.0 development
- typescript ^4.4.4 development
- url-loader ^3.0.0 development
- webpack ^4.20.1 development
- webpack-cli ~3.3.5 development
- webpack-dev-server ^3.1.10 development
- webpack-hasjs-plugin ^1.0.3 development
- webpack-merge ^4.2.2 development
- @material-ui/core ^4.10.2
- @material-ui/lab ^4.0.0-alpha.56
- @types/arcgis-js-api ~4.18.0
- @types/react-beautiful-dnd ^13.1.2
- @types/styled-components ^5.1.15
- clsx ^1.1.1
- date-fns ^2.11.1
- esri-loader ^3.0.0
- immer ^9.0.12
- lodash-es ^4.17.15
- png-ts 0.0.3
- rc-slider ^9.7.1
- react ^17.0.2
- react-beautiful-dnd ^13.1.0
- react-datepicker ^4.1.1
- react-dom ^17.0.2
- react-hook-form 7.17.5
- react-measure ^2.3.0
- react-redux ^7.1.3
- react-select ^3.1.0
- react-spinners-css 2.0.1
- react-tooltip 4.2.21
- redux ^4.0.5
- reselect ^4.0.0
- styled-components ^5.3.3
- xml-js ^1.6.11
- actions/checkout master composite
- actions/setup-node v1 composite
- blueraster/action-slack master composite
- blueraster/s3-sync-action master composite
- actions/checkout master composite
- actions/setup-node v1 composite
- aws-actions/configure-aws-credentials v1 composite
Score: -Infinity