# Arcgis Core Maps

> Create 2D and 3D maps using ArcGIS Maps SDK for JavaScript. Use for initializing maps, scenes, views, and navigation. Supports both Map Components (web components) and Core API approaches.

- **Type:** Skill
- **Install:** `agentstack add skill-saschabrunnerch-arcgis-maps-sdk-js-ai-context-arcgis-core-maps`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [SaschaBrunnerCH](https://agentstack.voostack.com/s/saschabrunnerch)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [SaschaBrunnerCH](https://github.com/SaschaBrunnerCH)
- **Source:** https://github.com/SaschaBrunnerCH/arcgis-maps-sdk-js-ai-context/tree/master/skills/arcgis-core-maps

## Install

```sh
agentstack add skill-saschabrunnerch-arcgis-maps-sdk-js-ai-context-arcgis-core-maps
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# ArcGIS Core Maps

Use this skill when creating 2D maps (MapView) or 3D scenes (SceneView) with the ArcGIS Maps SDK for JavaScript.

## Import Patterns

### Direct ESM Imports (Recommended for Build Tools)

Use with Vite, webpack, Rollup, or other build tools:

```javascript
import Map from "@arcgis/core/Map.js";
import MapView from "@arcgis/core/views/MapView.js";
import FeatureLayer from "@arcgis/core/layers/FeatureLayer.js";
```

- Tree-shakeable
- Standard JavaScript modules
- Best for production applications

### Dynamic Imports (CDN / No Build Tools)

Use with CDN script tags when no build step is available:

```javascript
const Map = await $arcgis.import("@arcgis/core/Map.js");
const MapView = await $arcgis.import("@arcgis/core/views/MapView.js");

// Multiple imports
const [FeatureLayer, Graphic] = await $arcgis.import([
  "@arcgis/core/layers/FeatureLayer.js",
  "@arcgis/core/Graphic.js",
]);
```

- Works with Map Components (web components)
- No build step required
- Good for quick prototypes and demos
- Requires `` in HTML

> **Note:** The examples in this skill use Direct ESM imports. For CDN usage, replace `import X from "path"` with `const X = await $arcgis.import("path")`.

## Autocasting vs Explicit Classes (TypeScript)

The ArcGIS SDK supports [autocasting](https://developers.arcgis.com/javascript/latest/autocasting/) - passing plain objects instead of class instances.

### When to Use Explicit Classes (Non-Autocast)

Use `new SimpleRenderer()`, `new Point()`, etc. when:

- **You need instance methods or `instanceof` checks**
- **Building shared internal libraries** - constructor APIs surface breaking changes at compile time
- **You want strong editor discoverability** - `new SimpleRenderer({ ... })` exposes properties clearly
- **You mutate objects incrementally** - long-lived instances are clearer as real classes

```typescript
import SimpleRenderer from "@arcgis/core/renderers/SimpleRenderer.js";
import SimpleMarkerSymbol from "@arcgis/core/symbols/SimpleMarkerSymbol.js";

const renderer = new SimpleRenderer({
  symbol: new SimpleMarkerSymbol({
    color: [226, 119, 40],
    size: 8,
  }),
});
```

### When to Use Autocasting

Use plain objects with `type` property when:

- **Configuration-heavy code** - renderers, symbols, popups are usually data, not behavior
- **UI-driven configuration** - React state → plain objects → SDK properties is simpler
- **Serialization and reuse matter** - configs can be stored, diffed, tested, reused
- **Property updates after creation** - `layer.renderer = { ... }` works cleanly in React `useEffect`

```typescript
// Use 'as const' or 'satisfies' to keep discriminated unions narrow
const renderer = {
  type: "simple",
  symbol: {
    type: "simple-marker",
    color: [226, 119, 40],
    size: 8,
  },
} as const;

// Or with satisfies for better type inference
const renderer = {
  type: "simple",
  symbol: {
    type: "simple-marker",
    color: [226, 119, 40],
    size: 8,
  },
} satisfies __esri.SimpleRendererProperties;
```

### TypeScript Best Practices

The real TypeScript concern is keeping discriminated unions narrow:

```typescript
// ❌ BAD - type widens to string
const symbol = { type: "simple-marker", color: "red" };

// ✅ GOOD - type stays literal
const symbol = { type: "simple-marker", color: "red" } as const;

// ✅ GOOD - explicit type annotation
const symbol: __esri.SimpleMarkerSymbolProperties = {
  type: "simple-marker",
  color: "red",
};
```

### Recommended Default

- **Autocast for configuration** (renderers, symbols, popups, labels)
- **Explicit classes for behavior** (when you need methods or instanceof)
- **Use `as const` or `satisfies`** to maintain type safety with autocasting

## Two Approaches

### 1. Map Components (Modern - Recommended)

Web components approach using `` and ``.

### 2. Core API

Traditional JavaScript approach using `Map`, `MapView`, and `SceneView` classes.

## CDN Setup

### Map Components Approach

```html

  
    
    
    ArcGIS Map
    
      html,
      body {
        height: 100%;
        margin: 0;
      }
    
    
    
    
    
    
    
  
  
    
      
    
  

```

### Core API Approach

```html

  
    
    
    ArcGIS Map
    
      html,
      body,
      #viewDiv {
        height: 100%;
        margin: 0;
      }
    
    
    
    
  
  
    
    
      import Map from "@arcgis/core/Map.js";
      import MapView from "@arcgis/core/views/MapView.js";

      const map = new Map({ basemap: "topo-vector" });
      const view = new MapView({
        container: "viewDiv",
        map: map,
        center: [-118.24, 34.05], // [longitude, latitude]
        zoom: 12,
      });
    
  

