Help us improve
Share bugs, ideas, or general feedback.
From arcgis-maps-sdk-js-ai-context
Manages ArcGIS portal content: saves WebMaps/WebScenes, bookmarks, slides, portal items. For content persistence, map/scene configuration, navigation presets.
npx claudepluginhub saschabrunnerch/arcgis-maps-sdk-js-ai-context --plugin arcgis-maps-sdk-js-ai-contextHow this skill is triggered — by the user, by Claude, or both
Slash command
/arcgis-maps-sdk-js-ai-context:arcgis-portal-contentThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Use this skill for saving maps, managing bookmarks, slides, working with portal items, and configuring WebMap/WebScene structure.
Embeds lightweight, self-contained ArcGIS maps in web pages using the arcgis-embedded-map web component. Use for quick read-only embeds in blogs, dashboards, reports with minimal code and built-in UI controls.
Guides Next.js Cache Components and Partial Prerendering (PPR): 'use cache' directives, cacheLife(), cacheTag(), revalidateTag() for caching, invalidation, static/dynamic optimization. Auto-activates on cacheComponents: true.
Migrates code, prompts, and API calls from Claude Sonnet 4.0/4.5 or Opus 4.1 to Opus 4.5, updating model strings on Anthropic, AWS, GCP, Azure platforms.
Share bugs, ideas, or general feedback.
Use this skill for saving maps, managing bookmarks, slides, working with portal items, and configuring WebMap/WebScene structure.
import WebMap from "@arcgis/core/WebMap.js";
import WebScene from "@arcgis/core/WebScene.js";
import Portal from "@arcgis/core/portal/Portal.js";
import PortalItem from "@arcgis/core/portal/PortalItem.js";
import PortalQueryParams from "@arcgis/core/portal/PortalQueryParams.js";
const WebMap = await $arcgis.import("@arcgis/core/WebMap.js");
const Portal = await $arcgis.import("@arcgis/core/portal/Portal.js");
const [PortalItem, PortalQueryParams] = await $arcgis.import([
"@arcgis/core/portal/PortalItem.js",
"@arcgis/core/portal/PortalQueryParams.js",
]);
import WebMap from "@arcgis/core/WebMap.js";
const webMap = new WebMap({
// From portal item
portalItem: {
id: "WEBMAP_ID",
portal: { url: "https://www.arcgis.com" },
},
});
// Or create from scratch
const webMap = new WebMap({
basemap: "topo-vector",
ground: "world-elevation",
layers: [featureLayer, graphicsLayer],
tables: [tableLayer],
initialViewProperties: {
center: [-118.805, 34.027],
zoom: 13,
},
bookmarks: [bookmark1, bookmark2],
});
const webMap = WebMap.fromJSON({
operationalLayers: [
{
id: "layer1",
layerType: "ArcGISFeatureLayer",
url: "https://services.arcgis.com/.../FeatureServer/0",
title: "My Layer",
visibility: true,
opacity: 1,
},
],
baseMap: {
baseMapLayers: [
{
id: "basemap",
layerType: "VectorTileLayer",
styleUrl:
"https://basemaps-api.arcgis.com/arcgis/rest/services/styles/v2/styles/arcgis/topographic",
},
],
title: "Topographic",
},
initialState: {
viewpoint: {
targetGeometry: {
xmin: -118.9,
ymin: 33.8,
xmax: -118.1,
ymax: 34.3,
spatialReference: { wkid: 4326 },
},
},
},
});
import WebScene from "@arcgis/core/WebScene.js";
const webScene = new WebScene({
portalItem: { id: "WEBSCENE_ID" },
});
// Or create from scratch
const webScene = new WebScene({
basemap: "satellite",
ground: "world-elevation",
layers: [sceneLayer, featureLayer],
initialViewProperties: {
viewpoint: {
camera: {
position: {
x: -118.805,
y: 34.027,
z: 1500,
spatialReference: { wkid: 4326 },
},
heading: 45,
tilt: 65,
},
},
},
presentation: {
slides: [slide1, slide2],
},
});
// Global scene (default)
const globalScene = new WebScene({
basemap: "satellite",
ground: "world-elevation",
viewingMode: "global",
});
// Local scene (with clipping)
const localScene = new WebScene({
basemap: "satellite",
ground: "world-elevation",
viewingMode: "local",
clippingArea: {
type: "extent",
xmin: -118.9,
ymin: 33.8,
xmax: -118.1,
ymax: 34.3,
spatialReference: { wkid: 4326 },
},
clippingEnabled: true,
});
const map = new WebMap({
portalItem: { id: "EXISTING_WEBMAP_ID" },
});
// Update map properties from view before saving
await map.updateFrom(view);
const savedItem = await map.saveAs({
title: "My New WebMap",
snippet: "Description of the map",
tags: ["tag1", "tag2"],
});
console.log(
"Saved to:",
savedItem.portal.url + "/home/item.html?id=" + savedItem.id,
);
await map.updateFrom(view);
await map.save();
<arcgis-map item-id="YOUR_WEBMAP_ID">
<arcgis-zoom slot="top-left"></arcgis-zoom>
</arcgis-map>
<script type="module">
const viewElement = document.querySelector("arcgis-map");
await viewElement.viewOnReady();
document.getElementById("saveBtn").onclick = async () => {
await viewElement.map.updateFrom(viewElement.view);
await viewElement.map.save();
};
</script>
const scene = new WebScene({
portalItem: { id: "EXISTING_WEBSCENE_ID" },
});
await scene.updateFrom(sceneView);
await scene.saveAs({
title: "My New WebScene",
snippet: "3D scene description",
});
<arcgis-map item-id="YOUR_WEBMAP_ID">
<arcgis-expand slot="top-right" expanded>
<arcgis-bookmarks
drag-enabled
show-add-bookmark-button
show-edit-bookmark-button
hide-time
>
</arcgis-bookmarks>
</arcgis-expand>
</arcgis-map>
<script type="module">
const bookmarks = document.querySelector("arcgis-bookmarks");
bookmarks.addEventListener("arcgisSelect", (event) => {
console.log("Selected:", event.detail.bookmark.name);
});
</script>
import Bookmark from "@arcgis/core/webmap/Bookmark.js";
const bookmark = new Bookmark({
name: "My Location",
viewpoint: view.viewpoint.clone(),
});
map.bookmarks.add(bookmark);
// Go to bookmark
view.goTo(bookmark.viewpoint);
import Slide from "@arcgis/core/webscene/Slide.js";
const slide = await Slide.createFrom(sceneView);
slide.title = { text: "Downtown View" };
// Add to presentation
scene.presentation.slides.add(slide);
const slide = scene.presentation.slides.getItemAt(0);
slide.applyTo(sceneView, {
maxDuration: 3000,
easing: "in-out-coast-cubic",
});
scene.presentation.slides.remove(slide);
import PortalItem from "@arcgis/core/portal/PortalItem.js";
const item = new PortalItem({ id: "ITEM_ID" });
await item.load();
console.log("Title:", item.title);
console.log("Type:", item.type);
console.log("Owner:", item.owner);
console.log("Created:", item.created);
import Portal from "@arcgis/core/portal/Portal.js";
import PortalQueryParams from "@arcgis/core/portal/PortalQueryParams.js";
const portal = new Portal({ authMode: "immediate" });
await portal.load();
const queryParams = new PortalQueryParams({
query: `owner:${portal.user.username} type:"Web Map"`,
sortField: "modified",
sortOrder: "desc",
num: 20,
});
const result = await portal.queryItems(queryParams);
result.results.forEach((item) => {
console.log(item.title, item.id);
});
const item = new PortalItem({ id: "ITEM_ID" });
await item.load();
item.title = "Updated Title";
item.snippet = "Updated description";
item.tags = ["new", "tags"];
await item.update();
const portal = new Portal();
await portal.load();
const groups = await portal.queryGroups({ query: "title:GIS" });
groups.results.forEach((group) => {
console.log(group.title, group.id);
});
const group = (await portal.queryGroups({ query: `id:GROUP_ID` })).results[0];
const content = await group.queryItems();
content.results.forEach((item) => {
console.log(item.title);
});
const portal = new Portal({ authMode: "immediate" });
await portal.load();
console.log("Username:", portal.user.username);
console.log("Full name:", portal.user.fullName);
console.log("Email:", portal.user.email);
console.log("Role:", portal.user.role);
console.log("Org name:", portal.name);
import PortalFolder from "@arcgis/core/portal/PortalFolder.js";
// Get user folders
const folders = await portal.user.fetchFolders();
folders.forEach((folder) => {
console.log(folder.title, folder.id);
});
// Query items in a specific folder
const queryParams = new PortalQueryParams({
query: `owner:${portal.user.username}`,
sortField: "modified",
num: 20,
});
queryParams.folder = folder;
const result = await portal.queryItems(queryParams);
Authentication required for saving: Saving requires user authentication. Ensure OAuth is set up before calling save() or saveAs().
Forgetting updateFrom before save: Always call updateFrom(view) before saving to capture the current view state:
// Anti-pattern: saving without updating
await map.save(); // May save stale viewpoint
// Correct: update from view first
await map.updateFrom(view);
await map.save();
Enterprise portal URL: Enterprise portals need explicit portal URL:
const portal = new Portal({
url: "https://your-portal.com/portal",
});
Ownership restrictions: You can only update portal items you own. Use saveAs() to create a copy you own.
Slide thumbnails: Generated automatically from Slide.createFrom() but may take time to render.
<!DOCTYPE html>
<html>
<head>
<script src="https://js.arcgis.com/5.0/"></script>
<script
type="module"
src="https://js.arcgis.com/5.0/map-components/"
></script>
<style>
html,
body {
height: 100%;
margin: 0;
}
</style>
</head>
<body>
<arcgis-map item-id="YOUR_WEBMAP_ID">
<arcgis-zoom slot="top-left"></arcgis-zoom>
<arcgis-expand slot="top-right" expanded>
<arcgis-bookmarks
drag-enabled
show-add-bookmark-button
show-edit-bookmark-button
>
</arcgis-bookmarks>
</arcgis-expand>
</arcgis-map>
<script type="module">
const viewElement = document.querySelector("arcgis-map");
await viewElement.viewOnReady();
// Save map on button click
document.getElementById("saveBtn").onclick = async () => {
await viewElement.map.updateFrom(viewElement.view);
await viewElement.map.save();
};
</script>
</body>
</html>
webmap-save - Saving a WebMap to portalwebmap-basic - Loading a WebMap from portalwebmap-swap - Swapping between WebMapswebscene-save - Saving a WebScene to portalwebscene-basic - Loading a WebScene from portalwebscene-slides - Managing WebScene slideswebscene-slide-tour - Slide tour through a WebScenebookmarks - Working with map bookmarkswidgets-bookmarks - Bookmarks widget usagebasemaps-portal - Loading basemaps from portallayers-portal - Loading layers from portal itemsportalitem-dragndrop - Drag and drop portal itemsarcgis-authentication for OAuth and API key setup.arcgis-core-maps for map and view creation.arcgis-layers for layer configuration.