Skip to content

Main Entry Point and Menu System

Relevant source files

The following files were used as context for generating this wiki page:

This page documents the Rust backend's application entry point (main.rs) and its menu system. It covers application initialization, Tauri command registration, menu construction with keyboard shortcuts, and the mechanism for forwarding menu actions to the frontend. For information about the frontend orchestration and how menu actions are handled in Vue, see Main Application Component. For details on the individual command handlers that are registered here, see Command Handlers.

Purpose and Scope

The main.rs file serves as the entry point for the Tauri desktop application. It is responsible for:

  • Initializing the Tauri runtime and window system
  • Constructing the native application menu with keyboard shortcuts
  • Registering all Tauri command handlers for frontend-backend IPC
  • Managing workspace watcher state
  • Forwarding menu events to the frontend via the event system

This 192-line file src-tauri/src/main.rs:1-192 acts as the "glue" that connects Tauri's native platform capabilities with the application's custom backend logic and frontend UI.

Sources: src-tauri/src/main.rs:1-192

Application Initialization Flow

The application bootstrap process follows a specific sequence to ensure all components are properly initialized before the application becomes interactive.

Initialization Sequence Diagram

Sources: src-tauri/src/main.rs:19-52

Main Function Structure

The main() function src-tauri/src/main.rs:19-52 uses Tauri's builder pattern to configure the application:

StepPurposeCode Location
State ManagementInitialize shared WorkspaceWatcherState for file watchingsrc-tauri/src/main.rs:21
Dialog PluginEnable native file/folder picker dialogssrc-tauri/src/main.rs:22
Setup HookConstruct and set application menusrc-tauri/src/main.rs:23-26
Menu HandlerRegister callback for menu click eventssrc-tauri/src/main.rs:27-31
Command RegistrationRegister 15 IPC command handlerssrc-tauri/src/main.rs:32-49
RunStart the Tauri application event loopsrc-tauri/src/main.rs:50-51

Sources: src-tauri/src/main.rs:19-52

The menu system consists of three interconnected components: menu construction, event routing, and action emission. Menu items are assigned string identifiers that are mapped to action strings and forwarded to the frontend.

Sources: src-tauri/src/main.rs:27-31, src-tauri/src/main.rs:161-191

The map_menu_action() function src-tauri/src/main.rs:161-180 converts menu item IDs to action strings. This indirection allows the menu ID to differ from the action name if needed, though currently they are identical:

Menu Item IDAction StringKeyboard Shortcut
open-folderopen-folderCmd/Ctrl+O
close-folderclose-folderCmd/Ctrl+W
undo-actionundo-actionCmd/Ctrl+Z
redo-actionredo-actionCmd/Ctrl+Shift+Z
new-cardnew-cardCmd/Ctrl+N
new-boardnew-boardCmd/Ctrl+Shift+N
attach-existing-boardattach-existing-board(none)
new-columnnew-column(none)
rename-selected-columnrename-selected-column(none)
delete-selected-columndelete-selected-column(none)
toggle-archive-columntoggle-archive-columnCmd/Ctrl+Shift+A
toggle-sub-boardstoggle-sub-boards(none)
delete-current-boarddelete-current-board(none)
archive-selected-cardsarchive-selected-cardsDelete
delete-selected-cardsdelete-selected-cardsShift+Delete

The mapping function returns Option<&'static str>, allowing unrecognized menu IDs to be ignored src-tauri/src/main.rs:178.

Sources: src-tauri/src/main.rs:161-180, src-tauri/src/main.rs:68-112

The build_menu() function src-tauri/src/main.rs:54-159 constructs the native application menu using Tauri's menu builder API. The menu structure varies by platform, with macOS receiving a dedicated application menu.

Sources: src-tauri/src/main.rs:54-159

Menu items are created using MenuItemBuilder src-tauri/src/main.rs:68-112, which provides a fluent API for configuring each item:

MenuItemBuilder::with_id(id, label)
    .accelerator(shortcut)  // Optional
    .build(app)?

For example, the "New Card" menu item src-tauri/src/main.rs:102-104:

MenuItemBuilder::with_id("new-card", "New Card")
    .accelerator("CmdOrCtrl+N")
    .build(app)?

The CmdOrCtrl prefix ensures cross-platform compatibility: Cmd on macOS, Ctrl on Windows/Linux.

Sources: src-tauri/src/main.rs:68-112

Platform-Specific Menu Construction

The menu construction logic uses conditional compilation to handle platform differences:

macOS-specific elements src-tauri/src/main.rs:56-67, src-tauri/src/main.rs:114-117:

  • PredefinedMenuItem::about() creates a standard "About" menu item
  • AboutMetadataBuilder populates it with app name, version, and icon
  • The app menu is added to the menu bar src-tauri/src/main.rs:149-150

