Bundle requirements and limits
What a valid hosted app bundle looks like, the limits CARTO enforces, and the headers and CSP it serves
A hosted app is a directory of built static files. CARTO serves them as they were uploaded, under the rules on this page.
Bundle rules
A directory
You pass a directory to carto app deploy, not an archive.
index.html at the root
Required. Otherwise the deploy fails with Bundle directory must contain index.html at the root. Point the command at your build output, not at the project root.
Subdirectories
Preserved. Each file is served at its path in the bundle.
carto.json
At the root, it is the manifest: read when you deploy and never uploaded. In a subdirectory, it is an ordinary file.
Symbolic links
Skipped. Anything a link points to must be a real file inside the directory to be deployed.
Relative asset paths
The app is served under /app/<slug>/, not at the root of a domain, so asset URLs must be relative. In Vite, set base: './'. An absolute path like /assets/app.js returns 404.
Whole files
Files are always served whole. HTTP range requests are not supported.
Client-side routing
Client-side routing works, with one rule:
A page request to a path without a file extension and without a trailing
/that does not match any file returnsindex.html, so your router can handle it./app/my-app/dashboard/2026loads the app, but/app/my-app/dashboard/returns404.A path with a file extension that does not match any file returns
404./app/my-app/assets/missing.jsis an error, never HTML.
Limits
Total bundle size
50 MB
File size
25 MB
Files per bundle
1000
Slug
1 to 40 characters matching /^[a-z0-9](?:[a-z0-9-]{0,38}[a-z0-9])?$/: lowercase letters, digits and hyphens, not starting or ending with a hyphen
Version label
1 to 64 characters matching /^(?!.*\.\.)[a-zA-Z0-9.:_-]{1,64}$/: letters, digits, ., :, _ and -, with no ..
App name
1 to 200 characters
App description
Up to 2000 characters
Connections per manifest
20
Named Sources per connection
200
SQL per Named Source
100,000 characters
These limits are checked before any file is uploaded, so a bundle over a limit fails without uploading anything. If a bundle is too large, the usual causes are source maps and unoptimized images: disable source maps for the deployed build, and compress images.
Response headers
CARTO sets these headers on every file it serves from a bundle. A bundle cannot change them.
Cache-Control
no-store
Nothing is cached by the browser or by intermediate caches. A redeploy takes effect on the next page load, and every load downloads the bundle again, so keep it small.
Vary
Origin, Cookie, Authorization
Responses are tied to the user's session.
X-Frame-Options
SAMEORIGIN
The app cannot be embedded in an iframe on another site.
Content-Security-Policy
See below
The app can only load resources from, and connect to, the allowed origins.
Content-Type
Based on the file extension
Files with an unknown extension are served as application/octet-stream.
The Content Security Policy
CARTO serves this policy with every file of a bundle:
script-src
The bundle, inline scripts and eval, unpkg.com, cdn.jsdelivr.net and *.cartocdn.com.
style-src
The bundle, inline styles, unpkg.com, cdn.jsdelivr.net, *.cartocdn.com and fonts.googleapis.com.
connect-src
The bundle, *.carto.com, *.cartodb.com, *.cartocdn.com, *.googleapis.com, unpkg.com and cdn.jsdelivr.net.
img-src
The bundle, data: and blob: URIs, *.cartocdn.com, *.googleapis.com and *.gstatic.com.
font-src
The bundle, data: URIs, *.cartocdn.com and fonts.gstatic.com.
worker-src
The bundle and blob: URIs.
In practice:
Libraries load from the bundle, or from
unpkg.comandcdn.jsdelivr.net. Including them in the bundle is the most reliable option.Basemaps must come from an allowed origin, such as the CARTO basemaps (
BASEMAPin@deck.gl/carto), served from*.cartocdn.com.Images, fonts and other files from other hosts are blocked. Include them in the bundle, or use
data:URIs.APIs other than CARTO and the allowed origins cannot be called from the app.
Embedding the app in another site is not possible, because of
X-Frame-Options: SAMEORIGIN.
No environment variables or secrets
A hosted app has no environment variables and no secrets. Its configuration comes from two places:
carto-info.json, for the user's access token, the API base URL and the user's identity. See Runtime and authentication.The bundle, for anything else, set at build time.
Anyone who can open the app can read its files. Keep SQL in Named Sources, and never include a credential in the bundle.
Related
Runtime and authentication: sessions,
carto-info.json, sharing and versions.App manifest (
carto.json): the manifest at the root of the bundle.appcommand reference: every command and flag.
Last updated
Was this helpful?
