Skip to content

Backend Architecture

Relevant source files

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

Purpose and Scope

This document describes the Rust backend architecture of KanStack, including its module organization, command handlers, workspace operations, and file system management. The backend is built with Tauri 2 and provides the file I/O layer that supports the frontend's markdown-based workspace model.

For information about frontend architecture and state management, see Frontend Architecture. For details about the data structures passed between backend and frontend, see Data Model.


Module Organization

The backend code is organized into focused modules that separate command handling from pure workspace logic. After the refactor described in the tauri-backend-module-split task, main.rs now handles only application bootstrap, while domain logic lives in dedicated modules.

Sources: src-tauri/src/main.rs:1-192, TODO/cards/tauri-backend-module-split.md:1-55

Key Design Principles

PrincipleImplementation
Separation of ConcernsCommands handle Tauri integration; workspace modules contain pure logic
Path-based IdentityBoards and cards are identified by normalized filesystem paths
Atomic OperationsFile writes include rollback support for error recovery
No DatabaseAll data persists as markdown files in TODO/ directories
Minimal DependenciesOnly essential crates: Tauri, notify, serde, trash

Sources: src-tauri/Cargo.toml:1-27, TODO/cards/tauri-backend-module-split.md:36-46


Command Layer

The backend exposes 15 Tauri commands that the frontend invokes via IPC. Commands are registered in main.rs and implemented across four domain-specific modules.

Registered Commands

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

Command Reference

