Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Development Setup and Guide

This comprehensive guide covers everything you need to know about developing Mimir, from initial setup to advanced development workflows.

Table of Contents

  1. Environment Setup
  2. Building and Running
  3. Project Architecture
  4. Development Workflows
  5. Testing Strategy
  6. Debugging Techniques
  7. Database Management
  8. Frontend Development
  9. Tauri-Specific Considerations
  10. Common Tasks

Environment Setup

System Requirements

  • macOS: 10.15 (Catalina) or later
  • Windows: Windows 10 or later
  • Linux: Any modern distribution with glibc 2.31+

Required Tools

Rust Toolchain

# Install rustup (Rust version manager)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Verify installation
rustc --version
cargo --version

Node.js and npm

# macOS (via Homebrew)
brew install node

# Windows (via installer)
# Download from https://nodejs.org

# Linux (via package manager)
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs

# Verify installation
node --version  # Should be v18 or higher
npm --version

Platform-Specific Dependencies

macOS Setup

# Install Xcode Command Line Tools
xcode-select --install

# Install Homebrew (if not already installed)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# Optional: Install additional development tools
brew install git gh

Linux Setup (Ubuntu/Debian)

# Update package lists
sudo apt-get update

# Install required dependencies
sudo apt-get install -y \
  libwebkit2gtk-4.1-dev \
  build-essential \
  curl \
  wget \
  file \
  libssl-dev \
  libgtk-3-dev \
  libayatana-appindicator3-dev \
  librsvg2-dev \
  patchelf

# Optional: Install git and gh
sudo apt-get install -y git gh

Linux Setup (Fedora)

sudo dnf install \
  webkit2gtk4.1-devel \
  openssl-devel \
  curl \
  wget \
  file \
  libappindicator-gtk3-devel \
  librsvg2-devel \
  patchelf

sudo dnf groupinstall "C Development Tools and Libraries"

Windows Setup

  1. Install Visual Studio Build Tools
  2. Install Git for Windows
  3. Install Node.js
  4. Install Rust via rustup-init.exe

Optional Development Tools

# Tauri CLI (faster startup for dev mode)
cargo install tauri-cli

# Angreal (test runner)
pip install 'angreal>=2'

# Diesel CLI (database migrations)
cargo install diesel_cli --no-default-features --features sqlite

# GitHub CLI (for PR management)
brew install gh  # macOS
# or download from https://cli.github.com/

IDE Setup

Install these extensions:

  • rust-analyzer - Rust language support
  • Tauri - Tauri development tools
  • Volar - Vue 3 language support
  • ESLint - JavaScript/TypeScript linting
  • Error Lens - Inline error messages

Settings:

{
  "rust-analyzer.checkOnSave.command": "clippy",
  "editor.formatOnSave": true,
  "[rust]": {
    "editor.defaultFormatter": "rust-lang.rust-analyzer"
  },
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[vue]": {
    "editor.defaultFormatter": "Vue.volar"
  }
}

IntelliJ IDEA / CLion

  • Install Rust plugin
  • Install Vue.js plugin
  • Enable Tauri support

Building and Running

Initial Build

# Clone repository
git clone https://github.com/mimir/mimir.git
cd mimir

# Build Rust workspace
cargo build

# Install frontend dependencies
cd crates/mimir/frontend
npm install
cd ../../..

Development Mode

# Run with hot reload (from project root)
cd crates/mimir
cargo tauri dev

# Or using installed tauri-cli
cd crates/mimir
tauri dev

This starts:

  • Vite dev server for frontend (hot reload)
  • Rust backend in debug mode
  • Application window with DevTools available

Production Build

# Build optimized release
cd crates/mimir
cargo tauri build

# Output locations:
# macOS: target/release/bundle/dmg/
# Windows: target/release/bundle/msi/
# Linux: target/release/bundle/deb/ and target/release/bundle/appimage/

Project Architecture

Workspace Structure

mimir/
├── Cargo.toml                 # Workspace configuration
├── crates/
│   ├── mimir/             # Main application
│   ├── mimir-core/        # Business logic
│   ├── mimir-mcp/         # MCP server for Claude Code
│   └── mimir-print/       # PDF generation
├── docs/                      # Documentation
├── data/                      # D&D reference data
└── .metis/                   # Project management

Architecture Layers

Frontend Layer (Vue 3 + TypeScript)

  • Views: Page-level components
  • Components: Reusable UI components
  • Stores: Pinia state management
  • Services: API wrappers for Tauri commands

