What we're doing, in one page
You describe a tool in plain English. An AI assistant (Claude Code or Codex) writes the code using Esri's building blocks. GitHub keeps every version. Vercel puts it on the web. Supabase holds the data when a map isn't enough. That workflow already built the tour, livessaved.jbf.com, and this very page.
The problem this guide solves: the ArcGIS developer platform is enormous, it changes monthly, and no one, human or AI, should be working from memory. So this page has two halves. The first is a ladder of six live demonstrations, each one building on the last: one map, stretched through five levels, then a live dashboard, then a live operation with radar, hurricanes, and Red Cross geography, then three that let loose: live air traffic over the country, every natural event on Earth right now, and the day/night line and the space station on the globe that opened this page. The second half is the reference you come back to: the platform map, the Brain, your stack, a plain-English dictionary, machine setup, and a place to ask anything.
The Ladder
Six demonstrations, each building on the last: a map, a dashboard, an operation, the sky, the planet, and the planet in 3D. Every code reveal below shows only what changed since the step before it.
The Brain
Live documentation lookups, 35 installed ArcGIS skills, and a daily watcher that opens an issue when Esri ships a release.
The Guardrail
AI in the workflow: always. AI inside a deployed Red Cross app: only with explicit approval, until the org turns AI on.
Demonstration 1
What one map can do
Five levels, one page element, each rung live. By the end of this demonstration the map computes; the two demonstrations after it put the same kit to work on whole jobs.
Level 1: a map is one tag
Where everyone starts. The map below is a single HTML tag, and the dropdown proves the tag is alive: changing one attribute redraws the planet.
<arcgis-map id="hello" basemap="osm" center="-98.5,39.8" zoom="4">
</arcgis-map>
<select id="pick">
<option value="osm">OpenStreetMap</option>
<option value="satellite">Satellite</option>
</select>
<script type="module">
document.getElementById("pick").addEventListener("change", (e) => {
document.getElementById("hello").basemap = e.target.value;
});
</script>
Level 2: two thousand earthquakes, three ways
The same live USGS feed, drawn three different ways with the buttons below. No exports, no geoprocessing tools; each view is a one-line change of mind.
const quakes = new GeoJSONLayer({
url: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson",
renderer: dotsSizedByMagnitude,
});
mapEl.map.add(quakes);
// Clusters: one property.
quakes.featureReduction = { type: "cluster", clusterRadius: "80px" };
// Heatmap: swap the renderer.
quakes.featureReduction = null;
quakes.renderer = {
type: "heatmap",
colorStops: [
{ ratio: 0.0, color: "rgba(216, 0, 27, 0)" },
{ ratio: 0.6, color: "rgba(216, 0, 27, 0.55)" },
{ ratio: 1.0, color: "#79000f" },
],
};
Level 3: the third dimension
Swap the word "map" for "scene" and the page grows terrain. This is Everest, drifting until you grab it; the mountains are real elevation data, not a picture.
<arcgis-scene basemap="satellite" ground="world-elevation">
</arcgis-scene>
const [Camera, Point] = await $arcgis.import([
"@arcgis/core/Camera.js",
"@arcgis/core/geometry/Point.js",
]);
sceneEl.view.goTo(new Camera({
position: new Point({ longitude: 86.92, latitude: 27.75,
z: 9200, spatialReference: { wkid: 4326 } }),
tilt: 76,
heading: 12, // facing the summit
}));
Level 4: motion and mood
Maps stopped being screenshots. Time is a control you hand the reader, and layers take visual effects the way photos take filters.
effect: "bloom(2, 0.6px, 0.1)", on a dark canvas.// Time: give the layer's own timestamps to a slider tag.
<arcgis-time-slider mode="cumulative-from-start" loop play-rate="90">
</arcgis-time-slider>
slider.fullTimeExtent = storms.timeInfo.fullTimeExtent;
slider.stops = { interval: { value: 6, unit: "hours" } };
slider.play();
// Mood: one property, no new layer.
quakes.effect = "bloom(2, 0.6px, 0.1)";
Level 5: maps that compute
The level Experience Builder can't reach. Click anywhere on Earth: the page draws a 250-kilometer circle, measures it geodesically, counts the live earthquakes inside, and writes you a sentence.
Click anywhere. Alaska and Japan are busy this week.
const geometryEngine = await $arcgis.import(
"@arcgis/core/geometry/geometryEngine.js");
mapEl.view.on("click", async (event) => {
const circle = geometryEngine.geodesicBuffer(
event.mapPoint, 250, "kilometers");
drawCircle(circle); // a fill graphic, nothing more
const { features } = await quakes.queryFeatures({
geometry: circle,
spatialRelationship: "intersects",
outFields: ["mag", "place"],
});
const strongest = features.reduce(
(a, b) => (a?.attributes.mag > b.attributes.mag ? a : b), null);
card.innerHTML = features.length
? `<h3>${features.length} earthquakes within 250 km this week</h3>
<p>Strongest: M ${strongest.attributes.mag.toFixed(1)}, ${strongest.attributes.place}</p>`
: `<h3>Zero earthquakes within 250 km this week</h3>
<p>A quiet neighborhood.</p>`;
});
That's the whole ladder for one map: a tag, a feed, a dimension, motion, and an answer. The next two demonstrations put this kit to work on whole jobs.
Demonstration 2
The dashboard
Demonstration 1 was one map stretching. This is a whole job: the live operational board people buy a product for, built from one federal feed and about two hundred readable lines. Each section below shows the next piece added; by the end you have seen all of it.
Start here: the numbers, computed in your browser
No server crunched these. The page pulled the week's earthquakes once, then asked four questions of the answer in plain JavaScript.
const { features } = await quakes.queryFeatures({
where: "1=1",
outFields: ["mag", "place", "time"],
});
kpiTotal.textContent = features.length.toLocaleString();
kpiBig.textContent = features
.filter((f) => f.attributes.mag >= 4.5).length.toLocaleString();
const strongest = [...features]
.sort((a, b) => b.attributes.mag - a.attributes.mag)[0];
kpiMax.textContent = `M ${strongest.attributes.mag.toFixed(1)}`;
const newest = features.reduce((a, b) =>
a.attributes.time > b.attributes.time ? a : b);
kpiRecent.textContent = agoText(newest.attributes.time);
Add the layout: map, list, and chart
The same query from above, laid out the way an operations room wants it: a map on the left, a ranked list and a chart on the right. Nothing new to teach here, just a different view of what you already computed.
Add one line: rows that steer the map
Click any row in the Strongest Five above and watch the board's map fly there. No widget wiring, no configuration panel: a list row is just a button, and a button can tell the map where to go. Add one listener to what you already built, and the pieces talk to each other.
row.addEventListener("click", () => {
mapEl.view.goTo({ target: feature.geometry, zoom: 6 });
});
The pattern: one layer, many questions
Everything in Demonstration 2, the numbers, the list, the histogram, came from one query against one layer, asked several questions in plain JavaScript afterward: how many, how many big ones, which one is strongest, how long since the last one, and how do they bin by magnitude. Dashboards-the-product does a fine job of this, and for routine internal boards it is still the right call. The difference here is ownership: about two hundred readable lines, your layout, your wording, your refresh policy, and nothing to license or configure. When you catch yourself fighting a dashboard product's layout grid, this pattern is the exit.
Demonstration 3
The operation
The reason the ladder exists. Four rungs build it one layer at a time: live radar, live storms, your organization's geography, then all of it on one screen answering one question: whose watch is the weather on?
Start here: the radar, live and refreshing
National weather radar, courtesy of NOAA by way of Iowa State's Mesonet, repainting itself every five minutes. One layer declaration, the first of three you'll see combined at the end.
const WMSLayer = await $arcgis.import(
"@arcgis/core/layers/WMSLayer.js");
mapEl.map.add(new WMSLayer({
url: "https://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi",
sublayers: [{ name: "nexrad-n0r" }],
opacity: 0.65,
refreshInterval: 5, // minutes; the layer refetches itself
}));
Add the second layer: storms, tracked as they move
Every active tropical system on Earth, from the National Hurricane Center by way of Esri's Living Atlas: observed track, forecast track, and the cone. The cards below count whatever is alive out there right now.
const HURRICANES = "https://services9.arcgis.com/RHVPKKiFTONKtxq3/arcgis/rest/services/Active_Hurricanes_v1/FeatureServer";
const cone = new FeatureLayer({ url: HURRICANES + "/4", opacity: 0.35 });
const track = new FeatureLayer({ url: HURRICANES + "/2" });
const positions = new FeatureLayer({ url: HURRICANES + "/0",
outFields: ["STORMNAME", "MAXWIND", "BASIN"] });
mapEl.map.addMany([cone, track, positions]);
Add the third layer: whose watch
The American Red Cross chapter boundaries from a public feature service, the last of the three layers before they combine. Click any chapter: the card answers with its name, region, and division, worded for a human.
const chapters = new FeatureLayer({
// The service name says 2022; the data inside is the current
// vintage (226 chapters). Names, not codes, in every card.
url: "https://services.arcgis.com/pGfbNJoYypmNq86F/arcgis/rest/services/Master_ARC_Geography_2022/FeatureServer/3",
outFields: ["Chapter", "Region", "Division"],
renderer: subtleOutlines,
});
mapEl.map.add(chapters);
mapEl.view.on("click", async (event) => {
const hit = await mapEl.view.hitTest(event, { include: chapters });
const result = hit.results.find((r) => r.graphic?.layer === chapters);
if (result) showCard(result.graphic.attributes); // name, region, division
});
Combine them: all of it, one screen
Radar, storms, and chapters together. Click a chapter to see who holds it; click a storm point for the forecast. This map does everything the three above it do, combined onto one screen.
// The exact three layers from the sections above, all on one map.
mapEl.map.addMany([chapters, radar, cone, track, positions]);
// Click handling now checks two layers instead of one.
mapEl.view.on("click", async (event) => {
const hit = await mapEl.view.hitTest(event,
{ include: [positions, chapters] });
const storm = hit.results.find((r) => r.graphic?.layer === positions);
const chapter = hit.results.find((r) => r.graphic?.layer === chapters);
if (storm) showStormCard(storm.graphic.attributes);
else if (chapter) showChapterCard(chapter.graphic.attributes);
});
Why this one matters
The moment live weather, live forecasts, and your own organization's geography share one screen, the map stops being a picture and becomes an operations tool. The question changes from "what does the weather look like" to "whose chapter is it over, and what is coming next."
Every layer in this demonstration is public and free, and assembling them took five layer declarations, every one already shown above. That assembly, layers nobody thought to put together, answering a question only you thought to ask, is the real trick. And this is still the shallow end: with a signed-in ArcGIS account the same kit reaches your org's private layers, live shelter status, and editing from the field. That is the next conversation.
Demonstration 4
Live sky
The first demonstration built to let loose. Hundreds of real aircraft over the continental United States right now, tracked by a worldwide network of volunteer radio receivers and free to query. No dashboard product has ever shipped a widget for this.
Start here: every plane over the country
Every aircraft currently reporting a position within 250 nautical miles of the center of the continental United States, one of the busiest patches of sky on Earth. Refreshed every minute; watch the count change as flights take off and land.
const res = await fetch("/api/flights");
const { states } = await res.json();
const graphics = states.map((s) => new Graphic({
geometry: { type: "point", longitude: s.lon, latitude: s.lat },
attributes: s,
}));
const planes = new FeatureLayer({
source: graphics,
objectIdField: "icao24",
fields: [
{ name: "icao24", type: "string" },
{ name: "callsign", type: "string" },
{ name: "country", type: "string" },
{ name: "altitudeM", type: "double" },
{ name: "velocityMs", type: "double" },
],
renderer: dotRenderer,
});
mapEl.map.add(planes);
Add one property: color by altitude
Same layer, one visual variable. Pale dots are near the ground; the darkest red is cruising altitude. Nothing about the data changed, only how it's asked to draw itself.
const dotRenderer = {
type: "simple",
symbol: { type: "simple-marker", size: 5, outline: null },
visualVariables: [{
type: "color",
field: "altitudeM",
stops: [
{ value: 0, color: "#fff0f2" },
{ value: 12000, color: "#79000f" },
],
}],
};
Add one listener: click one
Click any aircraft in the map above for its callsign, country, altitude, and speed, read straight from the same fetch that drew the dot.
mapEl.view.on("click", async (event) => {
const hit = await mapEl.view.hitTest(event, { include: planes });
const result = hit.results.find((r) => r.graphic?.layer === planes);
if (!result) return;
showCard(result.graphic.attributes); // callsign, country, altitude, speed
});
Why a proxy
This is the one feed on the page your browser cannot fetch directly. The flight feed behind this demo doesn't send the header that would let sdk.jbf.com call it from a browser, a common and reasonable policy, so the two calls above actually go to /api/flights, a file in this repo's api/ folder that fetches the feed on the server and hands the answer to your browser. Same pattern as the Ask panel at the bottom of this page: when a feed says no to your domain, a small serverless function says yes on your behalf. It's the one honest complication in six demonstrations, and now you know what it looks like.
Demonstration 5
Live Earth
NASA watches the planet from orbit and publishes what it sees: every open wildfire, storm, volcano, and ice event on Earth, updated continuously, no key required.
Start here: what's happening right now
One request to NASA's Earth Observatory Natural Event Tracker returns every open event on the planet: wildfires, storms, volcanoes, ice, drought, and more, each one named in its own card.
const res = await fetch(
"https://eonet.gsfc.nasa.gov/api/v3/events?status=open");
const { events } = await res.json();
const graphics = events.map((e) => {
const point = e.geometry.at(-1); // most recent position
return new Graphic({
geometry: { type: "point", longitude: point.coordinates[0],
latitude: point.coordinates[1] },
attributes: { title: e.title, category: e.categories[0].title,
link: e.sources[0]?.url, date: point.date },
});
});
const events_ = new FeatureLayer({
source: graphics,
objectIdField: "oid",
fields: [ /* title, category, link, date */ ],
renderer: dotRenderer, // the same marker style as every other layer here
});
mapEl.map.add(events_);
Add one listener: click one
The same click pattern as every other demonstration on this page. Click any point in the map above, a wildfire, a storm, a volcano: the card names it, dates it, and links to NASA's own record.
mapEl.view.on("click", async (event) => {
const hit = await mapEl.view.hitTest(event, { include: events_ });
const result = hit.results.find((r) => r.graphic?.layer === events_);
if (result) showCard(result.graphic.attributes); // title, category, link
});
One query, one planet
Thirteen categories of natural event, tracked by NASA, in one request with no key and no sign-in. The pattern by now should feel familiar: fetch, style by category, listen for clicks, show a card. Five demonstrations in, that is the whole trick repeating; only the data changes.
Demonstration 6
Live Earth, in 3D
Back to the globe this page opened with. Half of it is dark right now, a real line you can compute, and there is a space station crossing it at 17,000 miles an hour.
Start here: half the planet is dark right now
The line between day and night is not a graphic anyone drew. It's a circle, a quarter of Earth's circumference wide, centered on whichever point currently faces the sun. The same geodesic buffer from Level 5, pointed at a different question.
const { solarLat, solarLon } = await (await fetch("/api/iss")).json();
// The boundary of this buffer, a quarter of Earth's circumference from
// the sun's point, IS the terminator.
const litHemisphere = geometryEngine.geodesicBuffer(
{ type: "point", longitude: solarLon, latitude: solarLat },
10007.5, // a quarter of Earth's circumference, in kilometers
"kilometers"
);
const terminatorLine = { type: "polyline", paths: litHemisphere.rings };
sceneEl.map.add(new GraphicsLayer({
elevationInfo: { mode: "on-the-ground" },
graphics: [new Graphic({ geometry: terminatorLine, symbol: goldLine })],
}));
Add one marker: the space station
The International Space Station's real position, updated every few seconds, orbiting once every ninety minutes at roughly 17,000 miles an hour.
Locating the space station…
setInterval(async () => {
const iss = await (await fetch("/api/iss")).json();
issGraphic.geometry = { type: "point",
longitude: iss.lon, latitude: iss.lat, z: iss.altitudeKm * 1000 };
}, 8000);
Closing the loop
The globe at the very top of this page span for fifteen lines and did one thing: exist. Six demonstrations later, the same kind of element carries live air traffic, every fire and storm on the planet, and the exact line between day and night, computed live from the position of the sun. Nothing about the SDK changed between then and now. What changed is what you now know to ask it for.
The Reference
The platform, mapped
The demonstrations end here; what follows is worth skimming now and returning to later. Esri's developer platform looks like a hundred products. For our work it is six, and they nest neatly.
ArcGIS Online
Where the data lives
The Red Cross org's cloud: hosted feature layers, web maps, groups, sharing. Every app we build reads layers from here (or from public services). You already know this one.
Maps SDK for JavaScript
The kit our apps are made of
Esri's box of finished map parts for web pages. One CDN line loads it. It has two faces: map components, HTML tags like <arcgis-map>, our default, and the core API (@arcgis/core) when we need fine-grained control.
Calcite Design System
Esri's UI parts
Buttons, panels, sliders, tabs, as web components (<calcite-button>). We use them styled with our own role-based color tokens so apps still look like Jeff's work, not Esri's demos.
ArcGIS REST APIs
The plumbing underneath
Every layer, query, geocode, and route is ultimately a web request to a REST endpoint. The SDK wraps these so we rarely call them raw, but when something odd happens, this is the layer to inspect.
Location Services
Ready-made answers
Basemaps, geocoding (address → point), routing, places. Pay-as-you-go with a generous free tier; authenticated with an API key.
The Builders
The path we grew out of
Experience Builder, Dashboards, Instant Apps, StoryMaps. Still right for routine internal apps; the SDK is for when you catch yourself saying "I wish it could just…".
The Brain: how the assistants stay smart
Not a giant download of the docs; that goes stale in weeks. Three small systems instead, each solving one problem. Full strategy in ARCGIS-BRAIN.md in this repo.
-
Live retrieval: never answer from memory
AI training data skews to SDK 4.x; the platform is on 5.x. So the assistants look everything up live through Context7, a service that continuously indexes all of developers.arcgis.com (about 80,000 documentation snippets), the REST API docs, and Calcite. Zero maintenance, always current.
-
Distilled knowledge: the house way of building
35 ArcGIS task skills installed in
.claude/skills/(maps, layers, popups, editing, 3D…), plus our own pattern files: popups disabled, app-owned sidebars, filters + zoom-to-results, Calcite with role tokens. Twenty pages we maintain beat twenty thousand we don't. -
Monitoring: the daily watcher
A GitHub Action checks npm every day for new releases of
@arcgis/core,@arcgis/map-components, and@esri/calcite-components. When something ships, it opens an issue with the release notes and a ready-made prompt: "read these, update the knowledge files." A few minutes per release and the Brain has learned it.
Your stack, end to end
Four services, each doing one job. This page traveled through three of them to reach you; Supabase joins the day an app needs a database.
GitHub
The permanent record
Every project is a repository: the files plus their entire history. A commit is a saved snapshot; a branch is a parallel draft; a pull request is a proposed change you can review before it lands. If it isn't in git, it doesn't exist.
Vercel
The publisher
Watches the GitHub repo. Every push deploys automatically: branches get preview URLs, main goes to the real domain. It can also run tiny server-side functions, the Ask panel below uses one.
Supabase
The database, when needed
A hosted Postgres database with instant APIs and login handling. Reach for it when an app needs data that isn't geographic (sign-ups, submissions, logs) while the map data stays in ArcGIS Online.
Claude Code & Codex
The builders
AI coding assistants that work inside the repo: they read every file, follow CLAUDE.md / AGENTS.md house rules, write and test code, commit, and open pull requests. They run on your machines and accounts, nothing touches the Red Cross ArcGIS org.
The dictionary
Every term from the training videos, in plain English. Type to filter.
- HTML
- The skeleton of a web page: nested tags that say what exists: a heading, a paragraph, a map. The ten-line file in the tour is pure HTML.
- CSS
- The clothing: rules that say what things look like: colors, sizes, layout. Our role-based color tokens (Red Cross red, ink, canvas) live in CSS.
- JavaScript
- The muscles: code that makes the page do things: load earthquake data, respond to clicks, animate hurricanes. The language the ArcGIS SDK speaks.
- DOM
- Document Object Model. The browser's live, in-memory model of the page: every tag becomes an object JavaScript can find and change. When code does
document.getElementById("globe"), it's reaching into the DOM. HTML is the recipe; the DOM is the dish. - Web component
- A custom HTML tag with behavior built in.
<arcgis-map>and<calcite-button>are web components: drop the tag in, get a working map or button. This is why modern SDK code looks like HTML. - SDK vs API
- An API is a menu of things you can ask a service to do. An SDK is the toolkit that makes asking easy: pre-built parts, documentation, examples. The Maps SDK wraps the ArcGIS REST APIs.
- CDN
- Content Delivery Network. Servers around the world that hand out files fast. One
<script>tag pointed atjs.arcgis.comloads the whole SDK from Esri's CDN, nothing to install. - npm
- The package manager for JavaScript. Where libraries live, each with a version number; it's how our watcher knows the moment Esri releases
@arcgis/core5.2. Simple apps skip npm and use the CDN. - React
- A popular library for building interfaces out of reusable components. Esri publishes React wrappers for its parts, but plain HTML + web components covers most of our apps with less machinery.
- JSON
- The universal text format for data:
{"mag": 5.4, "place": "Alaska"}. Every feed and REST response we touch is JSON. GeoJSON is the map flavor, with geometry included. - REST
- The convention for asking web services questions via URLs. Paste a feature layer URL in a browser and you're speaking REST to ArcGIS.
- FeatureLayer
- The workhorse: a layer of geographic features (points, lines, polygons) with attributes, served by ArcGIS. Filterable, queryable, stylable.
- Renderer
- The rule that decides how features draw: what color, what size, scaled by which attribute. The earthquake dots sized by magnitude are one renderer.
- Popup (and why ours are off)
- The default ArcGIS bubble that opens on click. We disable it everywhere and show feature details in an app-owned side panel instead; it's the signature of Jeff's map UX.
- Repository (repo)
- One project's home in git/GitHub: the files plus every version of them since the beginning.
- Commit & push
- A commit is a saved snapshot with a note. A push uploads commits to GitHub. Commit early, push often; it's the undo history for the whole project.
- Pull request (PR)
- A proposed set of changes on a branch, ready to review and merge into
main. The assistants open PRs so you can see exactly what changed before it goes live. - Deploy
- Publishing the code to a real URL. Vercel does it automatically on every push, preview URLs for branches, the live site for
main. - Serverless function
- A small piece of server code that runs on demand, no server to maintain. Files in this repo's
api/folder become live endpoints on Vercel. The Ask panel below is one. - Environment variable
- A secret setting (like an API key) stored on the server, never in the code. Set in Vercel's project settings so keys don't end up on GitHub.
- MCP
- Model Context Protocol. The standard plug that connects AI assistants to live tools and data. Context7 (the docs lookup in the Brain) is an MCP server.
- Skill
- A folder of instructions an AI assistant loads when relevant, a recipe card. The 35 ArcGIS skills in
.claude/skills/teach layer patterns, popup templates, 3D, and more. - CLAUDE.md / AGENTS.md
- Standing orders in the repo that every assistant session reads first: house design rules, knowledge sources, guardrails. The Brain is wired into every project through these files.
- LLM / model
- Large Language Model, the AI itself (Claude, GPT). "Training cutoff" is why they can't be trusted on fresh SDK details, and why the Brain's live-lookup rule exists.
No terms match, try a shorter word.
Set up a machine
Jeff's own checklist for giving the AI assistants live Esri docs and the house skills on a new computer; skip this section unless you are provisioning one. Everything below is also in SETUP.md in the repo.
-
Give the assistants live Esri docs (Context7)
In a terminal:
Terminal · once per machineclaude mcp add --scope user --transport http context7 https://mcp.context7.com/mcpFor Codex, add the equivalent server entry to
~/.codex/config.toml. Details inSETUP.md. -
Confirm the ArcGIS skills travel with each repo
This repo already has all 35 skills committed in
.claude/skills/, cloning it brings them along. For other projects:Terminal · per projectnpx skills add saschabrunnerch/arcgis-maps-sdk-js-ai-context -
Wire the Brain into your app standard
Paste the contents of
knowledge/CLAUDE-arcgis-snippet.mdinto the CLAUDE.md thatfranzen-app-standardsinstalls, so every new app repo gets the knowledge sources and guardrails automatically. -
Optional: turn on the Ask panel
In the Vercel project settings for this site, add an environment variable named
ANTHROPIC_API_KEYwith a key from console.anthropic.com, then redeploy. Note: the panel is then usable by anyone who can reach the site; keep the site unlisted, set a spend cap on the key, or protect it with Vercel authentication if that matters.
Ask a question
Anything on this page, the SDK, Calcite, the DOM, GitHub, Vercel, ask in plain English. For build tasks ("make me an app that…"), open Claude Code in the repo instead; this panel explains, it doesn't build.