# About Webgeoda Scaffolding

### <<<<<<<< HEAD:README.md

description: >- WebGeoDa scaffolding is a set of toolkits to get started building and

### exploring geospatial data with easy to use frontend templates.

## About Webgeoda Scaffolding

### What is this thing?

WebGeoDa is a set of tools, templates, and scaffolding to quickly and easily develop geospatial data dashboards. WebGeoDa builds on the GeoDa suite of geospatial software and extends jsGeoDa through accessible and ready-to-go examples.

### What can WebGeoDa do?

WebGeoDa focuses on enabling exploratory data dashboards with complex data, the need for diverse variables, and high performance in-browser analytics. You can make maps with a variety of color-binning techniques and spatial statistical methods, like Hotspot cluster analysis, through a simple JSON based data and variable configuration.

### What do I need to get started?

To get started with WebGeoDa, you'll need:

* A Javascript package manager - `Yarn` or `NPM`
* `Degit`, a package to copy Github repositories (or you can directly fork the WebGeoDa example repository)
* A little bit of experience with HTML and JSON
* Your code editor of choice

*Don't worry, we'll walk through this in the* [*Getting Started*](/main/getting-started) *docs*

WebGeoDa is based on Next.js and React, although we've worked to keep much of the syntax as familar to users of Vanilla Javascript, HTML, and CSS. The ecosystem of JavaScript frameworks has become a complex place, and this project serves as a scaffolding to make jumping in a little bit easier.

### License and Ownership

#### GPL-3 (Gnu Public License)

This project is licensed under GPL-3, meaning you're free to use this for whatever you'd like! *However,* your project must be shared under the same license.

#### Ownership

Very intentionally, WebGeoDa doens't require your data to be uploaded to an external server, and you control when and where your WebGeoDa dashboard exists. There is no proprietary service that you're connected to, and you can run this locally for your own purposes, on a personal webserver, or through a host of different deploying options.

\========

## Introduction

> > > > > > > > main:readme.md


# Getting Started

Let's do this thing.

## Installing Node.js / NPM

