adding-tauri-splashscreen

Tauri Splashscreen Implementation

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "adding-tauri-splashscreen" with this command: npx skills add dchuk/claude-code-tauri-skills/dchuk-claude-code-tauri-skills-adding-tauri-splashscreen

Tauri Splashscreen Implementation

This skill covers implementing splash screens in Tauri v2 applications. A splash screen displays during application startup while the main window loads and initializes.

Overview

The splash screen pattern involves:

  • Showing a splash window immediately on launch

  • Hiding the main window until ready

  • Performing initialization tasks (frontend and backend)

  • Closing splash and showing main window when complete

Configuration

Window Configuration

Configure both windows in tauri.conf.json :

{ "app": { "windows": [ { "label": "main", "title": "My Application", "width": 1200, "height": 800, "visible": false }, { "label": "splashscreen", "title": "Loading", "url": "splashscreen.html", "width": 400, "height": 300, "center": true, "resizable": false, "decorations": false, "transparent": true, "alwaysOnTop": true } ] } }

Key settings:

  • "visible": false on main window - hides it until ready

  • "url": "splashscreen.html"

  • points to splash screen HTML

  • "decorations": false

  • removes window chrome for cleaner look

  • "transparent": true

  • enables transparent backgrounds

  • "alwaysOnTop": true

  • keeps splash visible during loading

Splash Screen HTML

Create splashscreen.html in your frontend source directory (e.g., src/ or public/ ):

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Loading</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; }

html, body {
  height: 100%;
  overflow: hidden;
  background: transparent;
}

.splash-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100vh;
  background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
  border-radius: 12px;
  color: white;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

.logo {
  width: 80px;
  height: 80px;
  margin-bottom: 24px;
}

.app-name {
  font-size: 24px;
  font-weight: 600;
  margin-bottom: 16px;
}

.loading-spinner {
  width: 40px;
  height: 40px;
  border: 3px solid rgba(255, 255, 255, 0.3);
  border-top-color: #4f46e5;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

.loading-text {
  margin-top: 16px;
  font-size: 14px;
  color: rgba(255, 255, 255, 0.7);
}

</style> </head> <body> <div class="splash-container"> <!-- Replace with your logo --> <svg class="logo" viewBox="0 0 100 100" fill="none"> <circle cx="50" cy="50" r="45" stroke="#4f46e5" stroke-width="4"/> <path d="M30 50 L45 65 L70 35" stroke="#4f46e5" stroke-width="4" fill="none"/> </svg> <div class="app-name">My Application</div> <div class="loading-spinner"></div> <div class="loading-text">Loading...</div> </div> </body> </html>

Frontend Setup

TypeScript/JavaScript Implementation

In your main entry file (e.g., src/main.ts ):

import { invoke } from '@tauri-apps/api/core';

// Helper function for delays function sleep(seconds: number): Promise<void> { return new Promise(resolve => setTimeout(resolve, seconds * 1000)); }

// Frontend initialization async function initializeFrontend(): Promise<void> { // Perform frontend setup tasks here: // - Load configuration // - Initialize state management // - Set up routing // - Preload critical assets

// Example: simulate initialization time await sleep(1);

// Notify backend that frontend is ready await invoke('set_complete', { task: 'frontend' }); }

// Start initialization when DOM is ready document.addEventListener('DOMContentLoaded', () => { initializeFrontend().catch(console.error); });

Alternative: Using Window Events

import { invoke } from '@tauri-apps/api/core'; import { getCurrentWindow } from '@tauri-apps/api/window';

async function initializeFrontend(): Promise<void> { // Your initialization logic const config = await loadConfig(); await setupRouter(); await preloadAssets();

// Signal completion await invoke('set_complete', { task: 'frontend' }); }

// Wait for window to be fully ready getCurrentWindow().once('tauri://created', () => { initializeFrontend(); });

Backend Setup

Add Tokio Dependency

cargo add tokio --features time

Rust Implementation

In src-tauri/src/lib.rs :

use std::sync::Mutex; use tauri::{AppHandle, Manager, State};

// Track initialization state struct SetupState { frontend_task: bool, backend_task: bool, }

impl Default for SetupState { fn default() -> Self { Self { frontend_task: false, backend_task: false, } } }

// Command to mark tasks complete #[tauri::command] async fn set_complete( app: AppHandle, state: State<'_, Mutex<SetupState>>, task: String, ) -> Result<(), String> { let mut state = state.lock().map_err(|e| e.to_string())?;

match task.as_str() {
    "frontend" => state.frontend_task = true,
    "backend" => state.backend_task = true,
    _ => return Err(format!("Unknown task: {}", task)),
}

// Check if all tasks are complete
if state.frontend_task &#x26;&#x26; state.backend_task {
    // Close splash and show main window
    if let Some(splash) = app.get_webview_window("splashscreen") {
        splash.close().map_err(|e| e.to_string())?;
    }

    if let Some(main) = app.get_webview_window("main") {
        main.show().map_err(|e| e.to_string())?;
        main.set_focus().map_err(|e| e.to_string())?;
    }
}

Ok(())

}

