tauri.conf.json - The Core Configuration File

A complete reference for the Tauri v2 configuration file covering its structure, every major section, platform-specific overrides, CLI extension, and common pitfalls beginners hit.

Every Tauri project contains a single file that acts as the bridge between your frontend, the Rust backend, the build process, and the final application bundle. That file is tauri.conf.json. If you have ever wondered how Tauri knows where your frontend lives, what the app should be called, or which window features to enable, this is where the answers live.

What tauri.conf.json Actually Is

tauri.conf.json is the main configuration file for a Tauri v2 application. It sits inside the src-tauri/ directory and is read by two separate consumers: the Tauri CLI (for building, dev server, and bundling) and the Tauri runtime that ships inside your final app. It also doubles as a marker — when the Tauri CLI runs, it looks for this file to locate the Rust project root.

Not the Only Config File:

The tauri.conf.json is not the only configuration Tauri reads. Capability files in src-tauri/capabilities/, platform-specific config files, and even command-line overrides all contribute to the final configuration object. But everything starts from this file.

Think of tauri.conf.json as the single source of truth for metadata that every part of the toolchain needs: your app’s name, its unique ID, the URL of your dev server, which plugins are active, and how the final installer should look. Without it, the CLI would not know where the project begins.

File Location and Supported Formats

The file lives at src-tauri/tauri.conf.json for every standard Tauri project. While JSON is the default, Tauri also supports JSON5 and TOML — but only if you explicitly opt in.

If you prefer JSON5 (which allows comments and trailing commas) or TOML (which uses a more readable kebab-case convention), you must enable the corresponding Cargo feature in src-tauri/Cargo.toml:

src-tauri/Cargo.toml
[build-dependencies]
tauri-build = { version = "2.0.0", features = ["config-json5"] }
[dependencies]
tauri = { version = "2.0.0", features = ["config-json5"] }

For TOML, replace "config-json5" with "config-toml" and name your file Tauri.toml. The structure is identical across formats, only the syntax changes.

src-tauri/tauri.conf.json
{
  "productName": "MyApp",
  "version": "0.1.0",
  "identifier": "com.example.myapp",
  "build": {
    "devUrl": "http://localhost:1420",
    "frontendDist": "../dist"
  },
  "app": {
    "windows": [
      {
        "title": "MyApp",
        "width": 800,
        "height": 600
      }
    ]
  }
}

The JSON example shows the standard minimal shape. The TOML example demonstrates how arrays of objects (like windows) use double brackets. Field names are case-sensitive in all formats, and TOML allows kebab-case for keys — a style the Tauri documentation often uses in reference materials.

The Top-Level Structure

Every tauri.conf.json contains five top-level objects and a few standalone fields. Here is the skeleton:

FieldRequiredPurpose
productNameNo (recommended)The human-readable app name.
versionNo (recommended)Semver version or path to a package.json with a version field.
identifierYesReverse-domain unique app ID (e.g. com.example.app).
buildNoControls how Tauri finds and builds the frontend.
appNoWindow management, security, tray, and global Tauri settings.
bundleNoInstaller and packaging configuration.
pluginsNoPlugin-specific configuration (like updater, deep-link).
mainBinaryNameNoOverride the final binary filename (without extension).

Identifier Is Not Optional:

The identifier field is not optional at runtime or for bundling. It is used for the bundle ID on macOS, the application ID on Linux, and the path to the webview data directory. It must contain only alphanumeric characters, hyphens, and periods — no spaces or underscores.

The version field can either be a string like "1.2.3" or a relative path to a package.json that contains a version field. If you omit version entirely, Tauri falls back to the version in Cargo.toml, but the official recommendation is to manage your app version in this config file to keep frontend and backend versioning consistent.

With the skeleton in mind, let’s walk through each section in detail.

The build Section: How Tauri Finds Your Frontend

The build object tells the CLI how to start your dev server, where to find the built frontend assets, and what auxiliary files to watch for changes.

src-tauri/tauri.conf.json
{
  "build": {
    "devUrl": "http://localhost:1420",
    "frontendDist": "../dist",
    "beforeDevCommand": "npm run dev",
    "beforeBuildCommand": "npm run build",
    "additionalWatchFolders": ["../shared-assets"]
  }
}