```

## 2D Maps

### Map Components

```html

  
  
  
  

  const mapElement = document.querySelector("arcgis-map");
  await mapElement.viewOnReady(); // Wait for view to be ready
  const view = mapElement.view; // Access the MapView
  const map = mapElement.map; // Access the Map

```

### Core API

```javascript
import Map from "@arcgis/core/Map.js";
import MapView from "@arcgis/core/views/MapView.js";

const map = new Map({ basemap: "streets-vector" });

const view = new MapView({
  container: "viewDiv",
  map: map,
  center: [-118.24, 34.05],
  zoom: 12,
  // Optional constraints
  constraints: {
    minZoom: 5,
    maxZoom: 18,
    rotationEnabled: false,
  },
});
```

## 3D Scenes

### Map Components

```html

  
  

  const sceneElement = document.querySelector("arcgis-scene");
  await sceneElement.viewOnReady();
  const view = sceneElement.view; // SceneView

```

### Core API

```javascript
import Map from "@arcgis/core/Map.js";
import SceneView from "@arcgis/core/views/SceneView.js";

const map = new Map({
  basemap: "topo-3d",
  ground: "world-elevation",
});

const view = new SceneView({
  container: "viewDiv",
  map: map,
  camera: {
    position: {
      longitude: -118.24,
      latitude: 34.05,
      z: 25000, // altitude in meters
    },
    heading: 0, // compass direction
    tilt: 45, // 0 = straight down, 90 = horizon
  },
});
```

## Loading WebMaps and WebScenes

### WebMap (2D)

```html

  

```

```javascript
// Core API
import MapView from "@arcgis/core/views/MapView.js";
import WebMap from "@arcgis/core/WebMap.js";

const webmap = new WebMap({
  portalItem: { id: "f2e9b762544945f390ca4ac3671cfa72" },
});

const view = new MapView({
  map: webmap,
  container: "viewDiv",
});
```

### WebScene (3D)

```html

  

```

```javascript
// Core API
import SceneView from "@arcgis/core/views/SceneView.js";
import WebScene from "@arcgis/core/WebScene.js";

const webscene = new WebScene({
  portalItem: { id: "YOUR_WEBSCENE_ID" },
});