// Backend initialization async fn setup_backend(app: AppHandle) { // IMPORTANT: Use tokio::time::sleep, NOT std::thread::sleep // std::thread::sleep blocks the entire async runtime

// Perform backend initialization:
// - Database connections
// - Load configuration
// - Initialize services

// Example: simulate work
tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;

// Mark backend as complete
if let Some(state) = app.try_state::&#x3C;Mutex&#x3C;SetupState>>() {
    let _ = set_complete(
        app.clone(),
        state,
        "backend".to_string(),
    ).await;
}

}

#[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() .manage(Mutex::new(SetupState::default())) .invoke_handler(tauri::generate_handler![set_complete]) .setup(|app| { let handle = app.handle().clone();

        // Spawn backend initialization
        tauri::async_runtime::spawn(async move {
            setup_backend(handle).await;
        });

        Ok(())
    })
    .run(tauri::generate_context!())
    .expect("error while running tauri application");

}

Simple Implementation

For simpler cases where you only need to wait for the frontend:

Configuration

{ "app": { "windows": [ { "label": "main", "visible": false }, { "label": "splashscreen", "url": "splashscreen.html", "width": 400, "height": 300, "decorations": false } ] } }

Frontend

import { invoke } from '@tauri-apps/api/core';

async function init() { // Initialize your app await setupApp();

// Close splash, show main await invoke('close_splashscreen'); }

document.addEventListener('DOMContentLoaded', init);

Backend

use tauri::{AppHandle, Manager};

#[tauri::command] async fn close_splashscreen(app: AppHandle) -> Result<(), String> { if let Some(splash) = app.get_webview_window("splashscreen") { splash.close().map_err(|e| e.to_string())?; }

if let Some(main) = app.get_webview_window("main") {
    main.show().map_err(|e| e.to_string())?;
    main.set_focus().map_err(|e| e.to_string())?;
}

Ok(())

}

#[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() .invoke_handler(tauri::generate_handler![close_splashscreen]) .run(tauri::generate_context!()) .expect("error while running tauri application"); }

Styling Variations

Minimal Splash

<style> .splash-container { display: flex; align-items: center; justify-content: center; height: 100vh; background: #ffffff; }

.logo { width: 120px; animation: pulse 2s ease-in-out infinite; }

@keyframes pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.7; transform: scale(0.95); } } </style>

Progress Bar Splash

<style> .progress-container { width: 200px; height: 4px; background: rgba(255, 255, 255, 0.2); border-radius: 2px; overflow: hidden; margin-top: 20px; }

.progress-bar { height: 100%; background: #4f46e5; animation: progress 2s ease-in-out infinite; }

@keyframes progress { 0% { width: 0%; } 50% { width: 70%; } 100% { width: 100%; } } </style>

<div class="progress-container"> <div class="progress-bar"></div> </div>

Dark Theme with Glow

<style> .splash-container { background: #0a0a0a; color: #ffffff; }

.logo { filter: drop-shadow(0 0 20px rgba(79, 70, 229, 0.5)); }

.app-name { text-shadow: 0 0 20px rgba(79, 70, 229, 0.5); } </style>

Important Notes

Async Sleep: Always use tokio::time::sleep in async Rust code, never std::thread::sleep . The latter blocks the entire runtime.

Window Labels: Ensure window labels in code match those in tauri.conf.json .

Error Handling: The splash screen should handle errors gracefully. If initialization fails, show the main window anyway with an error state.

Timing: Keep splash screen visible long enough for branding but not so long it frustrates users. Aim for 1-3 seconds minimum.

Transparent Windows: When using transparent: true , ensure your HTML has background: transparent on html and body elements.

Mobile Considerations: On mobile platforms, splash screens work differently. Consider using platform-native splash screens for iOS and Android.

Troubleshooting

Splash screen doesn't appear:

  • Verify the URL path is correct in tauri.conf.json

  • Check that the HTML file exists in the correct location

Main window shows too early:

  • Ensure visible: false is set on the main window

  • Verify the set_complete command is being called correctly

Transparent background not working:

  • Set transparent: true in window config

  • Set background: transparent in CSS for html and body

  • On some platforms, you may need decorations: false

Window position issues:

  • Use center: true for centered splash screens

  • Or specify explicit x and y coordinates

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

integrating-tauri-js-frontends

No summary provided by upstream source.

Repository SourceNeeds Review
-138
dchuk
Coding

configuring-tauri-permissions

No summary provided by upstream source.

Repository SourceNeeds Review
-116
dchuk
Coding

understanding-tauri-architecture

No summary provided by upstream source.

Repository SourceNeeds Review