From dev-team-kit-fv
Packages web frontends into native Android APKs and desktop apps for Windows/macOS/Linux using Tauri v2. Configures native permissions, notifications, file system, and builds.
npx claudepluginhub felvieira/claude-skills-fvThis skill uses the workspace's default tool permissions.
Skill OPCIONAL. Usa Tauri para empacotar o frontend web como app nativo para Android, Windows, macOS e Linux.
Sets up Tauri v2 for Android and iOS: initializes mobile targets, configures bundle IDs, runs dev/debug on devices/emulators.
Builds and debugs Tauri v2 desktop/mobile apps from web frontends (React, Vue, Svelte) with Rust backends, covering IPC commands, permissions, plugins, config, multi-platform builds.
Builds and maintains Tauri desktop/mobile apps with Rust backend and WebView frontend. Covers project setup, IPC commands/events, security configs, plugins, state management, and windows.
Share bugs, ideas, or general feedback.
Skill OPCIONAL. Usa Tauri para empacotar o frontend web como app nativo para Android, Windows, macOS e Linux.
Esta skill segue GLOBAL.md, policies/execution.md, policies/handoffs.md, policies/quality-gates.md, policies/token-efficiency.md, policies/stack-flexibility.md, policies/tool-safety.md e policies/evals.md.
Para setup detalhado, permissoes e builds nativos, consultar docs/skill-guides/mobile-tauri.md apenas quando necessario.
Framework: Tauri v2
Frontend: Mesmo React/Next.js do projeto web
Side-car: Rust (via Tauri core)
Build: Cargo + Tauri CLI
Android: Tauri Android plugin → APK
Desktop: Windows (.exe/.msi), macOS (.dmg), Linux (.deb/.AppImage)
npm install -D @tauri-apps/cli@latest
npx tauri init
npm install @tauri-apps/api@latest
npm install @tauri-apps/plugin-notification @tauri-apps/plugin-fs @tauri-apps/plugin-shell @tauri-apps/plugin-http
{
"$schema": "https://raw.githubusercontent.com/nicogaldamez/tauri-schema/refs/heads/main/tauri.conf.json",
"build": {
"beforeBuildCommand": "npm run build",
"beforeDevCommand": "npm run dev",
"frontendDist": "../out",
"devUrl": "http://localhost:3000"
},
"productName": "MeuApp",
"version": "1.0.0",
"identifier": "com.empresa.meuapp",
"app": {
"security": {
"csp": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' https://api.empresa.com"
},
"windows": [
{
"title": "MeuApp",
"width": 1024,
"height": 768,
"minWidth": 360,
"minHeight": 640,
"resizable": true,
"fullscreen": false
}
]
},
"bundle": {
"active": true,
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/128x128@2x.png",
"icons/icon.icns",
"icons/icon.ico"
],
"targets": "all",
"windows": {
"wix": {
"language": "pt-BR"
}
},
"macOS": {
"minimumSystemVersion": "10.15"
},
"linux": {
"deb": {
"depends": ["libwebkit2gtk-4.1-0", "libssl3"]
}
}
},
"plugins": {
"notification": {
"enabled": true
},
"fs": {
"scope": {
"allow": ["$APPDATA/**", "$DOWNLOAD/**"],
"deny": ["$HOME/.ssh/**"]
}
}
}
}
import { platform } from '@tauri-apps/plugin-os';
function isTauri(): boolean {
return typeof window !== 'undefined' && '__TAURI__' in window;
}
async function getPlatform(): Promise<'android' | 'ios' | 'windows' | 'macos' | 'linux' | 'web'> {
if (!isTauri()) return 'web';
const p = await platform();
return p as 'android' | 'ios' | 'windows' | 'macos' | 'linux';
}
import { useState, useEffect } from 'react';
interface MobileNavState {
showBackButton: boolean;
showBottomNav: boolean;
showSidebar: boolean;
safeAreaInsets: {
top: number;
bottom: number;
left: number;
right: number;
};
}
function useMobileNavigation(): MobileNavState {
const [state, setState] = useState<MobileNavState>({
showBackButton: false,
showBottomNav: false,
showSidebar: true,
safeAreaInsets: { top: 0, bottom: 0, left: 0, right: 0 },
});
useEffect(() => {
async function detect() {
const p = await getPlatform();
const isMobile = p === 'android' || p === 'ios';
setState({
showBackButton: isMobile,
showBottomNav: isMobile,
showSidebar: !isMobile,
safeAreaInsets: isMobile
? { top: 44, bottom: 34, left: 0, right: 0 }
: { top: 0, bottom: 0, left: 0, right: 0 },
});
}
detect();
}, []);
return state;
}
:root {
--safe-area-top: env(safe-area-inset-top, 0px);
--safe-area-bottom: env(safe-area-inset-bottom, 0px);
--safe-area-left: env(safe-area-inset-left, 0px);
--safe-area-right: env(safe-area-inset-right, 0px);
}
.app-container {
padding-top: var(--safe-area-top);
padding-bottom: var(--safe-area-bottom);
padding-left: var(--safe-area-left);
padding-right: var(--safe-area-right);
min-height: 100dvh;
}
.bottom-nav {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding-bottom: var(--safe-area-bottom);
background: white;
border-top: 1px solid #e5e7eb;
z-index: 50;
}
.top-header {
position: sticky;
top: 0;
padding-top: var(--safe-area-top);
background: white;
border-bottom: 1px solid #e5e7eb;
z-index: 50;
}
npx tauri dev
npx tauri build
npx tauri android build --apk
npx tauri android dev
Android Studio com SDK 33+, NDK 25+, Build Tools 33+. JAVA_HOME apontando para JDK 17.
export ANDROID_HOME="$HOME/Android/Sdk"
export NDK_HOME="$ANDROID_HOME/ndk/25.2.9519653"
export JAVA_HOME="/usr/lib/jvm/java-17-openjdk"
export PATH="$PATH:$ANDROID_HOME/platform-tools:$ANDROID_HOME/tools"
npx tauri android init
npx tauri android build --apk
O APK gerado fica em src-tauri/gen/android/app/build/outputs/apk/universal/release/.
import {
isPermissionGranted,
requestPermission,
sendNotification,
} from '@tauri-apps/plugin-notification';
async function notify(title: string, body: string): Promise<void> {
let granted = await isPermissionGranted();
if (!granted) {
const permission = await requestPermission();
granted = permission === 'granted';
}
if (!granted) return;
sendNotification({ title, body });
}
import { writeTextFile, readTextFile, BaseDirectory } from '@tauri-apps/plugin-fs';
async function saveData(filename: string, data: Record<string, unknown>): Promise<void> {
await writeTextFile(filename, JSON.stringify(data, null, 2), {
baseDir: BaseDirectory.AppData,
});
}
async function loadData<T>(filename: string): Promise<T | null> {
try {
const content = await readTextFile(filename, {
baseDir: BaseDirectory.AppData,
});
return JSON.parse(content) as T;
} catch {
return null;
}
}
Permissoes minimas configuradas (allowlist restritivo)
CSP configurado no tauri.conf.json
Icones gerados para todas as plataformas (32, 128, 256, 512, icns, ico)
Splash screen configurada para Android
Deep links configurados (se aplicavel)
Auto-update configurado para desktop (se aplicavel)
Testado em dispositivo real (Android + desktop)
Performance validada em dispositivo de baixo custo
Fallback offline implementado para features criticas
Assinatura de APK configurada para release
Comentarios no codigo so fazem sentido quando explicam contexto nao obvio, restricoes externas ou workarounds temporarios. Nomes de funcoes, variaveis e tipos devem ser autoexplicativos.