Application Layer (Tauri + Rust)

  • Commands: IPC handlers
  • Services: Application-level business logic
  • State: Application state management

Domain Layer (mimir-core)

  • Models: Domain entities
  • Services: Business logic
  • DAL: Data access layer
  • Migrations: Database schema

Infrastructure Layer

  • Database: SQLite with Diesel ORM
  • LLM: Ollama integration
  • File System: Campaign data storage

Data Flow

User Interaction
      ↓
Vue Component
      ↓
Pinia Store / API Service
      ↓
Tauri Command (IPC)
      ↓
Command Handler
      ↓
Core Service
      ↓
Repository (DAL)
      ↓
Database

Development Workflows

Feature Development

  1. Create Feature Branch
git checkout -b feature/my-feature
  1. Implement Feature
  • Add backend logic in mimir-core
  • Add Tauri command in mimir/src/commands
  • Add frontend UI in mimir/frontend/src
  1. Test Locally
cargo test --workspace
cd crates/mimir/frontend && npm test
  1. Commit and Push
git add .
git commit -m "Add feature description"
git push origin feature/my-feature

Bug Fix Workflow

  1. Reproduce the Bug
  • Create a failing test
  • Document reproduction steps
  1. Fix the Issue
  • Implement fix
  • Verify test passes
  1. Test Edge Cases
  • Add additional tests
  • Manual testing
  1. Submit PR

Adding a New Page

  1. Create Vue Component
# In crates/mimir/frontend/src/views/
touch MyNewView.vue
  1. Add Route
// In crates/mimir/frontend/src/app/router.ts
{
  path: '/my-new-page',
  name: 'MyNewPage',
  component: () => import('@/views/MyNewView.vue')
}
  1. Add Navigation
<!-- In layout component -->
<router-link to="/my-new-page">My New Page</router-link>

Adding a New Tauri Command

  1. Create Command Function
#![allow(unused)]
fn main() {
// In crates/mimir/src/commands/my_commands.rs
#[tauri::command]
pub async fn my_new_command(
    db_service: State<'_, Arc<DatabaseService>>,
    param: String,
) -> Result<String, String> {
    let mut conn = db_service.get_connection()
        .map_err(|e| format!("Database error: {}", e))?;

    // Business logic here
    Ok(format!("Processed: {}", param))
}
}
  1. Register Command
#![allow(unused)]
fn main() {
// In crates/mimir/src/main.rs
.invoke_handler(tauri::generate_handler![
    commands::my_new_command,
    // ... other commands
])
}
  1. Call from Frontend
// In frontend service
import { invoke } from '@tauri-apps/api/core';

export async function myNewCommand(param: string): Promise<string> {
  return await invoke<string>('my_new_command', { param });
}

Testing Strategy

Rust Testing

Unit Tests

#![allow(unused)]
fn main() {
// In same file as implementation
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_feature() {
        let result = my_function();
        assert_eq!(result, expected);
    }
}
}

Integration Tests

#![allow(unused)]
fn main() {
// In tests/integration_test.rs
use mimir_dm_core::*;

#[test]
fn test_database_workflow() {
    let mut conn = establish_connection(":memory:").unwrap();
    run_migrations(&mut conn).unwrap();

    // Test full workflow
}
}

Running Rust Tests

# All tests
cargo test --workspace

# Specific crate
cargo test -p mimir-core

# Specific test
cargo test test_campaign_creation

# With output
cargo test -- --nocapture

# Unit tests only (via angreal)
angreal test unit

Frontend Testing

Component Tests

// In crates/mimir/frontend/src/components/__tests__/
import { describe, it, expect } from 'vitest';
import { mount } from '@vue/test-utils';
import MyComponent from '../MyComponent.vue';

describe('MyComponent', () => {
  it('renders correctly', () => {
    const wrapper = mount(MyComponent, {
      props: { title: 'Test' }
    });
    expect(wrapper.text()).toContain('Test');
  });
});

Running Frontend Tests

cd crates/mimir/frontend

# Run tests
npm test

# Watch mode
npm test -- --watch

# Coverage
npm run test:coverage

# UI mode
npm run test:ui

Debugging Techniques

Rust Debugging

#![allow(unused)]
fn main() {
use tracing::{info, debug, warn, error};

debug!("Variable value: {:?}", my_var);
info!("Operation started");
warn!("Unusual condition: {}", condition);
error!("Operation failed: {}", err);
}