const view = new SceneView({
  map: webscene,
  container: "viewDiv",
});
```

## Navigation Components

| Component                  | Purpose                                     |
| -------------------------- | ------------------------------------------- |
| `arcgis-zoom`              | Zoom in/out buttons                         |
| `arcgis-compass`           | Orientation indicator, click to reset north |
| `arcgis-home`              | Return to initial extent                    |
| `arcgis-locate`            | Find user's location                        |
| `arcgis-navigation-toggle` | Switch between pan/rotate modes (3D)        |
| `arcgis-fullscreen`        | Toggle fullscreen mode                      |
| `arcgis-scale-bar`         | Display map scale                           |

### Slot Positions

```html

  
  
  
  
  

```

Available slots: `top-left`, `top-right`, `bottom-left`, `bottom-right`, `top-start`, `top-end`, `bottom-start`, `bottom-end`

## Component Attributes

The `` / `` components expose many declarative attributes beyond `basemap`, `center`, `zoom`. High-value ones:

| Attribute                 | Type                  | Purpose                                                                                       |
| ------------------------- | --------------------- | --------------------------------------------------------------------------------------------- |
| `item-id`                 | string                | Load a WebMap/WebScene from ArcGIS Online or Enterprise                                       |
| `rotation`                | number                | Map rotation in degrees                                                                       |
| `scale`                   | number                | Initial scale (e.g. `50000` for 1:50,000)                                                     |
| `extent`                  | Extent (autocast)     | Initial visible extent                                                                        |
| `viewpoint`               | Viewpoint (autocast)  | Combined center + scale + rotation                                                            |
| `spatial-reference`       | SpatialReference      | Coordinate system (WKID)                                                                      |
| `time-extent`             | TimeExtent            | Temporal filter for time-aware layers                                                         |
| `animations-disabled`     | boolean               | Disable all `goTo` animations                                                                 |
| `popup-disabled`          | boolean               | Disable the auto-popup on click                                                               |
| `popup-component-enabled` | boolean               | Use the new Popup component (beta) instead of the widget                                      |
| `auto-destroy-disabled`   | boolean               | Keep the view alive across unmount — **critical for React strict mode and SPA route changes** |
| `attribution-mode`        | `"dark"` \| `"light"` | Attribution text theme                                                                        |
| `hide-attribution`        | boolean               | Hide attribution (check the SDK license terms first)                                          |

Some properties are only settable via JavaScript (not as attributes):

| Property     | Type                 | Purpose                                                           |
| ------------ | -------------------- | ----------------------------------------------------------------- |
| `padding`    | ViewPadding          | Offset the UI logical area when side panels cover part of the map |
| `theme`      | Theme                | Light / dark rendering theme                                      |
| `background` | ColorBackground      | Background color for non-tiled regions                            |
| `graphics`   | Collection  | View-level graphics, independent of any layer                     |
| `highlights` | Collection           | Up to 6 highlight option sets for feature highlighting            |
| `analyses`   | Collection | 3D analyses (line-of-sight, viewshed) — SceneView only            |
| `aria`       | ARIAProperties       | Accessibility labels and descriptions                             |

```html

```

```javascript
// Layout: offset the UI when a 320px left sidebar covers part of the map
const mapElement = document.querySelector("arcgis-map");
await mapElement.viewOnReady();
mapElement.padding = { left: 320 };
```

## Map Properties

| Property         | Type                  | Description                    |
| ---------------- | --------------------- | ------------------------------ |
| `basemap`        | string or Basemap     | Base layer(s) for the map      |
| `ground`         | string or Ground      | Surface properties (elevation) |
| `layers`         | Collection            | Operational layers             |
| `tables`         | Collection            | Non-spatial tables             |
| `allLayers`      | Collection (readonly) | Flattened layer collection     |
| `allTables`      | Collection (readonly) | Flattened table collection     |
| `editableLayers` | Collection (readonly) | Layers that support editing    |
| `focusAreas`     | Collection (readonly) | Focus areas for the map        |

## Map Methods

| Method                    | Returns | Purpose                                      |
| ------------------------- | ------- | -------------------------------------------- |
| `add(layer, index?)`      | void    | Add a layer, optionally at a specific index  |
| `addMany(layers, index?)` | void    | Add multiple layers in one call              |
| `remove(layer)`           | Layer   | Remove a single layer                        |
| `removeMany(layers)`      | Layer[] | Remove multiple layers                       |
| `removeAll()`             | Layer[] | Remove all operational layers                |
| `reorder(layer, index?)`  | Layer   | Change layer draw order                      |
| `findLayerById(id)`       | Layer   | Find a layer by its `id` property            |
| `findTableById(id)`       | Layer   | Find a table by its `id` property            |
| `destroy()`               | void    | Release the map, its layers, basemap, ground |

```javascript
// Add at a specific index (below existing layers)
map.add(baseLayer, 0);