During tauri dev, the CLI starts the process defined in beforeDevCommand, waits for it to be ready, and then opens devUrl in a webview. During tauri build, the CLI runs beforeBuildCommand, then takes the contents of the frontendDist directory and embeds them into the final binary.

devUrl can point to any HTTP server — localhost with a specific port is the most common setup. frontendDist is a path relative to the src-tauri directory, so ../dist means the dist/ folder at the project root.

additionalWatchFolders is useful when your frontend build depends on files outside the normal project tree. Tauri watches these folders during development and triggers a rebuild when they change.

Works With Any Frontend Framework:

Because Tauri only cares about the final static files, you can swap React for Vue, Svelte, or plain HTML. The config stays the same — you only change the commands and the output folder.

The app Section: Windows, Security, and Runtime Behavior

The app object is where the runtime behavior of your Tauri app lives. It controls windows, security policies, tray icons, and global Tauri API availability.

Window Configuration

Every Tauri app starts with at least one window, defined in the windows array. Window configuration covers size, position, and appearance in more depth. Here is a production-like setup:

src-tauri/tauri.conf.json
{
  "app": {
    "windows": [
      {
        "label": "main",
        "title": "My Tauri App",
        "width": 1024,
        "height": 768,
        "resizable": true,
        "fullscreen": false,
        "decorations": true,
        "center": true
      }
    ]
  }
}

Each window object can contain more than a dozen properties, but the most commonly used ones are label (a unique identifier used to target the window from Rust code), title, width, height, and resizable. The center property places the window in the middle of the primary monitor on launch.

The label is especially important because security capabilities reference windows by label. If you later add a second window for a settings panel, it will need its own capability entry.

Security and Capabilities

The security key inside app is how Tauri v2 enforces its permission model. You must explicitly declare which capabilities each window can use.

src-tauri/tauri.conf.json
{
  "app": {
    "security": {
      "capabilities": ["main-capability", "settings-capability"],
      "csp": "default-src 'self'; img-src 'self' asset: https://asset.localhost blob: data:"
    }
  }
}

The capabilities array lists identifiers that reference files inside src-tauri/capabilities/. For example, main-capability maps to src-tauri/capabilities/main-capability.json. Tauri v2 also allows defining capabilities inline as JSON objects directly in this array, but using separate files is the standard approach and keeps the main config clean.

The Content Security Policy (CSP) string restricts what the webview can load. If you set it to null, Tauri will not inject a CSP at all. Leaving it unset means Tauri uses its built-in default, which is already restrictive. Most applications can leave it out unless they need to load remote images or fonts.

Capabilities Are Required for API Access:

Without a capability that permits a command (like fs:allow-read-file), any call from the frontend to that Tauri API will be silently blocked. A common beginner mistake is trying to use @tauri-apps/plugin-fs without enabling its permissions. If your frontend code seems to do nothing, check that the capability file is correctly referenced here.

Other App-Level Settings

Two fields in app that are worth knowing, though they are less frequently changed:

  • withGlobalTauri (boolean, default false): When set to true, Tauri exposes its core API under window.__TAURI__ in addition to the ES module import. This is primarily for projects that cannot use ES modules.
  • enableGTKAppId (boolean, default false): On Linux systems that use GTK, setting this to true registers the identifier as the GTK application ID, which helps the desktop environment group windows correctly.

The bundle Section: Packaging and Distribution

The bundle object controls how tauri build creates installers and app bundles. Bundle configuration covers installer formats and platform-specific packaging. The absolute minimum to enable bundling is setting active to true and providing an icon path.

src-tauri/tauri.conf.json
{
  "bundle": {
    "active": true,
    "icon": [
      "icons/32x32.png",
      "icons/128x128.png",
      "icons/icon.icns",
      "icons/icon.ico"
    ],
    "targets": "all"
  }
}

The targets field can be "all", a string like "msi", or an array of specific bundle types (["deb", "appimage"]). The icon array should include all required sizes for each platform — Tauri automatically selects the right one based on the target OS.

Each platform has its own sub-configuration, deeply nested under bundle. Here are the most important ones for a production app:

PlatformKeyTypical Use
Windowswindows.wix or windows.nsisChoose installer technology.
macOSmacOS.minimumSystemVersionSet minimum macOS version (default 10.13).
Linuxlinux.deb.filesMap extra files into the .deb package.
Androidandroid.minSdkVersionMinimum Android API level (default 24).
iOSiOS.minimumSystemVersionMinimum iOS version (default 14.0).

