A Tauri project is an ordinary web project with a Rust project tucked inside a src-tauri folder. This chapter explains what each file does, then looks at the tauri.conf.json configuration file and the capabilities folder that grants permissions.
The overall layout
A project created from the Vite and TypeScript template looks roughly like this:
tauri-app/
├── package.json # frontend dependencies and scripts
├── index.html
├── vite.config.ts
├── src/ # frontend code
│ └── main.ts
└── src-tauri/ # Rust core
├── Cargo.toml
├── build.rs
├── tauri.conf.json # Tauri configuration
├── capabilities/
│ └── default.json # per-window permissions
├── icons/
└── src/
├── main.rs # desktop entry point
└── lib.rs # the app itself, shared with mobile
The frontend half is a regular web project. Any framework works as long as it can produce static HTML, CSS and JavaScript. Tauri does not run a Node.js server alongside your app, so frameworks such as Next.js or SvelteKit must be configured for static export or SPA mode.
src-tauri: the Rust core
Cargo.toml lists the Rust dependencies. The template builds a library crate that is shared by the desktop executable and the mobile builds.
[package]
name = "tauri-app"
version = "0.1.0"
edition = "2021"
[lib]
name = "tauri_app_lib"
crate-type = ["staticlib", "cdylib", "rlib"]
[build-dependencies]
tauri-build = { version = "2", features = [] }
[dependencies]
tauri = { version = "2", features = [] }
tauri-plugin-opener = "2"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
build.rs runs tauri_build::build(), which reads the configuration and permission files and generates code needed at compile time. main.rs is the desktop entry point and simply calls the library's run function; the real app lives in lib.rs. The split exists because mobile builds do not use a main function: they enter through the run function marked with #[cfg_attr(mobile, tauri::mobile_entry_point)].
// src-tauri/src/main.rs
// Prevents an extra console window on Windows in release builds
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
fn main() {
tauri_app_lib::run()
}
tauri.conf.json
The app name, version, windows, security and bundling settings all live in this file. The template's version looks like this:
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "tauri-app",
"version": "0.1.0",
"identifier": "com.example.tauri-app",
"build": {
"beforeDevCommand": "npm run dev",
"devUrl": "http://localhost:1420",
"beforeBuildCommand": "npm run build",
"frontendDist": "../dist"
},
"app": {
"windows": [{ "title": "tauri-app", "width": 800, "height": 600 }],
"security": { "csp": null }
},
"bundle": {
"active": true,
"targets": "all",
"icon": ["icons/32x32.png", "icons/128x128.png", "icons/icon.icns", "icons/icon.ico"]
}
}
For platform-specific settings, add tauri.windows.conf.json, tauri.macos.conf.json, tauri.linux.conf.json, tauri.android.conf.json or tauri.ios.conf.json next to the main file. When building for that platform, its values are merged over the base configuration. The --config flag merges an additional file on demand.
capabilities: permissions per window
In Tauri 2, capability files decide what code running in the WebView may do. Every file in src-tauri/capabilities is enabled by default.
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default",
"description": "Default permissions for the main window",
"windows": ["main"],
"permissions": ["core:default", "opener:default"]
}
windows lists the labels of the windows that receive the capability, and permissions lists the permission identifiers to allow. The gen/schemas folder is generated during the build; its schemas let your editor autocomplete every available permission name. Chapter 3 covers the security model in depth.
Other conventions
- Do not draw icons by hand for every size; generate the
icons/ folder with npm run tauri icon. - The template's Vite config pins the dev server port (
strictPort) and ignores changes in src-tauri. src-tauri/target holds Rust build output and stays out of version control; Cargo.lock is committed.- As the Rust side grows, keep only app assembly in
lib.rs and move commands into modules such as commands.rs.
Summary
- The frontend is a normal web project; the Rust core lives in
src-tauri. - The app is built in the
run function of lib.rs, and main.rs only calls it. tauri.conf.json covers build, window, security and bundle settings, with optional per-platform overrides.- Files in
capabilities decide which permissions each window receives.
0 comments
Sign in · Sign in to leave a comment.