
Building Cross-Platform Apps with Tauri & React - Part 1: Project Setup
Learn how to set up a modern cross-platform application using Tauri 2.0, React, and TypeScript. This comprehensive guide covers everything from creating your first Tauri project to configuring shadcn/ui for a beautiful user interface.
Manish Kumar
Software Development Engineer with 1.5+ years of experience in back-end development and DevOps. Skilled in Go, Python, and TypeScript with expertise in building microservices, gRPC APIs, and WebSocket servers. Experienced in CI/CD automation, Docker-based deployments, and cloud infrastructure management. Passionate about clean architecture, scalable systems, and developer productivity.
Manish Kumar
Software Development Engineer with 1.5+ years of experience in back-end development and DevOps. Skilled in Go, Python, and TypeScript with expertise in building microservices, gRPC APIs, and WebSocket servers. Experienced in CI/CD automation, Docker-based deployments, and cloud infrastructure management. Passionate about clean architecture, scalable systems, and developer productivity.
Building Cross-Platform Apps with Tauri & React
๐ Series: Part 1 of 3
This is Part 1 of a comprehensive 3-part series on building cross-platform applications. In this part, we'll set up the foundation of our project with Tauri, React, and shadcn/ui.
Have you ever wanted to build a desktop application that also works on Android, using the same codebase? With Tauri 2.0, this dream becomes reality. Tauri is a revolutionary framework that lets you build lightweight, secure, and cross-platform applications using web technologies.
In this three-part tutorial series, we'll build a complete Task Management System that runs on Windows, macOS, Linux, and Android. We'll use React for the UI, Rust for the system layer, and Go for the backend API. By the end, you'll have a production-ready architecture that you can use for your own projects.
๐ฏ What We'll Build
A full-featured Task Management System with user management, CRUD operations, and a beautiful UI powered by shadcn/ui. The app will run natively on desktop platforms and Android with a single codebase.
In Part 1, we'll focus on setting up our development environment and creating the foundation of our project. Let's dive in!
Why Tauri?
Before we jump into the setup, let's understand why Tauri is an excellent choice for cross-platform development:
- Tiny Bundle Size: Tauri apps are significantly smaller than Electron apps (often 10-20x smaller)
- Better Performance: Uses the system's native webview instead of bundling Chromium
- Enhanced Security: Rust-powered backend provides memory safety and security by default
- True Cross-Platform: Desktop (Windows, macOS, Linux) and Mobile (Android, iOS coming soon)
- Modern DX: Use any web framework (React, Vue, Svelte, etc.) for the frontend
- Native Features: Access to system APIs through secure Rust commands
Architecture Overview
Our application follows a layered architecture that ensures separation of concerns and maintainability. Here's how the different layers interact:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ React Frontend Layer โ
โ โข Beautiful UI with shadcn/ui components โ
โ โข TypeScript for type safety โ
โ โข Custom hooks for state management โ
โ โข Form validation and user interactions โ
โโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ Tauri IPC (invoke)
โ Type-safe communication
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Rust Backend Layer โ
โ โข Tauri commands (exposed to frontend) โ
โ โข HTTP client for API communication โ
โ โข Type definitions and validation โ
โ โข Error handling and security โ
โโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ HTTP/REST API
โ JSON data exchange
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Go Backend Server โ
โ โข RESTful API endpoints โ
โ โข Business logic โ
โ โข Data persistence โ
โ โข CORS and middleware โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโThis architecture provides several benefits:
- Type Safety: Strong typing across all layers (TypeScript โ Rust โ Go)
- Separation of Concerns: Each layer has a clear, focused responsibility
- Scalability: Easy to scale or replace individual layers
- Testability: Each layer can be tested independently
- Security: Rust layer acts as a secure gateway between frontend and backend
Prerequisites
Before we begin, make sure you have the following tools installed and configured on your system. Don't worry if you haven't installed them yet - I'll provide links to help you get started.
Core Development Tools
- Node.js (v18 or higher) and npm - Download from https://nodejs.org
- Rust (latest stable version) - Install from https://rustup.rs
- Go (v1.21 or higher) - Install from https://go.dev/dl
- A code editor (VS Code recommended with Rust Analyzer and Go extensions)
For Android Development (Optional)
- Android Studio - Download from https://developer.android.com/studio
- Java Development Kit (JDK 17 or higher)
- Gradle (usually comes with Android Studio)
- Android SDK (install through Android Studio)
- ANDROID_HOME environment variable configured
- JAVA_HOME environment variable configured
โ ๏ธ Android Setup Requirements
If you plan to develop for Android, you must run 'sdkmanager --licenses' in your terminal to accept all Android SDK licenses. Also ensure that your ANDROID_HOME points to your Android SDK location.
Verify Your Installation
Run these commands to verify everything is installed correctly:
# Check Node.js and npm
node --version
npm --version
# Check Rust
rustc --version
cargo --version
# Check Go
go version
# Check Java (for Android)
java -versionStep 1: Creating Your Tauri Project
Let's create our Tauri application! Tauri provides a convenient scaffolding tool that sets up everything we need. Open your terminal and run:
npm create tauri-app@latestThe CLI will prompt you with several questions. Here's how to answer them for our project:
โ Project name ยท tauri-react-rust-app
โ Identifier ยท com.manishh.tauri-app
โ Choose which language to use for your frontend ยท TypeScript / JavaScript
โ Choose your package manager ยท npm
โ Choose your UI template ยท React
โ Choose your UI flavor ยท TypeScript
Template created! To get started run:
cd tauri-react-rust-app
npm install
npm run tauri android init๐ก Understanding the Options
Project name: The folder name for your project. Identifier: A unique reverse-domain identifier for your app (like com.yourname.appname). Package manager: We're using npm for this tutorial. UI template: React with TypeScript gives us the best developer experience.
Now let's navigate into the project directory and install dependencies:
cd tauri-react-rust-app
npm installThis will install all the necessary dependencies. The installation might take a few minutes depending on your internet connection.
Step 2: Understanding the Project Structure
Before we proceed, let's understand what was created. Your project now has this structure:
tauri-react-rust-app/
โโโ src/ # React frontend code
โ โโโ App.tsx # Main React component
โ โโโ App.css # Styles
โ โโโ main.tsx # React entry point
โ โโโ index.css # Global styles
โโโ src-tauri/ # Rust backend code
โ โโโ src/
โ โ โโโ main.rs # Rust entry point
โ โ โโโ lib.rs # Library code
โ โโโ Cargo.toml # Rust dependencies
โ โโโ tauri.conf.json # Tauri configuration
โ โโโ build.rs # Build script
โโโ public/ # Static assets
โโโ index.html # HTML template
โโโ package.json # Node dependencies
โโโ tsconfig.json # TypeScript config
โโโ vite.config.ts # Vite configKey directories explained:
- src/ - Your React frontend code lives here. This is where we'll build our UI components.
- src-tauri/ - The Rust backend code. This is where we'll write Tauri commands and API integration.
- src-tauri/Cargo.toml - Rust dependency management, similar to package.json for Node.
- tauri.conf.json - Tauri-specific configuration like window size, permissions, and build settings.
Step 3: Initialize Android Support
One of Tauri 2.0's most exciting features is native Android support. Even if you're primarily targeting desktop, it's worth setting this up now for future flexibility.
npm run tauri android initThis command generates an Android Studio project. You should see output like:
Generating Android Studio project...
Info "C:\Users\...\src-tauri" relative to "C:\Users\...\src-tauri\gen/android\tauri_app" is "..\..\..\"
Info Project generated successfully!
Make cool apps! ๐ป ๐ ๐This creates a new directory structure:
src-tauri/
โโโ gen/
โโโ android/ # Android Studio project
โโโ app/
โ โโโ src/
โ โโโ main/
โ โโโ AndroidManifest.xml
โ โโโ res/
โโโ gradle/
โโโ build.gradleโ Android Project Ready
You can now open this project in Android Studio from src-tauri/gen/android/ if you need to modify Android-specific settings. For most use cases, the default configuration works perfectly!
Step 4: Configure Rust Dependencies
Now we need to add the Rust dependencies that our application will use for HTTP requests, JSON handling, and error management. Open src-tauri/Cargo.toml and replace its content with:
1[package]2name = "tauri-react-rust-app"3version = "0.1.0"4description = "A Tauri App"5authors = ["you"]6edition = "2021"78[lib]9name = "tauri_react_rust_app_lib"10crate-type = ["staticlib", "cdylib", "rlib"]1112[build-dependencies]13tauri-build = { version = "2", features = [] }1415[dependencies]16tauri = { version = "2", features = [] }17tauri-plugin-opener = "2"18serde = { version = "1", features = ["derive"] }19serde_json = "1"20reqwest = { version = "0.11.27", default-features = false, features = [21 "json",22 "rustls-tls"23] }24chrono = { version = "0.4", features = ["serde"] }25thiserror = "1.0"Understanding the Dependencies
Let's understand what each dependency does:
| Dependency | Purpose | Why We Need It |
|---|---|---|
tauri | Core Tauri framework | Provides IPC, window management, and app structure |
tauri-plugin-opener | File/URL opener | Allows opening files and URLs from the app |
serde | Serialization framework | Converts Rust structs to/from JSON |
serde_json | JSON support | Handles JSON parsing and generation |
reqwest | HTTP client | Makes HTTP requests to our Go backend |
chrono | Date/time handling | Manages timestamps for users and tasks |
thiserror | Error handling | Creates ergonomic error types |
๐ฆ About reqwest Configuration
We're using 'rustls-tls' instead of the default 'native-tls' for better cross-platform compatibility. This ensures our app works consistently across Windows, macOS, Linux, and Android.
Step 5: Install and Configure Tailwind CSS
We'll use Tailwind CSS for styling our application. Tailwind provides utility classes that make it easy to build beautiful, responsive UIs quickly.
Install Tailwind Dependencies
npm install tailwindcss @tailwindcss/viteConfigure Tailwind
Replace the entire content of src/index.css with this single import:
@import "tailwindcss";That's it! The new Tailwind CSS v4 syntax is much simpler. Now we need to update our Vite configuration to use Tailwind.
Step 6: Configure TypeScript Path Aliases
Path aliases make our imports cleaner and more maintainable. Instead of writing '../../../components/Button', we can write '@/components/Button'.
Install Required Types
npm install -D @types/nodeUpdate tsconfig.json
Open tsconfig.json and update it with the following configuration:
1{2 "compilerOptions": {3 "target": "ES2020",4 "useDefineForClassFields": true,5 "lib": ["ES2020", "DOM", "DOM.Iterable"],6 "module": "ESNext",7 "skipLibCheck": true,89 /* Bundler mode */10 "moduleResolution": "bundler",11 "allowImportingTsExtensions": true,12 "resolveJsonModule": true,13 "isolatedModules": true,14 "noEmit": true,15 "jsx": "react-jsx",1617 /* Linting */18 "strict": true,19 "noUnusedLocals": true,20 "noUnusedParameters": true,21 "noFallthroughCasesInSwitch": true,22 "forceConsistentCasingInFileNames": true,2324 /* Path Aliases */25 "paths": {26 "@/*": ["./src/*"]27 }28 },29 "include": ["src"],30 "references": [{ "path": "./tsconfig.node.json" }]31}Update tsconfig.node.json
Now update tsconfig.node.json with these settings:
1{2 "compilerOptions": {3 "strict": true,4 "composite": true,5 "skipLibCheck": true,6 "module": "ESNext",7 "moduleResolution": "bundler",8 "allowSyntheticDefaultImports": true,9 "forceConsistentCasingInFileNames": true10 },11 "include": ["vite.config.ts"]12}๐ Important TypeScript Settings
We've added 'forceConsistentCasingInFileNames' to both configs. This ensures file imports have consistent casing across all operating systems, preventing bugs when deploying to Linux servers.
Step 7: Update Vite Configuration
Vite is our build tool and development server. We need to configure it to work with Tailwind CSS and support our path aliases.
Update vite.config.ts with the following:
1// File: vite.config.ts23import tailwindcss from "@tailwindcss/vite";4import react from "@vitejs/plugin-react";5import path from "path";6import { defineConfig } from "vite";78const host = process.env.TAURI_DEV_HOST;910// https://vite.dev/config/11export default defineConfig(async () => ({12 plugins: [react(), tailwindcss()],13 resolve: {14 alias: {15 "@": path.resolve(__dirname, "./src"),16 },17 },1819 // Vite options tailored for Tauri development and only applied in "tauri dev" or "tauri build"20 //21 // 1. prevent Vite from obscuring rust errors22 clearScreen: false,23 // 2. tauri expects a fixed port, fail if that port is not available24 server: {25 port: 1420,26 strictPort: true,27 host: host || false,28 hmr: host29 ? {30 protocol: "ws",31 host,32 port: 1421,33 }34 : undefined,35 watch: {36 // 3. tell Vite to ignore watching "src - tauri"37 ignored: ["**/src-tauri/**"],38 },39 },40}));41This configuration does three important things:
- Adds the React plugin for Fast Refresh and JSX support
- Adds the Tailwind CSS plugin for processing utility classes
- Sets up the @ alias to point to the src directory
Step 8: Initialize shadcn/ui
shadcn/ui is a collection of beautifully designed, accessible, and customizable React components built on top of Radix UI and Tailwind CSS. Unlike traditional component libraries, shadcn/ui copies components directly into your project, giving you full control.
Initialize shadcn/ui
npx shadcn@latest initYou'll be asked a few questions. Here's how to answer:
Which style would you like to use? โบ New York
Which color would you like to use as base color? โบ Neutral
Do you want to use CSS variables for colors? โบ yesInstall Required Components
Now let's install all the components we'll need for our application:
npx shadcn@latest add card button input label textarea checkbox select alert tabs badgeThis will create a components/ui directory in your src folder with all the components. Each component is fully customizable and the code is yours to modify!
src/
โโโ components/
โ โโโ ui/
โ โโโ card.tsx
โ โโโ button.tsx
โ โโโ input.tsx
โ โโโ label.tsx
โ โโโ textarea.tsx
โ โโโ checkbox.tsx
โ โโโ select.tsx
โ โโโ alert.tsx
โ โโโ tabs.tsx
โ โโโ badge.tsx
โโโ lib/
โโโ utils.ts๐จ Why shadcn/ui?
Unlike libraries like Material-UI or Ant Design, shadcn/ui components live in your codebase. You can modify them freely without worrying about breaking updates. Plus, they're built with accessibility in mind using Radix UI primitives.
Step 9: Test Your Setup
Let's verify everything is working by creating a simple test component. Update src/App.tsx with this code:
1import { Button } from "@/components/ui/button";2import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";34function App() {5 return (6 <div className="min-h-screen bg-background p-8">7 <div className="max-w-2xl mx-auto space-y-8">8 <div className="text-center space-y-2">9 <h1 className="text-4xl font-bold">Welcome to Tauri + React</h1>10 <p className="text-muted-foreground">11 Your cross-platform app is ready!12 </p>13 </div>1415 <Card>16 <CardHeader>17 <CardTitle>Setup Complete! ๐</CardTitle>18 <CardDescription>19 All dependencies are installed and configured20 </CardDescription>21 </CardHeader>22 <CardContent className="space-y-4">23 <div className="flex items-center gap-2">24 <span className="text-2xl">โ
</span>25 <span>Tauri 2.0 initialized</span>26 </div>27 <div className="flex items-center gap-2">28 <span className="text-2xl">โ
</span>29 <span>React with TypeScript configured</span>30 </div>31 <div className="flex items-center gap-2">32 <span className="text-2xl">โ
</span>33 <span>Tailwind CSS ready</span>34 </div>35 <div className="flex items-center gap-2">36 <span className="text-2xl">โ
</span>37 <span>shadcn/ui components installed</span>38 </div>39 <Button className="w-full mt-4">40 Ready to Build! ๐41 </Button>42 </CardContent>43 </Card>44 </div>45 </div>46 );47}4849export default App;Run the Development Server
Now let's start the development server:
npm run tauri devThis will compile your Rust code and start the Vite development server. After a few moments, a window should open showing your test component!
โฑ๏ธ First Build Takes Time
The first time you run 'npm run tauri dev', it will take a few minutes to compile all Rust dependencies. Subsequent builds will be much faster thanks to Rust's incremental compilation.
If you see the window with the card showing all checkmarks, congratulations! Your Tauri + React + shadcn/ui setup is working perfectly.
Final Project Structure
At this point, your project should have the following structure:
tauri-react-rust-app/
โโโ src/
โ โโโ components/
โ โ โโโ ui/ # shadcn/ui components
โ โโโ lib/
โ โ โโโ utils.ts # Utility functions
โ โโโ App.tsx # Main React component
โ โโโ App.css
โ โโโ main.tsx
โ โโโ index.css # Tailwind imports
โโโ src-tauri/
โ โโโ src/
โ โ โโโ main.rs
โ โ โโโ lib.rs
โ โโโ gen/
โ โ โโโ android/ # Android project (if initialized)
โ โโโ Cargo.toml # Updated with dependencies
โ โโโ tauri.conf.json
โ โโโ build.rs
โโโ public/
โโโ node_modules/
โโโ components.json # shadcn/ui config
โโโ package.json
โโโ tsconfig.json # Updated with path aliases
โโโ tsconfig.node.json # Updated
โโโ vite.config.ts # Updated with Tailwind
โโโ index.htmlWhat's Next?
Congratulations! You've successfully set up the foundation for a cross-platform Tauri application. You now have:
- A Tauri 2.0 project with React and TypeScript
- Android support initialized and ready
- Rust dependencies configured for HTTP requests and JSON handling
- Tailwind CSS set up for styling
- shadcn/ui components installed and working
- TypeScript path aliases configured
- A working development environment
In Part 2 of this series, we'll dive into building the Rust backend layer. We'll create:
- Type-safe data structures that mirror our API
- A robust error handling system
- An HTTP client for communicating with the Go backend
- A service layer that encapsulates all API calls
- Tauri commands that expose functionality to React
- A clean, modular Rust architecture
๐ Continue to Part 2
Ready to build the Rust backend layer? Check out Part 2: Building the Rust Backend Layer for Tauri where we'll create a type-safe bridge between React and our Go API!
Troubleshooting Common Issues
Rust Compilation Errors
If you encounter Rust compilation errors, try these steps:
# Update Rust to latest version
rustup update
# Clean build cache
cd src-tauri
cargo clean
# Try building again
cd ..
npm run tauri devPath Alias Not Working
If imports with @ are not working, make sure:
- @types/node is installed
- Both tsconfig.json and vite.config.ts have the alias configured
- You've restarted the development server after making config changes
- Your IDE has reloaded the TypeScript configuration
Android Initialization Failed
If Android initialization fails, verify:
- ANDROID_HOME environment variable is set correctly
- JAVA_HOME points to JDK 17 or higher
- Android SDK is installed through Android Studio
- You've accepted Android SDK licenses: sdkmanager --licenses
shadcn/ui Components Not Found
If you get import errors for shadcn/ui components:
# Reinstall the components
npx shadcn@latest add card button input label textarea checkbox select alert tabs badge
# Make sure components.json exists in your project root
# Restart your dev server
npm run tauri devAdditional Resources
Here are some helpful resources for learning more:
- Tauri Documentation: https://tauri.app/
- React Documentation: https://react.dev/
- Tailwind CSS Documentation: https://tailwindcss.com/
- shadcn/ui Components: https://ui.shadcn.com/
- Rust Book: https://doc.rust-lang.org/book/
- TypeScript Handbook: https://www.typescriptlang.org/docs/
You're now ready to move on to Part 2 where we'll build the Rust backend layer! Keep this project structure in mind as we add more functionality in the upcoming parts.
๐ฌ Questions or Feedback?
If you run into any issues or have questions about this setup, feel free to reach out. Happy coding! ๐