Development
Contribute
Development
How to set up your local development environment and contribute to Clanker Yap.
Prerequisites
System Requirements
| Tool | Version | Purpose |
|---|---|---|
| Rust | Stable | Backend compilation |
| Node.js | 16+ | Frontend and Tauri CLI |
| npm | 8+ | Package management |
| CMake | 3.10+ | C dependencies |
| Git | Any | Version control |
Linux Dependencies
sudo pacman -S --needed \
base-devel \
cmake \
webkit2gtk-4.1 \
libappindicator-gtk3 \
librsvg \
nodejs \
npm
Verification
Check your toolchain:
rustc --version # Should be 1.70+
node --version # Should be 16+
npm --version # Should be 8+
cmake --version # Should be 3.10+
Repository Setup
Clone the Repository
git clone https://github.com/your-username/clanker-yap.git
cd clanker-yap
Install Dependencies
npm install
This installs:
- Tauri CLI
- Build dependencies
Verify Setup
# Rust compilation check
cargo check --manifest-path src-tauri/Cargo.toml
# Run tests
cargo test --manifest-path src-tauri/Cargo.toml
Project Structure Overview
clanker-yap/
├── src/ # Frontend (HTML/CSS/JS)
│ ├── index.html # Main UI markup
│ ├── main.js # Frontend logic
│ ├── style.css # UI styles
│ └── vendor/ # Vendor files (tauri.js)
├── src-tauri/ # Rust backend
│ ├── src/
│ │ ├── domain/ # Core types
│ │ ├── application/ # Business logic
│ │ ├── infrastructure/ # External integrations
│ │ └── presentation/ # Tauri commands
│ ├── Cargo.toml
│ └── tauri.conf.json
├── docs/ # Documentation
├── CONTRIBUTING.md
└── README.md
Running Development Mode
Start Development Server
npm run tauri:dev
This command:
- Compiles Rust backend
- Starts Tauri dev server
- Opens the application window
- Enables hot reload for frontend
Hot Reload
Changes to frontend files (src/) are reflected immediately.
Changes to Rust code trigger recompilation automatically.
Debug Mode
For verbose logging, set the RUST_LOG environment variable:
RUST_LOG=trace npm run tauri:dev
Rust Development
Package Structure
src-tauri/src/
├── domain/ # Pure types (no I/O)
├── application/ # Use cases
├── infrastructure/ # External integrations
└── presentation/ # Tauri commands
Adding a New Feature
1. Domain Layer
If adding business logic:
// src-tauri/src/domain/my_feature.rs
/// Documentation
#[derive(Debug, Clone)]
pub struct MyFeature {
pub value: String,
}
impl MyFeature {
/// Creates a new instance with validation
pub fn new(value: String) -> Result<Self> {
if value.is_empty() {
return Err(AppError::SettingsInvalid(
"Value cannot be empty".into()
));
}
Ok(Self { value })
}
}
2. Application Layer
If adding business operations:
// src-tauri/src/application/use_cases/my_feature.rs
use crate::domain::{AppError, Result};
pub struct MyFeatureUseCase;
impl MyFeatureUseCase {
pub fn do_something(&self, input: String) -> Result<String> {
// Business logic here
Ok(input.to_uppercase())
}
}
3. Infrastructure Layer
If integrating with external services:
// src-tauri/src/infrastructure/my_service/mod.rs
pub mod service;
4. Presentation Layer
If exposing commands to frontend:
// src-tauri/src/presentation/commands/my_feature_cmds.rs
use tauri::command;
#[command]
pub fn my_command(value: String) -> Result<String, String> {
// Call use case
Ok("response".into())
}
Module Registration
Add new modules to mod.rs files:
// domain/mod.rs
pub mod my_feature;
// application/mod.rs
pub mod use_cases;
// presentation/commands/mod.rs
pub mod my_feature_cmds;
Frontend Development
HTML Structure
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Clanker Yap</title>
<link rel="stylesheet" href="style.css" />
<script src="vendor/tauri.js"></script>
</head>
<body>
<div class="app-shell">
<!-- Your UI here -->
</div>
<script src="main.js"></script>
</body>
</html>
Tauri API Usage
// Import invoke from Tauri
const { invoke } = window.__TAURI__.core;
// Call Rust command
async function getSettings() {
try {
const settings = await invoke('get_settings');
console.log(settings);
} catch (error) {
console.error('Failed:', error);
}
}
// Listen for events
window.__TAURI__.event.listen('recording-state', (event) => {
console.log('State changed:', event.payload);
});
UI Styling
Styles are in src/style.css. Uses CSS custom properties:
:root {
--color-primary: #0078d4;
--color-bg: #1a1a1a;
--font-sans: system-ui, sans-serif;
}
.app-shell {
background: var(--color-bg);
color: white;
font-family: var(--font-sans);
}
Testing
Rust Unit Tests
# Run all tests
cargo test --manifest-path src-tauri/Cargo.toml
# Run specific test
cargo test --manifest-path src-tauri/Cargo.toml transcription
# Run with output
cargo test --manifest-path src-tauri/Cargo.toml -- --nocapture
Frontend Testing
Manual testing for frontend:
npm run tauri:dev- Interact with the app
- Check console for errors
Test Structure
src-tauri/src/
└── domain/
└── transcription.rs # Tests at bottom
#[cfg(test)]
mod tests {
#[test]
fn rejects_text_longer_than_max_length() { ... }
}
Code Quality
Formatting
# Format Rust code
cargo fmt --manifest-path src-tauri/Cargo.toml
# Check formatting (CI)
cargo fmt --manifest-path src-tauri/Cargo.toml -- --check
Linting
# Clippy lints
cargo clippy --manifest-path src-tauri/Cargo.toml -- -D warnings
Type Checking
# Type check
cargo check --manifest-path src-tauri/Cargo.toml
Debugging
Rust Debugging
Logging
Use tracing for structured logging:
use tracing::{info, warn, error};
fn my_function() {
info!("Starting operation");
warn!("Something unexpected");
error!("Operation failed");
}
Environment Variables
# Enable all logging
RUST_LOG=trace npm run tauri:dev
# Enable specific module
RUST_LOG=voice_transcribe=debug npm run tauri:dev
GDB/LLDB
# Debug with GDB
rust-gdb --args cargo run --manifest-path src-tauri/Cargo.toml
# Debug with LLDB
rust-lldb --args cargo run --manifest-path src-tauri/Cargo.toml
Frontend Debugging
Console
Open DevTools (right-click → Inspect) to see console logs.
Tauri Inspector
Enable Tauri devtools in tauri.conf.json:
{
"build": {
"devtools": true
}
}
Network Debugging
Recording Issues
Check audio device permissions:
# Linux: Check ALSA
arecord -l
# Linux: Check PulseAudio
pactl list sources
# Check microphone in system settings
Paste Issues
Debug paste mode:
- Open app in foreground
- Hold hotkey, speak, release
- Watch console for errors
- Try different paste modes
Building for Local Release Testing
Current release targets:
- Linux x86_64 AppImage
Build it with:
npm run tauri:build
Output location:
src-tauri/target/release/bundle/appimage/
Contributing
See CONTRIBUTING.md for:
- Code style guidelines
- Pull request process
- Reporting issues
- Feature requests
Dependency Management
Updating Rust Dependencies
# Update Cargo.toml version
# Then update lockfile
cargo update --manifest-path src-tauri/Cargo.toml
Adding New Dependencies
-
Add to
src-tauri/Cargo.toml:[dependencies] my-new-crate = "1.0" -
Run
cargo check --manifest-path src-tauri/Cargo.toml
Frontend Dependencies
# Add npm package
npm install package-name
# Update package-lock.json
npm install
Performance Profiling
Rust Profiling
# Profile with criterion
cargo bench --manifest-path src-tauri/Cargo.toml
# Check binary size
cargo bloaty --release --manifest-path src-tauri/Cargo.toml
Memory Usage
# Check memory with massif
valgrind --tool=massif ./target/release/voice-transcribe
Common Development Tasks
Add a New Setting
-
Update
domain/settings.rs:pub struct Settings { // Existing fields... pub new_setting: String, } -
Update persistence in
infrastructure/persistence/ -
Add Tauri command in
presentation/commands/ -
Add UI in frontend
Add a New Command
- Create command handler in
presentation/commands/ - Register in
lib.rs - Call from frontend via
invoke()
Add Transcriptions
- Update
domain/transcription.rs - Update repository in
infrastructure/persistence/ - Add command for frontend access