All platforms src-tauri/src/main.rs:118-158:

  • File, Edit, Board, Column, and Card menus are created using SubmenuBuilder
  • Separators divide related menu items using .separator()
  • Final menu is assembled using MenuBuilder chain

Sources: src-tauri/src/main.rs:54-159

When a user clicks a menu item or presses a keyboard shortcut, Tauri invokes the callback registered via on_menu_event() src-tauri/src/main.rs:27-31. This callback orchestrates the flow from native menu event to frontend notification.

Sources: src-tauri/src/main.rs:27-31

Event Emission

The emit_menu_action() function src-tauri/src/main.rs:182-191 uses Tauri's event system to notify the frontend:

  1. Constructs a MenuActionPayload with the action string src-tauri/src/main.rs:186-188
  2. Calls app_handle.emit() with event name MENU_ACTION_EVENT src-tauri/src/main.rs:184-189
  3. Returns Result<(), String> to handle potential emission errors

The event name MENU_ACTION_EVENT is defined in backend/models.rs (imported at src-tauri/src/main.rs:17) and used by the frontend to listen for menu actions.

Sources: src-tauri/src/main.rs:182-191, src-tauri/src/main.rs:16-17

Command Handler Registration

The invoke_handler macro src-tauri/src/main.rs:32-49 registers 15 Tauri command handlers that the frontend can invoke via IPC. These commands provide the backend API for all workspace, board, and card operations.

Registered Commands by Category

CategoryCommandsModule
Workspaceload_workspace
save_workspace_boards
apply_workspace_snapshot
sync_known_board_tree
workspace.rs
Cardsave_card_file
create_card_in_board
rename_card
delete_card_file
card.rs
Boardsave_board_file
create_board
rename_board
delete_board
board.rs
Watcherwatch_workspace
unwatch_workspace
watcher.rs
Configload_app_config
save_app_config
workspace.rs

All command functions are imported from backend::commands module src-tauri/src/main.rs:10-15.

Sources: src-tauri/src/main.rs:10-15, src-tauri/src/main.rs:32-49

Command Invocation Pattern

Commands are invoked from the frontend using Tauri's invoke() API:

typescript
// Frontend code example
const result = await invoke('load_workspace', { workspacePath });

The tauri::generate_handler! macro src-tauri/src/main.rs:32 generates the routing code that:

  1. Deserializes command arguments from the frontend
  2. Calls the appropriate Rust function
  3. Serializes the return value back to the frontend
  4. Handles errors and converts them to frontend-compatible formats

Sources: src-tauri/src/main.rs:32-49

State Management

The application manages a single piece of shared state: WorkspaceWatcherState src-tauri/src/main.rs:21. This state is initialized using Tauri's manage() method, which makes it available to all command handlers.

WorkspaceWatcherState Usage

The WorkspaceWatcherState type is defined in backend/models.rs src-tauri/src/main.rs:16 and provides thread-safe access to the file system watcher. For details on how the watcher operates, see File System Watching.

Sources: src-tauri/src/main.rs:21, src-tauri/src/main.rs:16

Configuration Files

The Tauri configuration file src-tauri/tauri.conf.json:1-36 defines application metadata and window properties:

SettingValuePurpose
productName"KanStack"Application display name
version"0.6.0"Current version number
identifier"com.kanstack.app"Bundle identifier
window.width1440Initial window width
window.height920Initial window height
window.maximizedtrueStart maximized
window.title""Empty title (set dynamically)
beforeDevCommand"npm run dev"Dev server startup command
beforeBuildCommand"npm run build"Production build command
devUrl"http://localhost:1420"Dev server URL
frontendDist"../dist"Production build output directory

The window title is left empty src-tauri/tauri.conf.json:16 because it is set dynamically by the frontend based on the current workspace and board.

Sources: src-tauri/tauri.conf.json:1-36

Bootstrap Summary

The complete application bootstrap process can be summarized as:

  1. State Initialization: Create WorkspaceWatcherState for file watching
  2. Plugin Setup: Initialize dialog plugin for native file pickers
  3. Menu Construction: Build platform-appropriate menu with shortcuts
  4. Menu Routing: Register event handler to forward menu actions to frontend
  5. Command Registration: Register 15 IPC command handlers
  6. Event Loop: Start Tauri runtime and display window

This architecture separates concerns cleanly: the menu system handles user actions in native UI, the command system handles programmatic operations from the frontend, and the event system bridges the two layers bidirectionally.

Sources: src-tauri/src/main.rs:1-192, src-tauri/tauri.conf.json:1-36