To get start, install [Node.js](https://nodejs.org/en/) from Node's site, or [your package manager of choice](https://nodejs.org/en/download/package-manager/). For advanced usage [Node Version Manager (nvm)](https://github.com/nvm-sh/nvm#installing-and-updating) may be useful.

**Optionally,** install `Yarn`, which tends to make dependency management a bit less painful. After installing `Node`/`npm`:

```bash
npm install --global yarn
```

## Installing Degit

The easiest way to get start with WebGeoDa scaffolding is with [`Degit`](https://github.com/Rich-Harris/degit). Install `Degit` with:

```bash
npm i -g degit
```

**Alternatively** you can fork the repository directly [@nofurtherinformation/webgeoda](https://github.com/nofurtherinformation/webgeoda).

## Scaffolding Your Project

Next, in your terminal, you can create a new WebGeoDa scaffolding like this:

{% tabs %}
{% tab title="Yarn" %}

```bash
npx degit nofurtherinformation/webgeoda my-webgeoda-project
cd my-webgeoda-project

yarn
```

{% endtab %}

{% tab title="NPM" %}

```bash
npx degit nofurtherinformation/webgeoda my-webgeoda-project
cd my-webgeoda-project

npm install
```

{% endtab %}
{% endtabs %}

## Mapbox API Key

Mapbox tiles are the default background tiles for WebGeoDa scaffolding's maps. If you want to use [Mapbox](https://www.mapbox.com/), make an account and generate an API token. Then, create a file called `.env.local` in the project root folder with your API key as shown below:

```
NEXT_PUBLIC_MAPBOX_TOKEN=pk.abcdefg01189998819991197253...
```

## Starting the Dev Server

To run the local development server, open your terminal and get started like so:

{% tabs %}
{% tab title="Yarn" %}

```bash
yarn dev
```

{% endtab %}

{% tab title="NPM" %}

```bash
npm run dev
```

{% endtab %}
{% endtabs %}

## We're in.

You now have the basic WebGeoDa scaffolding ready to go! From here, why not [add some data](https://github.com/nofurtherinformation/webgeoda-gitbook/tree/e7c5f1171692ee9ee9265cd6740ccf40ec01cf9d/data/import.md), [customize static pages](https://github.com/nofurtherinformation/webgeoda-gitbook/tree/e7c5f1171692ee9ee9265cd6740ccf40ec01cf9d/pages/static/readme.md), or check out the default [file structure](https://github.com/nofurtherinformation/webgeoda-gitbook/tree/e7c5f1171692ee9ee9265cd6740ccf40ec01cf9d/data/file-structure.md) to see how things fit together?


# Importing Data


# Creating Variables


# Binning Types


# Map Modes


# Variable Specification


# File Structure


# Making an API


# Static Pages


# Adding and Customizing Pages


# Styling and CSS Modules


# Map Customization


# Change Tooltip and Data Sidebar Information


# Modifying Layers


# Netlify


# Vercel


# Github Pages


# Elsewhere!


# jsGeoDa


# Next.JS


# Alternate Map Views


# Binary Data Formats


# About Webgeoda Scaffolding

WebGeoDa Scaffolding is a set of easy-to-use frontend JavaScript toolkits to get started building and exploring client-side geospatial analytics.

## About Webgeoda Scaffolding

### What is this thing?

WebGeoDa is a set of tools, templates, and scaffolding to quickly and easily develop geospatial data dashboards. WebGeoDa builds on the GeoDa suite of geospatial software and extends jsGeoDa through accessible and ready-to-go examples.

WebGeoDa capabilities have four areas of complexity. It's easy to learn, but with a high ceiling for customization:\
\
‍💻 Add your geospatial data (GeoJSON), join it to your tabular data (CSV) right in the browser. Specify your variables with a simple JSON specification, and your map is ready to be published!

**📑** Customize and add static pages to describe your data and the context of your dashboard. WebGeoDa provides some built-in styling tools using Plain CSS and a reasonably approachable JSX, similar to HTML.

**🗺** Add additional map features using Mapbox and Deck.gl, or explore additional data insights through interactive tooltip and sidebar functions.

**🦺** Dive directly into the WebGeoDa scaffolding with full control over custom react hooks, the jsGeoDa WebAssembly + WebWorker geospatial engine, a fast Redux-backed state, and extensible and accessible components.&#x20;

#### Here's a demo

{% embed url="<https://webgeoda.netlify.app/map>" %}

### What can WebGeoDa do?

WebGeoDa focuses on enabling exploratory data dashboards with complex data, the need for diverse variables, and high performance in-browser analytics. You can make maps with a variety of color-binning techniques and spatial statistical methods, like Hotspot cluster analysis, through a simple JSON based data and variable configuration.

### What do I need to get started?

To get started with WebGeoDa, you'll need:

* `Node.js`and know how use the terminal
* `Degit`, a package to copy Github repositories (or you can directly fork the WebGeoDa example repository)
* Some experience with HTML and JSON to get started, JavaScript to dive deeper

*Ready to get going? See the* [*Getting Started*](/getting-started) *docs*

WebGeoDa is based on Next.js and React, although we've worked to keep much of the syntax as familiar to users of Vanilla Javascript, HTML, and CSS. The ecosystem of JavaScript frameworks has become a complex place, and this project serves as a scaffolding to make jumping in a little bit easier.

### License and Ownership

#### GPL-3 (Gnu Public License)

This project is licensed under GPL-3, meaning you're free to use this for whatever you'd like! Howeve&#x72;*,* your project should be shared under the same license.

#### Ownership

Very intentionally, WebGeoDa doesn't require your data to be uploaded to an external server, and you control when and where your WebGeoDa dashboard exists. There is no proprietary service that you're connected to, and you can run this locally for your own purposes, on a personal web server, or through a host of different deploying options. Free. Forever.&#x20;

## Introduction


# Data Concepts

Before we dive in, a few ideas to help you connect your data to WebGeoDa.

There are three main data concepts that are important to loading your data in WebGeoDa:

1. **Geospatial data**: Geospatial data (geodata) represents the geospatial data that you'll be working with. Currently, WebGeoDa supports [GeoJSON](https://geojson.org/) or Mapbox Vector Map Tiles ([hosted through Mapbox](https://www.mapbox.com/mts)) as the core polygons that you want to represent. \
   \
   Each geodata needs to have a common identifier column, such as a ZIP code or FIPS code. Ideally, most data about these geographies will be contained in the tables, described below, but having some basic information, such as land area or population may be useful. <br>
2. **Tables:** Tables, or tabular data, should contain most of the information you want to map. These also need a common identifier column that directly reflects the ID column on your geodata. This data can take the form of CSV files, but you can also connect externally to JSON data or a Google Sheet.\
   \
   Each geodata has a set of tables attached to it, from which WebGeoDa will infer which variables are valid for that set of geographies. You can define the same table name for different geographies, allowing you to swap between different geographies for the same variable -- for example, consider exploring unemployment rates at the state, county, and zip code level. Each reveals something different about the spatial patterns through more or less granularity. \
   \
   **Note**: It is critical that all tables present across different geographies have the same available columns. Consider each table name that you define like a preset data schema -- WebGeoDa will use the available tables at different geographies to infer which variables are valid at which geographic scale. If tables of the same name, joined across different spatial scales, have different columns, you may get unexpected results. <br>
3. **Variables:** To define how you want to visualize your data (spatially, and in charts), variables specify the combination of data you want to understand. Each variable needs at minimum a name, data table, column name,  and binning strategy. If you want, you can normalize variables by dividing a numerator and denominator data column in each geography, such as GDP per capita. Variables can also handle time-series data, where you can define a date index rather than a specific column name. \
   \
   Variables are used for both map representations, where each polygon is colored based on the value of the data, and in chart or information representations -- currently supported are distribution graphs of Histograms, 2D Scatterplots, and Scaled Dot 2D Histogram, and Heatmap. WebGeoDa will automatically populate the spatial scales that have the correct tables. WebGeoDa will also automatically swap to the relevant data set when changing variables, if the current geographic scale doesn't have the data needed.&#x20;


# Getting Started

Let's do this thing.

## Installing Node.js / NPM

To get started, install [Node.js](https://nodejs.org/en/) from Node's site, or [your package manager of choice](https://nodejs.org/en/download/package-manager/). For advanced usage [Node Version Manager (nvm)](https://github.com/nvm-sh/nvm#installing-and-updating) may be useful.

**Optionally,** install `Yarn`, which tends to make dependency management a bit less painful. After installing `Node`/`npm`:

```bash
npm install --global yarn
```

## Starting your project

The easiest way to get started with your project is to go to the [webgeoda repo](https://github.com/GeoDaCenter/webgeoda) and click the *use this template* button. That will let you create a new GitHub repository based on the current WebGeoDa release.&#x20;

Once you have your GitHub repo started, clone the repository and open a terminal in your project folder. Run `npm install` to download the required modules.

## Required Environment Variables - Mapbox API Key

Mapbox tiles are the default background tiles for WebGeoDa scaffolding's maps. If you want to use [Mapbox](https://www.mapbox.com/), make an account and generate an API token. Then, create a file called `.env.local` in the project root folder with your API key as shown below:

```
NEXT_PUBLIC_MAPBOX_TOKEN=pk.abcdefg01189998819991197253...
```

## Starting the Dev Server

To run the local development server, open your terminal and get started like so:

{% tabs %}
{% tab title="Yarn" %}

```bash
yarn dev
```

{% endtab %}

{% tab title="NPM" %}

```bash
npm run dev
```

{% endtab %}
{% endtabs %}

## We're in.

You now have the basic WebGeoDa scaffolding ready to go! From here, why not [add some data](https://github.com/nofurtherinformation/webgeoda-gitbook/tree/b570c349ae9c0b81dd465bd8438485784f21956f/data/import.md), [customize static pages](https://github.com/nofurtherinformation/webgeoda-gitbook/tree/b570c349ae9c0b81dd465bd8438485784f21956f/pages/static/readme.md), or check out the default [file structure](https://github.com/nofurtherinformation/webgeoda-gitbook/tree/b570c349ae9c0b81dd465bd8438485784f21956f/data/file-structure.md) to see how things fit together?


# Libraries and Dependencies

AKA What's keeping this thing afloat?

## Framework

WebGeoDa uses [Next.js](https://nextjs.org/), a server-side rendering JavaScript framework by Vercel.

## Geospatial Engine

Our geospatial engine (and namesake) is Dr Xun Li and Dr Luc Anselin's [jsGeoDa](https://xunli.gitbook.io/jsgeoda/), a WebAssembly-based geospatial analysis module. By default, it's accessed in a WebWorker, aka a separate thread, meaning your interface is free for interaction while Geospatial analysis is going on.

## Mapping

By default, mapping is done using [Mapbox](https://www.mapbox.com/) with [Deck.gl](https://deck.gl/) layered on top. In the future, additional map components may be available.

## Visualization and Information Expression

In the works 👀

## State Management

State management is done with [Redux](https://redux.js.org/)/[React-Redux](https://react-redux.js.org/). Redux is a classic, and a good fit here given the frequent state updates, partial state access, and potentially high cost of re-rendering the map. Our built-in actions use just a reducer and inline-actions, rather than an additional actions file:

```javascript
    // some component
    const dispatch = useDispatch(); // send an action to the reducer
    const myFunction = (someData) => {
        dispatch({
            type: 'Very Import Update',
            payload: someData
        })
    }
```

## UI Toolkit

There are numerous UI toolkits available in the React ecosystem, like [React Bootstrap](https://react-bootstrap.github.io/), [Material-UI](https://material-ui.com/), [Ant Design](https://ant.design/), and others.

Our provided UI toolkit focuses on simple, vanilla HTML and CSS focused components and high accessibility. So, we base our interactive components on [Reach UI](https://reach.tech/), a highly accessible foundation for React-based design systems and [Flexbox Grid](http://flexboxgrid.com/), a simple CSS-based column layout tool.

## WebWorker Management

We use [Comlink](https://github.com/GoogleChromeLabs/comlink) to call and manage our WebWorkers. It's lovely.


# File Structure Overview

Where'd everybody go?

Coming from other programming langauges or more classic JavaScript / HTML + CSS projects, the modular file structure in JavaScript framework-based repositories can be unintuitive. There's some definite advantages here, especially while collaborating with others, and things that appear a more helpful than they first appear, like [scoped CSS module](https://github.com/nofurtherinformation/webgeoda-gitbook/tree/1e59f8359e36fb07d698d5c0df416a1f389c3cb9/mdn-docs/README.md). Here's an overview of what's located where.

## Root Folder

In the root folder of your WebGeoDa scaffolding, you'll find a number of configuration files, including `package.json`, which manages the JavaScript package dependencies, meta-information about the project, and `map-config.js`, which holds your geospatial and tabular data specifications, variable definitions, and a few built-in controls for the interface style. There's also the `README`, which you may want to customize for your repo, and additional configuration files for `Next.js` and a few deployment options pre-configured.

## Public

Truth in advertising, the public folder holds all of your public facing static assets that won't be bundled together with your WebGeoDa project at build time. Meaning, your data assets (GeoJSONs, CSVs, etc.) live there. Additionally, any images you want to include should be located there, your favicon, and the provided WebGeoDa WebWorker scripts.

## Pages

In pages, each JavaScript file, like `map.js` represents a page path -- eg. *yourSite.com/map*. `index.js` represents your homepage, and `_app.js` is the script that pulls it all together. By adding a new file in pages, you're creating a new Route to the page - read more about how Next.js handles page routing [here](/file-structure). Removing a page works the same way, remove that file and the page goes away. By default, you'll have pages for `index.js`, `map.js`, and `about.js`.

In pages you'll also find `api`, where you can create API endpoints when deploying your WebGeoDa scaffolding on Vercel. This is extremely useful if you want to create a simple data access pipeline right in your project. For more on creating API routes, see [making an api](/data/making-an-api).

When adding or removing pages, you'll also want to update the Navigation links. You can find the navigation bar component, `MainNav.js` located in `components > layout`. Speaking of which...

## Components

The components folder is the home for your JavaScript components, each one a dimutive unit of code that ideally should do a minimal number of things, but do them well. For instance, the `Legend` component takes a list of colors and labels, then returns a `div` with those organized in a clear way. Components make life easier by reducing the amount of code you ever need to think about at once.

By default, WebGeoDa scaffolding provides folders for layout and map components. In addition to each JavaScript component, most are paired with a CSS Module (eg. `Legend.module.css`). This CSS is scoped just for that component, and imported at the top of each one. This allows for fewer concerns about conflicting styles, and the same benefits of a smaller amount of code in any single file. Oh, since it came up...

## Styles

The styles folder has a few different CSS files that define the styles for your WebGeoDa scaffolding. Each page, (eg. About, Home) has its own CSS module, just like your JavaScript components. Additionally, `global.css` has project-wide styles. This stylesheet is particularly useful for handling things like fonts, interactive elements like buttons, and declaring global CSS colors. Additionally, `grid.css` is borrowed from Kristofer Joseph's excellent *Flexbox Grid* style package, which enables the simple and easy-to-use grid layouts on pages.

## \_webgeoda

This folder has all the WebGeoDa guts, including utilities, data store management, custom React Hooks, and so on. In this folder you'll find:

* `build-scripts`: Build-time scripts for handling a few things, like constructing your cache-management Service Worker
* `constants`: Default data store parameters
* `hooks`: Custom hooks that manage interactions between your data, the data store, and jsGeoDa
* `reducers`: The core function that handles different actions in the data store
* `schemas`: Built-in Protobuffer Schemas
* `utils`: A handful of different utilities, including `colors.js` (built-in color scales), `data.js` (a handful of data parsing utilities), `map.js` (some map helper functions), and so on


# Importing Data

Data, data everywhere. But not a bit to bite.

## Supported Data Formats

WebGeoDa currently supports `GeoJSON` files for geospatial data. Geospatial files must have some kind of feature or geographic ID column. You can import tabular data from `CSV` or from our csv-like [`Protobuffer` schema](https://github.com/nofurtherinformation/webgeoda-gitbook/tree/6b7c6fb5bcce2b83250523ad66e92934bd0e9072/data/advanced/protobuffer.md).

Future versions plan to enable `Shapefile` and `Geobuf` geospatial data support, as well as connections to simple backends like Google Sheets. In the future, we'll connect with more proper backends.

## Importing GeoJSON

To import a GeoJSON, first add your file to `public/geojson`. Next open `map-config.js` in the root directory using your code editor of choice. An example of how you can declare data will greet you there -- you'll see something like this:

```javascript
const data = [
    {
        name: 'Texas Block Groups', // Plain english name for dataset
        geodata: 'tx.geojson', // geospatial data to join to
        id:'GEOID', // fid / geoid join column
        tables: {} // any additional tabular data
    }
]
```

Each geospatial dataset you'll add will need to an object in `data`. Here's the (case sensitive) defails on how this should look:

* `name`: What a human would call your data
* `geojson`: The name of the GeoJSON file in `public/geojson`
* `id`: The join column or feature ID column of your data to join additional tables (commonly, *FIPS*, *GEOID*, etc)
* `tables`: A list of tables you'd like to join on-the-fly to your data - more below

Joining additional tables in the browser means that data can be much better optimized for file transfer size, while still only needing simple, static server requirements. Each table you add in the `tables` property of your data will load with your GeoJSON file if they are in your default variable, or will lazy load after the initial map view. Don't want to keep those users waiting 🤠

## Joining Tables

To add tables, be sure to add your `CSV` file(s) to the `public/csv` folder. Then, you can add entries to each geospatial data's `tables` property:

```javascript
const data = [
    {
        name: 'Texas Block Groups',
        ...
        tables: {
            acs_data: { // data table name
                file:'texas_acs.csv',
                type:'characteristic',
                id:'FIPS'
            }
        }
    }
]
```

* Date Table Name (as a property in `tables`): The name you'd like to refer to this data elsewhere
* `file`: The name of the tabular data file in `public/csv`
* `type`: The type of data included - `characteristic` for simple columns of data, `time-series` or `time-series-cumulative` if you'd like a timeline
* `id`: The join column that should reference your geospatial data
* `dates`: If using time-series data, specify whether your dates are an ISO date format (`YYYY-MM-DD`) or US date format (`MM/DD/YYYY`)

If your GeoJSONs are larger than \~5MB and have a large number of features, we strongly recommend separating out your tabular data. Avoid tabular data in GeoJSON means that the property keys won't get duplicated, and file transfer / parsing time will be reducing.

You can also import `Protobuffer` files using our csv-like schema, allowing for even smaller files when data are particularly large. You can read more about their usage in the [advanced docs](https://github.com/nofurtherinformation/webgeoda-gitbook/tree/6b7c6fb5bcce2b83250523ad66e92934bd0e9072/data/advanced/protobuffer.md).


# Accessing Exernal Data

External data, such as third-party APIs, can be used in place of geospatial or tabular data. By default, any [Cross-Origin](/data/external-data) accessible `GeoJSON` URL can be used in place of a file in `public/geojson` when speccing out your [datasets](/data/external-data), and any `CSV` URL can be used instead of a local file.

Due to the structure of the binning algorithms and clustering analyses at the core of WebGeoDa, tiled data are not currently supported for choropleth layers.

## Coming Soon

* Google Sheets Support
* JSON endpoint support
* Firebase
* Hasura / Supabase
* Elastic Search
* Datasette


# Making an API

Next.js features built-in support for API routes (eg. `my.website/api/data`), meaning that you can easily deploy a simple API alongside your WebGeoDa dashboard. I freaking know, right?

See Next.JS documentation for more:

{% embed url="<https://nextjs.org/docs/api-routes/introduction>" %}


# Overview

Calculating variables on-the-fly is possible with a variety of simple descriptors to derive new fields or use pre-processed data. There are three variable types:

* **Continuous**: Numeric variables on a continuous scale, such as population density or access to internet
* **Categorical**: Ordinal variables with fixed categories for each geography, such as electricity infrastructure, vulnerability category, or any dummy variables.
* **LISA**: *Local Indicator of Spatial Autocorrelation* statistics, which identify significant hotspots, coldspots, and neighboring geographies.

In `map-config.js` in the project root folder, you'll see `variables` where you can define your variables.

```javascript
const variables = [
    {
        variable: "Median age",
        numerator: 'Median age',
        binning: 'naturalBreaks',
        numberOfBins:7,
        colorScale: colors.colorbrewer.Purples
    }
    ...
]
```

In this example, we make a variable called `Median Age` that uses the column `Median Age` from our GeoJSON. It uses the *natural breaks* binning strategy (more on binning [here](https://github.com/nofurtherinformation/webgeoda-gitbook/tree/f32b024ae45448f60ff60d3566f1267e6994e579/data/variables/data/creating-variables/binning-types.md)), with 7 bins, and uses the [ColorBrewer](http://colorbrewer.org/) purples color scheme.

You can declare multiple variables, which will appear in the drop down menu on the left side of the map Each variable can be dynamically binned, or provided with a fixed color scheme. You can use time-series data, single columns, or categorical data.

See the [full variable specification](https://github.com/nofurtherinformation/webgeoda-gitbook/tree/f32b024ae45448f60ff60d3566f1267e6994e579/data/variables/data/variables/full-spec.md) for more information.

## Available Color Scales

Currently, all [ColorBrewer](http://colorbrewer.org/) scales are included. Most support 3-9 bins. See more [here](https://github.com/nofurtherinformation/webgeoda-gitbook/tree/f32b024ae45448f60ff60d3566f1267e6994e579/data/variables/data/variables/colors.md)


# Continuous

Binning is the process of classifying a body of data into discrete breakpoints, or bins, to more easily understand and digest the data. Many online maps utilize unclassified scales -- continuous color gradients -- but we prefer and provide tools for a robust set of binning strategies.

You can specify binning strategy and number of bins for each of your variables in `map-config.js` by setting the `binning` and `numberOfBins` parameters. For a more in-depth look at binning strategies, refer to [jsGeoDa docs](https://xunli.gitbook.io/jsgeoda/).

## Binning Modes

Here are the different binning modes available in WebGeoDa:

### Natural Breaks

This non-linear algorithm identifies natural groupings of values that highlight more intuitive breakpoints.

```javascript
{
    // some variable
    binning: 'naturalBreaks',
    numberOfBins:5, // 3 - 9
}
```

### Quantiles

Quantile breaks create bins based on an equal number of entries in numerical order based on the given number of bins.

```javascript
{
    // some variable
    binning: 'quantileBreaks',
    numberOfBins:5, // 3 - 9
}
```

### Percentiles

Percentile breaks identify bins at the 1% lowest percentile, 10th percentile, 50th percentile (median), 90th percentile, and 99% highest perceentile.

```javascript
{
    // some variable
    binning: 'percentileBreaks'
}
```

### Standard Deviations

Standard deviations are calculated from your given variable based on .... Standard Deviation breaks fall on less than -2 standard deviations, -1 to -2 standard deviations, 0 to -1 standard deviations, 0 to +1 standard deviations, +1 to +2 standard deviations and greater than +2 standard deviations.

```javascript
{
    // some variable
    binning: 'stddev_breaks'
}
```

### Hinge Breaks

15/30

```javascript
{
    // some variable
    binning: 'hingeBreaks15' // alternatively 'hingeBreaks30'
}
```

### Custom, Fixed Scales

If you want to provide a custom or fixed binning scale for your data, such as a particular equal interval (eg. 5, 10, 15, 20, 25, etc.), you can provide a `fixedScale` parameter in your variable:

```javascript
{
    variable: 'Percent Vaccinated',
    fixedScale: [20, 30, 40, 50, 60, 70],
    colorScale: colors.colorBrewer.Greens
}
```


# Categorical

Categorical variables can be called by declaring `categorical: true` in your variable specification:

```javascript
    // ...variables
    {
        variable: "Most Common Heating Fuel",
        numerator: "household_data",
        nProperty: "Fuel Type",
        categorical: true,
        colorScale: colors.colorbrewer.Dark2,
    }
```

You can use any data properties for categorical data, but note that the map will search for exact matches to the data categories. Similarly, you can use any color scheme, although colorBrewer's [Qualitative Color Schemes](https://colorbrewer2.org/#type=qualitative\&scheme=Dark2\&n=6) (or similar) may be best suited for categorical variables.

Note that categorical variables will look for every unique value and assign it a color. For data columns or variables with a large number of unique values, this may not be the best option.


# LISA

In addition to various [binning strategies](https://github.com/nofurtherinformation/webgeoda-gitbook/tree/3f52ced9327a8784263a72795b1b25a75f375435/variables/variables/binning-types.md), you can specify a variable that identifies statistically significant local clusters, also known as Local Indicators of Spatial Autocorrelation (or LISAs; [Anselin, 1995](https://onlinelibrary.wiley.com/doi/pdf/10.1111/j.1538-4632.1995.tb00338.x)). The LISA statistic identifies a hotspot where a core location and its neighbors are above average for the data and they have significant correlation, relative to a random spatial distribution (known as the reference distribution). For coldspots, the same LISA statistic finds areas below average. Spatial outliers are locations with above-average core locations and below-average neighbors or vice versa. Spatial clusters and outliers are displayed at a certain pseudo significance level (such as 0.05 or 0.01), and by default, only cluster core locations are displayed.

## Specifying LISA Variables

```javascript
    // ...variables
    {
        variable: "Population Density Hotspot",
        numerator: "acs_data",
        nProperty: "Total Population",
        denominator: "acs_data",
        dProperty: "Area Land",
        lisa: true
    }
```

## LISA Options

By default, WebGeoDa uses Local Moran's I algorithm ([Anselin, 1995](https://onlinelibrary.wiley.com/doi/pdf/10.1111/j.1538-4632.1995.tb00338.x)) to calculate local spatial autocorrelation. You can specify an alternate LISA function with the `lisaFunction` parameter in your LISA variable spec.`lisaFunction` should be the name of a [jsGeoDa local spatial autocorrelation function](https://xunli.gitbook.io/jsgeoda/local-spatial-autocorrelation/local-moran). For more background on LISA statistics, visit GeoDa's [intro to spatial data analysis docs](https://geodacenter.github.io/workbook/6a_local_auto/lab6a.html).

Additionally, you can provide additional LISA parameters for your jsGeoDa LISA function in `lisaParams`. The map ID and spatial weights ID will be automatically provided to jsGeoDa, but additional parameters can be provided as an array:

```javascript
    // ...variables
    {
        // ...variable spec
        lisa: true,
        lisaFunction: 'localGeary',
        lisaParams: [
            999, // Number permutations, 
            'lookup',// String permutation_method,
            0.05, // NUmber significance_cutoff, 
            123456789 // Number seed
        ]
    }
```

See [jsGeoDa docs](https://xunli.gitbook.io/jsgeoda/local-spatial-autocorrelation/local-moran) for futher information on LISA calculations and parameters.

## Spatial Weights Options

By default, WebGeoDa uses Queen's Weights, but you can specify a preferred way to calculate spatial weights (such as distance weights or kernel weights). You specify this by calling the `weightsFunction` parameter in your LISA variable spec. `weightsFunction` should be the name of a [jsGeoDa weights function](https://xunli.gitbook.io/jsgeoda/spatial-weights/contiguity-based-weights).

Additionally, you can provide additional weights parameters for your jsGeoDa weights function in `weightsParams`. The map ID will be automatically provided to the jsGeoDa weights function, but additional parameters can be provided as an array:

```javascript
    // ...variables
    {
        // ...variable spec
        lisa: true,
        weightsFunction: 'getDistanceWeights',
        weightsParams: [
            500, // Number distBand,
            1, // Number power, 
            false, // Boolean isInverse, 
            false, // Boolean isArc,
            true// Boolean isMile
        ]
    }
```

See [jsGeoDa docs](https://xunli.gitbook.io/jsgeoda/spatial-weights/distance-based-weights) for futher information on weights calculations and parameters.


# Colors

Map color scales strongly impact the interpretation of a map and impact its accessibility, legibility, and visual interest. WebGeoDa provides a collection of helpful built-in color scaling standards, and also allows for any custom color scale to be added.

## Color Format

All color scales should be arrays of RGB values, like so:

```javascript
const myColorScale = [
    [0,0,0], //r, g, b
    [40,40,40],
    [80,80,80],
    [140,140,140],
    [220,220,220]
]
```

## ColorBrewer

ColorBrewer scales, designed by the immeasurable Cynthia Brewer, are available for convenient use in WebGeoDa. Preview these scales below:

{% embed url="<https://colorbrewer2.org/#type=sequential&scheme=BuGn&n=3>" %}

When using ColorBrewer scales, you can specify a given scale as shown below:

```javascript
const variables = [{
    variable: 'myVar',
    numerator: 'myData',
    nProperty: 'myColumn',
    binning: 'naturalBreaks',
    colorScale: colors.colorBrewer.Reds
}]
```

## GeoDa Spatial Statistics

The official GeoDa color scales are available under `colors.geoda` and include color scales for LISA data and hinge breaks.


# Variable Specification

The full variable specification reflects all the options available when specifying your variable. Below are all available variable parameters:

* variable `String`: The name a well-adjusted human person might use to describe your variable
* numerator `String`: The numerator for your variable. If you're only using properties from your geospatial data (eg. GeoJSON properties on each feature), you can call the column name directly here. Otherwise, this should refer to the joined data table you'd like to use.
* nProperty `String`: The data column of your numerator to use (eg. 'Total Population')
* nRange `Number`: For time-series data, specify a temporal range for the variable (eg. 1 - daily, 7 - weekly, etc). Cumulative time-series data can be used by calling this `nRange` with `null`
* nIndex `Number`: ...
* denominator `String`: The denominator for your variable. Same conditions apply as `numerator`!
* dProperty `String`: The data column of your numerator to use (eg. 'Land Area')
* dRange `Number`: See `nRange`. If not declared
* dIndex `Number`: ...
* scale `Number`: The scale calculated values will be mutiplied by. For example, if you're using a percentage variable that is normalized from 0-1, you might set a scale of `100`. For many public health metrics, a scale of values per 10,000 or 100,000 may be useful.
* binning `String`: The binning strategy you want for this variable. By default, natural breaks will be used. Read more on available [binning strategies](https://github.com/nofurtherinformation/webgeoda-gitbook/tree/7710e188a74eaf2084b4fb2441eb259996df3fff/variables/variables/binning-types.md)
* numberOfBins `Number`: The number of bins to be generated. Defaults to 5. Built-in color brewer schemes support 3-9 bins.
* colorScale `Object` or `Array`: A built-in color scale of your choice (eg. `colors.colorBrewer.Reds`) or a custom array of RGB values (eg. `[[0,20,40],[20,40,80],[40,80,120]]`). If using a custom scale, you should include the same number of colors as the number of bins.&#x20;
* fixedScale `Array`: Pre-define a range of bins by specifying the breakpoints as an array (eg. `[5,10,15]` will produce bins *Less than 5, 5 to 10, 10 to 15, Greater than 15*)


# Adding and Customizing Pages

Static pages are extremely useful to contextualize the data presented in your WebGeoDa dashboard. For example, you could include documentation on your data sources, potential limitations, citations, and a data download. Or add a form for users to report data issues and suggestions!

## Starting a New Page

At its core, here's all you need for a page:

```javascript
// pages/myPage.js
import Head from 'next/head'

export default function MyPage() {
    return (
        <div>
            <Head>
                <title>My Page:: WebGeoDa Scaffolding</title>
                <meta name="description" content="A Really Good Page." />
                <link rel="icon" href="/favicon.ico" />
            </Head>
            Ahoy, Globe!
        </div>
    )
}
```

Each page script starts with any imports, here we're importing the `<Head>` component from `next/head`. Then, your main function for that page, denoted with `export default`. You can have any additional logic you need for the page in this function and any additional helper functions outside the function as well.

The `return` statement has the bulk of what we're looking for here. Instead of writing traditional HTML, [Next.js](/pages/adding-and-customizing-pages) and React use a mash of HTML and XML called [JSX](/pages/adding-and-customizing-pages). It can interpret traditional HTML elements, such as `div`, but also supports custom elements and components. In the example above the `<Head>` component we imported allows us to modify the meta information on the page, like the title, description, favicon, and so on. Past that head

## Updating the Nav Bar

Add or remove `<MenuLink>` elements in the navbar, found in `components/layout/MainNav.js`. Each of these represents a link in the navigation menu, and the `href` property leads to the page's route (eg. "/map"). Be sure to include `as='a'` in the `<MenuLink>` element for expected behavior:

```javascript
// components/layout/MainNav.js
    // other component stuff...
    <Menu>
        <MenuButton>
            Menu <span aria-hidden className={styles.hamburger}>☰</span>
        </MenuButton>
        <MenuList id="menu">
            <MenuLink as="a" href="/">
                Home
            </MenuLink>
            <MenuLink as="a" href="/map">
                Map
            </MenuLink>
            <MenuLink as="a" href="/about">
                About
            </MenuLink>
        </MenuList>
    </Menu>
```


# Styling and CSS Modules

WebGeoDa scaffolding includes CSS module support for local CSS on each page or component. We recommend creating a new CSS module file for each new page and then importing that to your JavaScript file. For an introduction to CSS, visit [mdn docs?](/pages/styling-and-css-modules).

## Creating and Importing CSS Modules

If you had a page `data.js`, you could create a new CSS module, `styles/Data.module.css`. This works just like any CSS file, but will be specifically scoped for the JavaScript files where it's imported. You can import styles at the top of your JavaScript file like this:

```javascript
// pages/data.js
import Head from 'next/head'
import styles from '../styles/Data.module.css'
```

Now, you can start writing your CSS rules, which might look something like this:

```css
.container {
    min-height: 100vh;
    /** some rules */
}

.main {
    padding: 5rem 0;
    flex: 1;
    display: flex;
    /** some more rules */
}
```

## Using CSS Module Styles

After importing your CSS file and adding rules, you can access your styles right in your JavaScript function. JSX requires CSS classes to be called slightly differently than normal html, using `className='myClass'` instead of `class='myClass'`. CSS IDs can still be called normally, and nested selectors, like `nav .logo img` will work as expected. Here's how to apply a CSS class from your CSS module:

```jsx
<h1 className={styles.title}>About Webgeoda</h1>
<h2 className={styles.sectionHead}>Data Sources</h2>
```

Here, we use `<h1>` and `<h2>` tags that are given a `className` property from the imported `styles` CSS module (`styles.title` and `styles.sectionHead` specifically). In JSX, we apply these styles using curly braces `{}` since they are imported from the CSS module.

## Using Global Styles

In addition to calling scoped styles from your CSS modules, you can apply simple CSS classes in a more traditional way from `styles/global.css` and `styles/grid.css`:

```markup
<div className="row rules horizontally-centered">
    <!-- some content -->
</div>
```

## Grid Layouts

WebGeoDa includes [Flexbox Grid](http://flexboxgrid.com/), a lightweight CSS column system for defining column widths at multiple responsive breakpoints. This styling allows for 12-column grid layouts with responsive `xs`, `sm`, `md` and `lg` breakpoints. The `xs` and `sm` breakpoints are for mobile and tablet devices, where you might want fewer columns, the `md` for mid-size displays, and the `lg` for laptop or desktop size resolutions. Tagging `div`s, or other html elements with `col`-`breakpoint`-`number of columns` (eg. `col-md-6`) defines its column layout. The parent element should be tagged with the CSS class `row`.

Here's a quick example of three columns:

```markup
<div className="row rules">
    <div className="col-xs-12 col-md-6 col-lg-4">
        <!-- some content -->
    </div>
    <div className="col-xs-12 col-md-6 col-lg-4">
        <!-- some content -->
    </div>
    <div className="col-xs-12 col-md-6 col-lg-4">
        <!-- some content -->
    </div>
</div> <!-- end row -->
```

On desktop, this will display three columns side by side, on a mid-size display two columns and then a third on a new row, and on mobile this will display one single collapsed column. More options, like row-reordering, fluid columns, and spacing options are available at [Flexbox Grid](http://flexboxgrid.com/).


# Changing the Background Map Tiles

You can create a range of custom background maps through [Mapbox](https://www.mapbox.com)'s studio interface, and export the public style URL. In `map-config.js`, you can add a new Mapbox map style URL in the `styling` parameter, as shown below.

```javascript
const styling = {
    mapStyle: 'mapbox://styles/dhalpern/ckp07gekw2p2317phroaarzej'
}
```

## Alternative Map Tile Providers

Coming soon MapTiler and Stamen fans!


# Visualization Modes

## 2D

The default map view.

## 3D

\~ Coming Soon \~

## Cartogram

\~ Coming Soon \~

## Dot Density

\~ Coming Soon \~


# Change Tooltip and Data Sidebar Information


# Modifying Layers


# Data Exploration Widgets

## Specification

Each widget is specified as an entry in the `widgets` array in `map-config.js`.

```javascript
const widgets = [
    {
        type: string,
        display: string,
        options: { ... },
        ...
    }
];
```

All widgets require the following fields:

| Key       | Type                                                | Description                                                                                  |
| --------- | --------------------------------------------------- | -------------------------------------------------------------------------------------------- |
| `type`    | One of: `histogram`, `scatter`, `scatter3d`, `line` | The basic type of widget.                                                                    |
| `display` | One of: `pinned`, `tray`, `hidden`                  | The starting position of the widget; widgets can be dragged by users.                        |
| `options` | Map                                                 | Additional options: see below. You must specify a value; to use default values, set to `{}`. |

## Widget Types

### Histograms

Create visualizations for single variables with histograms. Histograms are also interactive and can be used to filter what's highlighted on the map.

#### Configuration

```javascript
{
    type: "histogram",
    display: "pinned" | "tray" | "hidden",
    variable: string,
    options: {
        header: string,
        foregroundColor: color,
        xAxisLabel: string,
        yAxisLabel: string,
        thresholds: int
    }
}
```

| Key                       | Type     | Description                                                                                                     | Default   |
| ------------------------- | -------- | --------------------------------------------------------------------------------------------------------------- | --------- |
| `variable`                | string   | The name of the variable to display.                                                                            | Required  |
| `options.header`          | string   | The header/title of the widget.                                                                                 | null      |
| `options.foregroundColor` | hex code | The color of the bars.                                                                                          | `#000000` |
| `options.xAxisLabel`      | string   | The label of the x-axis.                                                                                        | null      |
| `options.yAxisLabel`      | string   | The label of the y-axis.                                                                                        | null      |
| `options.thresholds`      | int      | This option will be passed to D3's binning function; the number of bins is not guaranteed to match this number. | 40        |

### 2D Scatterplots

#### Configuration

```javascript
{
    type: "scatter",
    display: "pinned" | "tray" | "hidden",
    xVariable: string,
    yVariable: string,
    options: {
        header: string,
        foregroundColor: color,
        pointSize: number,
        xAxisLabel: string,
        yAxisLabel: string,
        showBestFitLine: bool,
        removeZeroValues: bool
    }
}
```

| Key                        | Type     | Description                                                                   | Default   |
| -------------------------- | -------- | ----------------------------------------------------------------------------- | --------- |
| `xVariable`                | string   | The name of the x-axis variable.                                              | Required  |
| `yVariable`                | string   | The name of the y-axis variable.                                              | Required  |
| `options.header`           | string   | The header/title of the widget.                                               | null      |
| `options.foregroundColor`  | hex code | The color of the points.                                                      | `#000000` |
| `options.pointSize`        | number   | The radius of the scatter points.                                             | 0.1       |
| `options.xAxisLabel`       | string   | The label of the x-axis.                                                      | null      |
| `options.yAxisLabel`       | string   | The label of the y-axis.                                                      | null      |
| `options.showBestFitLine`  | bool     | Set to true to calculate and display a best fit line using linear regression. | false     |
| `options.removeZeroValues` | bool     | Set to true to remove points with zero values.                                | false     |

#### LISA Scatterplots

LISA statistics can be generated and plotted in Scatterplot widgets. To plot spatial lag values, set your `yVariable` to `LISA`:

```javascript
{
    type: "scatter",
    yVariable: "LISA"
    // ...
}
```

Best fit lines are not supported for LISA scatterplots.

#### Clustering

Scatterplot widgets can calculate clusters using k-means clustering and display them as colors.

```javascript
{
    type: "scatter",
    options: {
        foregroundColor: "cluster",
        numClusters: int,
        clusterColors: color[]
        // ...
    }
    // ...
}
```

**Additional configuration options for cluster charts**

| Key                       | Type               | Description                                                                         | Default  |
| ------------------------- | ------------------ | ----------------------------------------------------------------------------------- | -------- |
| `options.foregroundColor` | string             | Should be set to `"cluster"`                                                        | Required |
| `options.numClusters`     | int                | The number of clusters to generate.                                                 | 2        |
| `options.clusterColors`   | array of hex codes | The colors to use for each cluster. Should be an array with length >= `numClusters` | Required |

### 3D Scatterplots

#### Configuration

```javascript
{
    type: "scatter3d",
    display: "pinned" | "tray" | "hidden",
    xVariable: string,
    yVariable: string,
    zVariable: string,
    options: {
        header: string,
        foregroundColor: color,
        pointSize: number,
        xAxisLabel: string,
        yAxisLabel: string,
        zAxisLabel: string,
        gridlinesInterval: [number, number, number]
    }
}
```

| Key                         | Type       | Description                                                                                                     | Default   |
| --------------------------- | ---------- | --------------------------------------------------------------------------------------------------------------- | --------- |
| `xVariable`                 | string     | The name of the x-axis variable.                                                                                | Required  |
| `yVariable`                 | string     | The name of the y-axis variable.                                                                                | Required  |
| `zVariable`                 | string     | The name of the z-axis variable.                                                                                | Required  |
| `options.header`            | string     | The header/title of the widget.                                                                                 | null      |
| `options.foregroundColor`   | hex code   | The color of the points.                                                                                        | `#000000` |
| `options.pointSize`         | number     | The radius of the scatter points.                                                                               | 0.5       |
| `options.xAxisLabel`        | string     | The label of the x-axis.                                                                                        | null      |
| `options.yAxisLabel`        | string     | The label of the y-axis.                                                                                        | null      |
| `options.zAxisLabel`        | string     | The label of the z-axis.                                                                                        | null      |
| `options.gridlinesInterval` | number\[3] | The intervals at which to draw gridlines and labels. Order: \[x, y, z]. If omitted, no gridlines will be shown. | null      |

### Line

Display one-dimensional variables over time as a 2D line chart.

#### Configuration

```javascript
{
    type: "line",
    display: "pinned" | "tray" | "hidden",
    variable: string,
    options: {
        header: string,
        foregroundColor: color,
        pointSize: number,
        xAxisLabel: string,
        yAxisLabel: string,
        showBestFitLine: bool,
        removeZeroValues: bool
    }
}
```

| Key                       | Type     | Description                                                                                              | Default      |
| ------------------------- | -------- | -------------------------------------------------------------------------------------------------------- | ------------ |
| `variable`                | string   | The name of the variable to display.                                                                     | Required7    |
| `options.header`          | string   | The header/title of the widget.                                                                          | null         |
| `options.foregroundColor` | hex code | The color of the line.                                                                                   | `#000000`    |
| `options.pointSize`       | number   | The radius of the points on the line.                                                                    | 1            |
| `options.xAxisLabel`      | string   | The label of the x-axis.                                                                                 | null         |
| `options.yAxisLabel`      | string   | The label of the y-axis.                                                                                 | null         |
| `options.dateFormat`      | string   | The format of the date labels. [Specification on Day.js docs](https://day.js.org/docs/en/display/format) | "YYYY-MM-DD" |


# Widget Layouts


# Netlify

The WebGeoDa scaffolding template includes a Netlify configuration that does most of the work here. While WebGeoDa's underlying framework, Next.js, is *strictly* best suited to Vercel for hosting, Netlify has benefits for organizations looking for free or open-source sponsored hosting. To start create or link an existing account to [Netlify](https://netlify.com/)

Next, follow the tutorial below the link your Github repo to Netlify:

{% embed url="<https://docs.netlify.com/site-deploys/create-deploys/>" %}

Your website will now automatically build as you push new data and changes to your code.


# Vercel

Vercel is often the best choice for hosting WebGeoDa scaffolding. Similar to Netlify, it provides static site hosting that supports Next.js --which Vercel built! It's fast, it's powerful, and they provide additional services beyond static site hosting if you grow beyond static needs. To get started, create or link an account on [Vercel](https://vercel.com/).

Next, follow the below tutorial to link your Github repo to a Vercel deployment.

{% embed url="<https://ihatetomatoes-nextjs-101.vercel.app/post/how-deploy-next-app-vercel>" %}

Note that for organizations, Vercel does not provide a free plan -- individuals can use the free tier.


# Github Pages (or elsewhere)

\[Insert reject modernity meme]

Github pages, or any static web provider, can absolutely be used to host WebGeoDa scaffolding! To export your site as a static, plain ol' JS, HTML, and CSS website, run the following commands:

```
npm run build 
npm run export
```

This will generate a folder named `out` that contains your generated site pages. Rename this to `docs` and then follow the tutorial below to set up a Github pages site:

{% embed url="<https://docs.github.com/en/pages/getting-started-with-github-pages/creating-a-github-pages-site>" %}

A few important notes here:\
\- GitHub does not have the same performance as Netlify or Vercel\
\- Static site exports will not support all Next.js features, like dynamic routes

With that said, you can take the built `out` folder generated in your repo to **any** static web hosting, or[ host it yourself! ](https://www.instructables.com/Host-your-website-on-Raspberry-pi/)


# jsGeoDa

jsGeoDa is the geospatial engine behind the calculations in WebGeoDa scaffolding. See more at <https://xunli.gitbook.io/jsgeoda/>


# Next.JS

Next.JS is a server-side rendering React-based web framework. It has a lot of the benefits of React web apps and sites, but also generates plain ol' HTML pages, speeding up loading time and removing headaches for a number of different challenges. Learn more below:

{% embed url="<https://nextjs.org/>" %}


# Alternate Map Views

Coming soon...


# Binary Data Formats

Coming soon, WebGeoDa scaffolding will support ProtoBuffer and GeoBuf for data transfer formats. Learn more below:

{% embed url="<https://developers.google.com/protocol-buffers>" %}

{% embed url="<https://github.com/mapbox/geobuf>" %}