// Batch add for initial setup
map.addMany([featureLayer, graphicsLayer, imageryLayer]);

// Reorder — move a layer to index 2
map.reorder(roadsLayer, 2);

// Lookup by ID (requires `id` to be set on the layer at creation)
const roads = map.findLayerById("roads");
if (roads) roads.visible = false;
```

> **Pattern:** A single `Map` instance can be shared across both a `MapView` (2D) and a `SceneView` (3D). User interaction happens on the view, not the map, so two views over the same map stay in sync for layers while maintaining independent camera/extent state.

## View Configuration

### Setting Initial Extent

```javascript
// By center and zoom
const view = new MapView({
  container: "viewDiv",
  map: map,
  center: [-118.24, 34.05],
  zoom: 12,
});

// By scale
const view = new MapView({
  container: "viewDiv",
  map: map,
  center: [-118.24, 34.05],
  scale: 50000, // 1:50,000
});

// By extent
const view = new MapView({
  container: "viewDiv",
  map: map,
  extent: {
    xmin: -118.5,
    ymin: 33.8,
    xmax: -117.9,
    ymax: 34.3,
    spatialReference: { wkid: 4326 },
  },
});
```

### Programmatic Navigation

```javascript
// Go to location
await view.goTo({
  center: [-118.24, 34.05],
  zoom: 15,
});

// Animated navigation
await view.goTo(
  { center: [-118.24, 34.05], zoom: 15 },
  { duration: 2000, easing: "ease-in-out" },
);

// Go to extent
await view.goTo(layer.fullExtent);

// Go to features
await view.goTo(featureSet.features);
```

### View Constraints

```javascript
// Constrain zoom levels
view.constraints = {
  minZoom: 5,
  maxZoom: 18,
};

// Constrain to area
view.constraints = {
  geometry: layer.fullExtent,
  minScale: 500000,
};

// Disable rotation
view.constraints = {
  rotationEnabled: false,
};
```

## View State Properties

| Property      | Type    | Description                               |
| ------------- | ------- | ----------------------------------------- |
| `ready`       | boolean | Whether the view is fully initialized     |
| `updating`    | boolean | Whether any layer or the view is updating |
| `stationary`  | boolean | True when no navigation is in progress    |
| `interacting` | boolean | True when user is interacting (pan/zoom)  |
| `suspended`   | boolean | True when the view is not visible         |
| `focused`     | boolean | True when the view has keyboard focus     |
| `resolution`  | number  | Map units per pixel                       |

## Event Handling

### Component Events

Map Components fire DOM events on the `` / `` element itself, prefixed with `arcgisView`. These mirror the view events but can be handled via `addEventListener` on the element — including _before_ the view is ready.

```javascript
const mapElement = document.querySelector("arcgis-map");

// Alternative to awaiting viewOnReady()
mapElement.addEventListener("arcgisViewRea

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [SaschaBrunnerCH](https://github.com/SaschaBrunnerCH)
- **Source:** [SaschaBrunnerCH/arcgis-maps-sdk-js-ai-context](https://github.com/SaschaBrunnerCH/arcgis-maps-sdk-js-ai-context)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-saschabrunnerch-arcgis-maps-sdk-js-ai-context-arcgis-core-maps
- Seller: https://agentstack.voostack.com/s/saschabrunnerch
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
