Environment Config

Environment Variables and capacitor.config.json

A .ts config is a program: the CLI evaluates it in Node on every run, so it can read process.env. That keeps the live-reload settings of The server Block out of release builds:

Adding the server block only when CAP_LIVE_URL is setJavaScript
const liveUrl = process.env.CAP_LIVE_URL; // set only while developing
// ... inside the config object:
  ...(liveUrl && { server: { url: liveUrl, cleartext: true } }),
The same config copied with and without the variable
CAP_LIVE_URL=http://localhost:5813 npx cap copy android
node -p "require('./android/app/src/main/assets/capacitor.config.json').server"
npx cap copy android
node -p "require('./android/app/src/main/assets/capacitor.config.json').server"
Output
...
{ url: 'http://localhost:5813', cleartext: true }
...
undefined

The variable is read during copy and frozen into the APK's JSON; values the web code needs at run time belong in your bundler's variables (Vite 25,978 's import.meta.env).

capacitor.config.json holds the same keys as plain data, with no imports or logic. The .ts route has a trap: the CLI loads it through TypeScript's classic compiler API, which TypeScript 7 no longer exports. With typescript@7.0.2, npm 2,036 's latest, every sync failed with [error] Parsing capacitor.config.ts failed. The CLI's fallback, Node's built-in type stripping, needs Node.js 23.6 2,131 +, or 22.6+ with --experimental-strip-types; Ubuntu 225 's Node 22 build lacks it (ERR_NO_TYPESCRIPT). Pinning typescript@6 fixed sync at once.