Icons Are Not Optional for Bundling:

Running tauri build without icons in the config will fail. The tauri icon command generates the required set from a single source image and places them in src-tauri/icons/. Run it once before your first build.

The plugins Section: Configuring Tauri Plugins

Plugins that need their own configuration — such as the updater, deep-link handler, or CLI plugin — read their settings from the plugins object.

src-tauri/tauri.conf.json
{
  "plugins": {
    "updater": {
      "endpoints": [
        "https://cdn.example.com/update/{{target}}/{{arch}}/{{current_version}}"
      ],
      "pubkey": "YOUR_PUBLIC_KEY_HERE",
      "dialog": true
    }
  }
}

This example configures the updater plugin to check a remote endpoint for new versions and display a dialog to the user when an update is found. The pubkey field must match the public key you generated with cargo tauri signer generate. Without it, update verification is impossible.

Different plugins have entirely different configuration shapes. Always refer to the specific plugin’s documentation. The plugins object is not validated against a universal schema — each plugin defines its own keys.

Platform-Specific Configuration Files

Tauri can merge separate configuration files for specific platforms. This is useful when the same application needs slightly different settings on Windows versus macOS — for example, different window titles, different signing identities, or different plugin configurations.

The naming convention follows the pattern tauri.{platform}.conf.json:

  • tauri.linux.conf.json
  • tauri.macos.conf.json
  • tauri.windows.conf.json
  • tauri.android.conf.json
  • tauri.ios.conf.json

These files sit next to tauri.conf.json in src-tauri/. Tauri merges them using the JSON Merge Patch (RFC 7396) specification. That means any key you define in the platform-specific file completely replaces the corresponding key from the base config — it is not a deep recursive merge.

src-tauri/tauri.linux.conf.json
{
  "productName": "my-app-linux",
  "bundle": {
    "resources": ["./linux-assets"]
  }
}

Given a base config with "productName": "MyApp" and no resources, the resolved Linux config would have productName set to "my-app-linux" and resources set to ["./linux-assets"]. All other fields remain as they were in the base.

This merging happens transparently when you run tauri build or tauri dev on the respective platform. You do not need to specify which config to use — Tauri detects the platform automatically.

Extending Configuration via the CLI

Sometimes you need to tweak the configuration without permanently changing the file — for example, building a beta version with a different app identifier and name. Tauri supports a --config flag on dev, build, and bundle commands that accepts either a raw JSON string or a path to a JSON file.

Create a separate config file with only the overrides:

src-tauri/tauri.beta.conf.json
{
  "productName": "MyApp Beta",
  "identifier": "com.example.myapp.beta"
}

Then pass it during the build:

npm run tauri build -- --config src-tauri/tauri.beta.conf.json

The merge follows the same RFC 7396 rules. This mechanism lets you maintain a single codebase while producing multiple variants of your app — stable, beta, nightly, and so on — without duplicating the full configuration.

Common Configuration Mistakes

Over the years, the most frequent source of confusion in tauri.conf.json comes from mixing Tauri v1 and v2 syntax. Tauri v2 moved many keys to different locations and renamed others.

The Number One Mistake: v1 Keys in a v2 Project:

If you see errors like Additional properties are not allowed ('bundle' was unexpected) or Additional properties are not allowed ('devPath', 'distDir' were unexpected), you are using Tauri v1 keys in a Tauri v2 configuration. In v2, bundle is a top-level key — not nested under app or tauri. The devPath and distDir keys are now devUrl and frontendDist respectively. Also, there is no "tauri" wrapper object in v2; all keys are at the root.

Another pattern that trips up beginners is forgetting the capabilities array in app.security. A correctly structured capability file referenced by name in the config works, but if the reference is missing, the entire capability is ignored, and the frontend API calls silently fail.

The Fastest Way to Validate Your Config:

Run tauri dev and watch the terminal output. If the config is invalid, the CLI will reject it immediately with a specific error message. A successful dev server launch means your configuration is structurally sound.

What tauri.conf.json Unlocks Next

tauri.conf.json is the starting point for every Tauri project, but it is not self-contained. The capabilities array inside app.security points to files in the capabilities/ directory, which you must understand to grant API access to your frontend. The plugins object references plugins that you register in Rust and import in JavaScript. And the bundle section relies on icons you generate with the tauri icon command.