One command to a working ArcGIS app: the @arcgis/create CLI
Every framework worth using has a scaffolding command. React has one. Vue has one. Vite has
one. For years, starting an ArcGIS Maps SDK for JavaScript project meant doing it the long way —
scaffold a bare app, install three packages, guess at the CSS imports, discover the asset path problem in
production. Esri closed that gap: @arcgis/create generates a working, SDK-wired
project in one command, across seven templates.
This post covers what the CLI actually produces, how it differs from the CDN path, the one CSS behaviour that still catches people migrating from widgets, and the short list of things the template deliberately does not do for you — the gap between “it runs” and “it ships.”
Two ways in, and they solve different problems
Esri’s Get started guide now frames the decision cleanly. There is a CDN path and an npm path, and the honest answer to “which one” is that they are not competing — they serve different stages of work.
| ArcGIS CDN | npm + @arcgis/create | |
|---|---|---|
| Setup | One <script type="module"> tag | One CLI command, then npm install |
| Build step | None | Vite / Angular / Webpack, per template |
| Module loading | $arcgis.import() — CDN-exclusive, not standard ESM | Standard ESM import statements |
| Versioning | URL-pinned: MAJOR.MINOR or MAJOR.MINOR.PATCH | package.json + lockfile |
| Bundle control | None — you get the hosted build | Tree-shaking, code-splitting, your own asset strategy |
| Best for | Demos, embeds, single-file pages, teams without a build pipeline | Products, anything with tests, CI, or a design system |
The current CDN entry point is version-pinned in the URL:
<!-- Load the ArcGIS Maps SDK for JavaScript from CDN --> <script type="module" src="https://js.arcgis.com/5.1/"></script>
js.arcgis.com/5.0/ it will keep working
— but check the release notes before you bump, and note that Esri publishes the latest
patch version there too if you need MAJOR.MINOR.PATCH precision.What the CLI does
The @arcgis/create
tool runs through either npm init or npx. Run it with
no arguments and it prompts you interactively:
# interactive — either form works
npm init @arcgis
npx @arcgis/create
Or skip the prompts entirely with flags, which is what you want in a documented setup script or a repeatable team workflow:
# CLI options: # -n, --name <name> Name of the project # -t, --template <template> Template to use npx @arcgis/create -n my-arcgis-app -t vite
Seven templates ship today, and the naming is exactly what you would guess:
| Template flag | What you get |
|---|---|
vite | Vite + vanilla JavaScript, SDK integrated |
react | React app with the SDK wired in |
angular | Angular workspace with the SDK wired in |
vue | Vue app with the SDK wired in |
webpack | Webpack build, for teams already standardised on it |
cdn | Static starter using the CDN entry point — no install |
node | Server-side / headless use of the core API |
If you would rather read the templates before you run anything, they live in the public Esri/jsapi-resources repository. Esri notes these demonstrate working with the core API, components, OAuth, and Calcite — the OAuth template in particular is worth reading before you hand-roll an auth flow.
What a generated project contains
Under the hood the templates install the same three packages you would install by hand:
npm install @arcgis/map-components @arcgis/core @esri/calcite-components
That split matters and is worth internalising. @arcgis/core is the core API
— layers, geometry, renderers, query. @arcgis/map-components is one of
six component libraries the SDK now ships (Map, Charts, AI in beta, Embeddable, Coding, and
Common). @esri/calcite-components is Esri’s
Calcite Design
System, which supplies the surrounding UI shell.
Components are registered by importing them, which is easy to miss if you are used to widgets:
import "./index.css"; import "@arcgis/map-components/components/arcgis-map"; import "@arcgis/map-components/components/arcgis-zoom"; import Graphic from "@arcgis/core/Graphic.js"; const viewElement = document.querySelector("arcgis-map"); // Wait for the view to be ready before adding functionality viewElement.addEventListener("arcgisViewReadyChange", () => { const pointGraphic = new Graphic({ geometry: point, symbol: markerSymbol }); viewElement.graphics.add(pointGraphic); });
The import is not decoration — it registers the custom element with the browser’s
CustomElementRegistry. Forget it and <arcgis-map>
renders as an inert unknown element with no error in the console. That silence is the single most common
“why is my map blank” in a component-based project.
The CSS trap that still catches people
This is the detail worth the price of admission. When you use components via npm, the SDK’s component styles and Calcite styles are loaded for you. You only need enough app CSS to give the map a box with height:
/* index.css */ html, body { height: 100%; margin: 0; }
But if any part of your app still uses widgets, or programmatically constructs a MapView or
SceneView instead of using the Map or Scene component, you must still import the
core API stylesheet yourself:
/* only needed if you use widgets or a programmatic MapView/SceneView */ @import "@arcgis/core/assets/esri/themes/light/main.css";
The failure mode is unusually confusing: a half-migrated app looks almost right — the map draws, the components look fine — and only the remaining widgets render unstyled. It reads like a broken widget rather than a missing stylesheet.
What the template does not do for you
A generated project runs. That is not the same as ready to ship. Five things we add on every ArcGIS project before it is allowed near a client environment:
- Move the API key out of source. Templates put a key where you can find it. Production reads it from an environment variable and the key itself is scoped to the referrers and services the app actually needs — nothing more.
- Pin the dev server port. API key referrer restrictions and OAuth redirect URIs are origin-bound. A dev server that silently picks a new port when the old one is busy will fail auth in ways that look like credential problems. Fix the port; make it strict.
- Decide the asset strategy early. The default pulls SDK assets from Esri’s CDN. Disconnected or air-gapped deployments need local assets — see Esri’s working with assets guide. Retrofitting this after the fact is unpleasant.
- Replace the default chrome. A template app looks like a template app. If the map is your product, the UI around it needs to be designed — Calcite theming, your typography, your colours, real cartography.
- Add accessibility and performance budgets. Keyboard reachability for every map control, contrast that passes WCAG, and a hard ceiling on initial bundle size. Map apps regress on all three quietly.
npm run dev for architecture. The decisions that determine whether the app is
still maintainable in two years — auth model, asset strategy, component boundaries, state ownership
— are all still yours, and the template is deliberately silent on every one of them.References
- Get started — ArcGIS Maps SDK for JavaScript (CDN and npm paths, @arcgis/create usage)
- Using the SDK in a Vite JavaScript app — installation, CSS, component imports
- ArcGIS Maps SDK for JavaScript release notes
- Components transition plan — migrating from widgets
- Working with assets — local assets and disconnected deployments
- Esri/jsapi-resources — application templates (core API, components, OAuth, Calcite)
- @arcgis/create on npm
Scaffolding is the easy part.
We build ArcGIS applications where the auth model, asset strategy, design system, and performance budget are decided before the first commit — not discovered in production.
Book a free intro call