# Config and Project Layout

## Layout

```text
my-app/
├── src/                     # web source (edit here)
├── dist/                    # web build output = webDir (gitignored)
├── android/                 # native project: commit it
│   └── app/src/main/assets/public/   # generated by cap copy: never edit
├── ios/                     # native project: commit it
│   └── App/App/public/               # generated by cap copy: never edit
├── capacitor.config.ts
└── package.json
```

`.gitignore` essentials (the Capacitor templates already include most of these inside `android/` and `ios/`):

```gitignore
node_modules/
dist/
ios/App/Pods/
ios/App/App/public/
android/app/src/main/assets/public/
android/.gradle/
android/app/build/
android/build/
*.jks
*.keystore
.env*
.capgo_key_v2
```

## capacitor.config.ts

Prefer TypeScript config: it is type-checked against `CapacitorConfig` and can read env vars at `cap sync`/`copy` time.

```typescript
import type { CapacitorConfig } from '@capacitor/cli';

const devUrl = process.env.CAP_SERVER_URL; // only set in a dev shell

const config: CapacitorConfig = {
  appId: 'com.company.app',      // reverse-domain; changing it after release = new app
  appName: 'My App',
  webDir: 'dist',                // must match the bundler output
  ...(devUrl && { server: { url: devUrl, cleartext: devUrl.startsWith('http:') } }),
  plugins: {
    SplashScreen: { launchAutoHide: false }, // hide manually once the app renders
  },
};

export default config;
```

Traps:
- The config is evaluated when you run `cap sync`/`copy`, not at app runtime. Env vars present in your shell at sync time get baked into `capacitor.config.json` inside the native projects. Sync release builds from a clean shell or CI.
- `process.env.NODE_ENV === 'development'` is usually not set in the shell running the CLI. Use an explicit variable.
- `webContentsDebuggingEnabled`, `loggingBehavior` and `server.*` defaults are already safe for release. Leave them unset unless you have a reason.
- `capacitor.config.ts` wins over `.js`, which wins over `.json`. A stale `capacitor.config.json` next to a `.ts` is silently ignored: delete it.
- Capacitor 9 removes `cap run -l/--host/--port/--https`; use `npx cap run <platform> --url http://<ip>:<port>`.

## Environment-specific builds

For QA/staging/prod variants, follow the official guide: Xcode schemes/targets and Android product flavors, plus a per-environment Capacitor config selected by an env var at `cap copy` time (`NODE_ENV=qa npx cap copy`). https://capacitorjs.com/docs/guides/environment-specific-configurations

Keep different `appId`s per environment if testers install them side by side.

## Version alignment

```bash
npm ls @capacitor/core @capacitor/cli @capacitor/ios @capacitor/android
npx cap doctor
```

- Upgrade core packages together:
  ```bash
  npm install @capacitor/core@latest @capacitor/ios@latest @capacitor/android@latest
  npm install -D @capacitor/cli@latest
  npx cap sync
  ```
  `@latest` stays within the current stable major (8.x today). Major jumps go through `capacitor-app-upgrades`.
- `@capacitor/cli` belongs in `devDependencies`.
- Plugins: match the plugin major to the Capacitor major. Upgrading only plugins across a major without Capacitor (or the reverse) is the most common source of native build errors.
- Capacitor 9 is on the `next` tag (alpha). Only install with `@next` in a branch for evaluation.