CommandModulePurpose
load_workspaceworkspace.rsLoad all boards and cards from a workspace root path
save_board_fileboard.rsWrite updated board markdown to TODO/todo.md
save_card_filecard.rsWrite updated card markdown to TODO/cards/*.md
save_workspace_boardsworkspace.rsBatch save multiple board files atomically
apply_workspace_snapshotworkspace.rsRestore workspace to a previous snapshot state (for undo)
create_card_in_boardcard.rsCreate a new card file in a board's cards directory
create_boardboard.rsCreate a new board with its TODO/ directory structure
rename_cardcard.rsRename a card file and update all referencing board links
rename_boardboard.rsUpdate a board's title in its frontmatter
delete_card_filecard.rsMove card file to trash
delete_boardboard.rsMove entire board TODO/ directory to trash
sync_known_board_treeworkspace.rsDiscover sub-boards and persist paths to markdown
watch_workspacewatcher.rsStart file system watcher for workspace changes
unwatch_workspacewatcher.rsStop file system watcher
load_app_config / save_app_configworkspace.rsPersist app preferences to JSON file

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


Command Implementation Pattern

All commands follow a consistent pattern enabled by the shared support module:

Sources: The pattern is described in TODO/cards/tauri-backend-module-split.md:42-44

Support Module Helpers

The backend/commands/support.rs module provides shared functionality to eliminate duplication across command handlers:

HelperPurpose
resolve_board_root()Extract board root path from any board-related file path
resolve_workspace_root()Extract workspace root path from board or card path
build_board_write()Construct a BoardWrite for TODO/todo.md
build_card_write()Construct a BoardWrite for TODO/cards/*.md
parse_local_card_slug()Extract card slug from cards/slug.md path

Sources: TODO/cards/tauri-backend-module-split.md:42-44


Workspace Operations

The backend/workspace/ modules provide the core file system and markdown operations that power the workspace model.

Path Resolution (paths.rs)

Path resolution functions normalize and validate file paths according to KanStack's TODO/ structure:

Sources: Described in module organization from TODO/cards/tauri-backend-module-split.md:40-41

Markdown Parsing (markdown.rs)

The markdown parser extracts structured data from board and card files:

FunctionPurpose
extract_frontmatter()Parse YAML frontmatter between --- delimiters
extract_settings()Parse JSON settings block from %% kanban:settings %%
parse_wikilinks()Extract [[target|label]] references from markdown
parse_headings()Identify ## columns and ### sections

The parser is used during workspace loading but lives in the backend for testing. The frontend has its own richer TypeScript parser (parseWorkspace) that produces the full KanbanParseResult.

Sources: TODO/cards/cross-workspace-boards.md:48, TODO/cards/tauri-backend-module-split.md:41

Sub-Board Discovery (discovery.rs)

The discover_sub_board_paths() function implements the manual sub-board discovery algorithm:

Discovery is triggered by the sync_known_board_tree command, which writes discovered paths into the ## Sub Boards section of TODO/todo.md.

Sources: docs/plans/2026-03-12-cross-workspace-boards-design.md:15-31, TODO/cards/cross-workspace-boards.md:42-47

Snapshot Loading (loading.rs)

The workspace loading pipeline transforms a root path into a WorkspaceSnapshot:

Each FileSnapshot contains:

  • path: Absolute file path
  • content: File content as string
  • is_board: Boolean indicating if this is todo.md

The snapshot is returned to the frontend, which parses it into structured LoadedWorkspace.

Sources: TODO/cards/tauri-backend-module-split.md:44

File Operations (fs.rs)

The file system module provides write operations with rollback support:

FunctionPurpose
apply_workspace_writes()Execute multiple writes atomically with rollback on failure
write_file()Write content to file, creating parent directories as needed
rename_with_rollback()Rename file/directory with automatic rollback on error
move_to_trash()Move file/directory to OS trash (using trash crate)

All write operations ensure parent directories exist and normalize paths before writing.

Sources: TODO/cards/tauri-backend-module-split.md:45-46, src-tauri/Cargo.toml:18


File System Watching

KanStack uses the notify crate to watch for external file changes and emit workspace-changed events to the frontend.

Watcher Architecture

Sources: src-tauri/Cargo.toml:12, command registration in src-tauri/src/main.rs:32-49

Watcher State Management

The watcher state is managed through Tauri's state management system:

  • WorkspaceWatcherState is registered in main.rs using .manage()
  • It contains an Arc<Mutex<Option<notify::Watcher>>> for thread-safe access
  • watch_workspace creates a new watcher and stores it in the state
  • unwatch_workspace removes and drops the watcher, stopping notifications
  • The watcher automatically cleans up when the state is dropped

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


The backend provides menu action event bridging between Tauri's native menu system and the frontend's action handlers.

Sources: src-tauri/src/main.rs:161-191

The build_menu() function in main.rs constructs the application menu with keyboard shortcuts:

MenuItemsAccelerators
FileOpen Folder, Close FolderCmd+O, Cmd+W
EditUndo, RedoCmd+Z, Cmd+Shift+Z
BoardNew Board, Attach Existing, Toggle Archive, Toggle Sub Boards, Delete BoardCmd+Shift+N, -, Cmd+Shift+A, -, -
ColumnNew Column, Rename Column, Delete Column-, -, -
CardNew Card, Archive Selected, Delete SelectedCmd+N, Delete, Shift+Delete

Menu events are mapped to action strings and emitted as menu-action events for the frontend to handle.

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


Data Models

The backend/models.rs module defines the data structures shared between commands and passed across the IPC boundary.

Core Types

Sources: Command usage patterns from src-tauri/src/main.rs:10-17

Type Purpose

TypePurposeSerialization
WorkspaceSnapshotComplete workspace state returned from load_workspaceJSON via serde
FileSnapshotIndividual file content and metadataJSON via serde
BoardWritePending write operation with optional renameJSON via serde
MenuActionPayloadMenu action event payloadJSON via serde
WorkspaceWatcherStateManaged state for file system watcherNot serialized

All serializable types use #[derive(Serialize, Deserialize)] from the serde crate.

Sources: src-tauri/Cargo.toml:13-14


Error Handling

Backend commands return Result<T, String> where the error string is returned to the frontend. Common error patterns:

Error SourceHandling
File I/O errorsConverted to descriptive strings with file path context
Path validation errorsEarly return with clear message about path expectations
Watcher setup errorsReturned with notify crate error details
Serialization errorsJSON/YAML parse errors returned with source location

Write operations use rollback to maintain consistency when errors occur mid-operation.

Sources: Pattern described in TODO/cards/tauri-backend-module-split.md:43


Testing Strategy

The backend includes unit tests for pure functions in the markdown parsing module. Tests validate frontmatter extraction, settings parsing, and wikilink resolution.

Command handlers are tested indirectly through frontend integration tests and manual verification during development. The modular architecture allows workspace helpers to be tested independently from Tauri command infrastructure.

Sources: TODO/cards/cross-workspace-boards.md:48, TODO/cards/tauri-backend-module-split.md:32