VS Code Debugging

  1. Install CodeLLDB extension
  2. Add .vscode/launch.json:
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "lldb",
      "request": "launch",
      "name": "Debug Tauri",
      "cargo": {
        "args": ["build", "--manifest-path=crates/mimir/Cargo.toml"]
      },
      "cwd": "${workspaceFolder}"
    }
  ]
}

Frontend Debugging

Browser DevTools

  • Right-click in app → “Inspect Element”
  • Console tab for logs
  • Network tab for Tauri commands
  • Vue DevTools for component inspection

Console Logging

console.log('Debug:', variable);
console.warn('Warning:', condition);
console.error('Error:', error);

Database Debugging

# Open development database (macOS)
sqlite3 ~/Library/Application\ Support/com.mimir.app/dev/mimir.db

# Common commands
.tables                # List tables
.schema campaigns      # Show table structure
SELECT * FROM campaigns;  # Query data
.quit                  # Exit

Database Management

Migrations

Creating a Migration

cd crates/mimir-core
diesel migration generate add_new_feature

# Edit migrations/YYYY-MM-DD-HHMMSS_add_new_feature/up.sql
# Edit migrations/YYYY-MM-DD-HHMMSS_add_new_feature/down.sql

Running Migrations

# Apply migrations
diesel migration run

# Rollback last migration
diesel migration revert

# Test migration cycle
diesel migration redo

Development Database Location

  • macOS: ~/Library/Application Support/com.mimir.app/dev/mimir.db
  • Linux: ~/.local/share/com.mimir.app/dev/mimir.db
  • Windows: %APPDATA%\com.mimir.app/dev\mimir.db

Resetting Development Database

# macOS
rm -rf ~/Library/Application\ Support/com.mimir.app/dev/

# Linux
rm -rf ~/.local/share/com.mimir.app/dev/

# Windows
# Delete folder: %APPDATA%\com.mimir.app/dev\

# Restart app to recreate
cargo tauri dev

Frontend Development

Hot Reload

Changes to Vue components, TypeScript, and CSS hot reload automatically:

  • Save file
  • Browser refreshes automatically
  • State may reset depending on change

State Management (Pinia)

// Define store
import { defineStore } from 'pinia';

export const useCampaignStore = defineStore('campaign', () => {
  const campaigns = ref<Campaign[]>([]);

  async function loadCampaigns() {
    campaigns.value = await invoke('list_campaigns');
  }

  return { campaigns, loadCampaigns };
});

// Use in component
const campaignStore = useCampaignStore();
await campaignStore.loadCampaigns();

Calling Tauri Commands

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

// Basic invocation
const result = await invoke<string>('command_name', { param: value });

// With error handling
try {
  const data = await invoke<Campaign>('get_campaign', { id: campaignId });
} catch (error) {
  console.error('Failed to get campaign:', error);
}

Tauri-Specific Considerations

IPC Communication

Commands run in separate thread from UI:

  • Always async
  • Data must be serializable
  • Large data may have performance impact

File System Access

#![allow(unused)]
fn main() {
// Use tauri::api::path for cross-platform paths
use tauri::api::path::{app_data_dir, app_config_dir};

let data_dir = app_data_dir(&config).unwrap();
}

Window Management

import { getCurrent } from '@tauri-apps/api/window';

const appWindow = getCurrent();
await appWindow.setTitle('New Title');
await appWindow.maximize();

Common Tasks

Updating Dependencies

# Rust dependencies
cargo update

# Frontend dependencies
cd crates/mimir/frontend
npm update

Formatting Code

# Rust
cargo fmt

# TypeScript/Vue
cd crates/mimir/frontend
npm run lint

Running Clippy

cargo clippy --all-targets --all-features

# Fix auto-fixable issues
cargo clippy --fix

Type Checking Frontend

cd crates/mimir/frontend
npm run type-check

Performance Optimization

Profiling Rust Code

cargo build --release --profile=profiling
# Use profiling tools like flamegraph or perf

Frontend Performance

  • Use Vue DevTools performance tab
  • Check bundle size: npm run build -- --analyze
  • Lazy load routes and heavy components

Additional Resources

Getting Help

  • Check CONTRIBUTING.md for contribution guidelines
  • Search GitHub Issues
  • Review crate READMEs for detailed architecture info
  • Ask questions in pull request comments