Product Configuration

Define the name version and unique identifier of your Tauri application in tauri.conf.json

The top‑level fields of tauri.conf.json that describe your app’s identity — its product name, version number, and bundle identifier — sit directly at the root of the file. They do not live inside app, build, or bundle. Together they control how your application is presented to users, how it is identified by the operating system, and how updates are matched across releases. Keep these in sync with Cargo.toml if you also set a crate version there.

Product Name

The productName field is the human‑readable name that appears in the window title bar, the operating system’s application list, installer dialogs, and the “About” box. If you leave it out, Tauri falls back to the name field from your Cargo.toml, but setting it explicitly gives you a name that is independent of the Rust package name and can contain spaces or branding.

// src-tauri/tauri.conf.json
{
  "productName": "My Tauri App"
}

The value must match the pattern ^[^/\:*?"<>|]+$ — essentially any characters except forward slash, backslash, colon, asterisk, question mark, double quote, less‑than, greater‑than, and pipe. A build will fail if any of those forbidden characters are present.

Name validation is strict:

Using a colon, slash, or any of the other prohibited characters in the product name produces a hard error during tauri build. The error message points directly at the invalid character so it is quick to fix, but catching it early saves a confusing first‑build experience.

Application Version

The version field accepts two forms: a direct SemVer string, or a path to a package.json file that contains a version field. When you omit it, Tauri reads the version from your Cargo.toml.

Using a package.json Path

For a React + Vite frontend where the package.json lives at the project root, the common pattern is to point the config at that file:

// src-tauri/tauri.conf.json
{
  "productName": "my-app",
  "version": "../package.json"
}

Tauri resolves the path relative to the location of tauri.conf.json. It then reads the "version" key from that JSON file — so "1.2.0" in package.json becomes 1.2.0 in the built application. This keeps the frontend’s version and the desktop bundle’s version synchronised without any duplication.

Using a SemVer String

A hard‑coded version is equally valid:

{
  "version": "1.0.0"
}

The string must follow Semantic Versioning. Pre‑release suffixes like 1.0.0-beta.1 are allowed, but anything that does not parse as valid SemVer will be rejected.

Invalid SemVer breaks the build:

A version like "1.0" (missing patch) or "version-1" causes a configuration parsing error. Always use the major.minor.patch format, with an optional pre‑release label after a hyphen.

How the Version Translates on Each Platform

The same version number feeds into platform‑specific metadata automatically:

  • macOS – becomes CFBundleShortVersionString and the default CFBundleVersion. You can override the bundle version separately via bundle > macOS > bundleVersion.
  • iOS – same as macOS; the tauri ios build command also provides a --build-number flag to append a build number.
  • Android – Tauri derives a versionCode integer from the SemVer fields (major * 1 000 000 + minor * 1 000 + patch). You can set a custom versionCode under bundle > android > versionCode.

This platform mapping happens automatically at build time — you do not need to duplicate version information for each target.

Bundle Identifier

The identifier field is a globally unique string that identifies your application to the operating system. It is the only required field in tauri.conf.json and must use reverse‑domain notation, such as com.mycompany.myapp. The operating system uses this value for:

  • The bundle ID on macOS and iOS
  • The application ID on Android
  • The Windows AppUserModelId
  • The path to the application’s private data directory (e.g. ~/.local/share/com.mycompany.myapp)

The string may contain only alphanumeric characters, hyphens, and periods. Spaces, underscores, and other symbols are not allowed.

// src-tauri/tauri.conf.json
{
  "identifier": "com.tauri.dev",
  "productName": "Tauri App"
}

Changing the identifier after release orphans user data:

The data directory is derived directly from the identifier. If you change identifier in a later release, the application will start with a fresh data store — all previously saved local data, preferences, and caches become invisible to the new version. Choose a stable reverse‑domain name early and stick with it.

For a personal project, com.github.<username>.<appname> or dev.<username>.<appname> are common choices. For a commercial product, use a domain you control, reversed.

Overriding the Binary Name

The mainBinaryName field lets you rename the compiled executable without changing the Cargo package name. Tauri normally takes the binary name from Cargo.toml. If you set mainBinaryName, the CLI renames the executable after compilation and wires the bundler to use that new name. Do not include the file extension — .exe, .app, or none — Tauri appends it automatically for each platform.

{
  "mainBinaryName": "my-launcher"
}

This is useful when the crate name contains underscores or is tied to an internal naming convention that you do not want exposed as the user‑facing executable.

A Complete Product Configuration

Below is a minimal but valid tauri.conf.json for a React + Vite application, showing all four product‑identity fields together with the essential build and app blocks that make the project runnable.

// src-tauri/tauri.conf.json
{
  "productName": "My App",
  "version": "../package.json",
  "identifier": "com.example.myapp",
  "mainBinaryName": "my-app",
  "build": {
    "beforeDevCommand": "npm run dev",
    "beforeBuildCommand": "npm run build",
    "devUrl": "http://localhost:1420",
    "frontendDist": "../dist"
  },
  "app": {
    "windows": [
      {
        "title": "My App",
        "width": 800,
        "height": 600
      }
    ],
    "security": {
      "csp": null
    }
  },
  "bundle": {},
  "plugins": {}
}

Everything in the right place:

With this structure, tauri dev starts the Vite dev server and opens a window titled “My App”, and tauri build produces a bundle that uses the version from your frontend’s package.json and the unique ID com.example.myapp. Nothing is buried inside a wrong object — product fields stay at the root.

Common Mistakes

Misplaced product fields are the single most frequent configuration error when moving from older Tauri versions or example code.

Confusing Tauri v1 and Tauri v2 Structures

Tauri v1 placed product information inside a "package" object and build‑related paths inside "build" with different key names. Tauri v2 flattened those fields to the root. If you see an error like Additional properties are not allowed ('package' was unexpected), you are feeding a v1‑style config to a v2 CLI.

// ❌ Tauri v1 style — will be rejected in v2
{
  "package": {
    "productName": "my-app",
    "version": "0.1.0"
  },
  "build": {
    "distDir": "../dist",
    "devPath": "http://localhost:1420"
  }
}

The package wrapper and the old distDir/devPath keys do not exist in v2. Use the root‑level fields and the new names frontendDist/devUrl instead.

Placing Product Fields Inside app or bundle

Another common slip is nesting the identifier or product name inside app, bundle, or plugins. Those objects have their own schemas and will reject unknown keys.

// ❌ Wrong location — identifier inside app
{
  "app": {
    "identifier": "com.example.app"
  }
}

The only valid location for identifier, productName, version, and mainBinaryName is directly at the root of the configuration object.

Note:

The optional $schema field (pointing to the Tauri JSON schema) enables autocompletion and inline validation in editors like VS Code. Adding "$schema": "node_modules/@tauri-apps/cli/schema.json" helps catch placement errors before you even run a build.


The name, version, and identifier you choose at the start become the permanent identity of your application in the user’s system. A clear reverse‑domain identifier is the bedrock of platform integration, and linking the version to package.json keeps every release consistently labelled. When you later configure builds, bundles, and updaters, Tauri will thread these same three values through every artifact — so investing the care to set them correctly here saves time across the entire project lifecycle.