Skip to main content

Available Commands

Development

pnpm dev
# Starts Vite at http://localhost:5173
# Hot module replacement enabled
# Tauri commands will NOT work

Type Checking

pnpm build
# Runs: tsc && vite build
# Checks types + builds frontend

Linting & Formatting

pnpm check
# Runs Biome lint + format check
# Exits with error if issues found

Testing

pnpm test
# Runs Vitest test suite

Production Build

Build Desktop App

pnpm tauri build
This command:
1

TypeScript type check

Runs tsc to verify frontend types
2

Vite production build

Bundles frontend to src-tauri/target/release/bundle/
  • Minifies JavaScript/CSS
  • Optimizes images
  • Generates source maps (optional)
3

Rust release build

Compiles Rust with optimizations:
cargo build --release
  • Full optimizations (-O3 equivalent)
  • No debug symbols (smaller binary)
  • Takes ~2-5 minutes
4

Create platform bundles

Generates installers for current platform

Output Artifacts

src-tauri/target/release/bundle/
├── dmg/
│   └── Glyph_0.1.10_aarch64.dmg       # Installer
├── macos/
│   └── Glyph.app                      # Application bundle
└── updater/
    └── Glyph_0.1.10_aarch64.app.tar.gz # Auto-updater
Separate builds needed for x86_64 (Intel) and aarch64 (Apple Silicon)

Pre-push Checklist

Before pushing to remote, run:
pnpm check && pnpm build && cd src-tauri && cargo check
This verifies:
  • ✅ Code is formatted (Biome)
  • ✅ No linting errors (Biome)
  • ✅ TypeScript compiles
  • ✅ Rust compiles
Add this as a Git pre-push hook:
.git/hooks/pre-push
#!/bin/sh
pnpm check && pnpm build && cd src-tauri && cargo check
Make executable:
chmod +x .git/hooks/pre-push

Build Optimization

Rust Release Profile

Configured in src-tauri/Cargo.toml:
Cargo.toml
[profile.release]
opt-level = 3           # Maximum optimization
lto = true              # Link-time optimization
codegen-units = 1       # Single codegen unit (slower build, faster runtime)
strip = true            # Remove debug symbols
panic = 'abort'         # Smaller binary (no unwinding)

Vite Build Options

Configured in vite.config.ts:
vite.config.ts
export default defineConfig({
  build: {
    target: 'esnext',
    minify: 'esbuild',     // Fast minification
    sourcemap: false,      // Disable for smaller bundle
    rollupOptions: {
      output: {
        manualChunks: {    // Code splitting
          vendor: ['react', 'react-dom'],
          editor: ['@tiptap/react', '@tiptap/starter-kit']
        }
      }
    }
  }
});

Platform-Specific Builds

macOS: Universal Binary

Build for both Intel and Apple Silicon:
# Build x86_64 (Intel)
rustup target add x86_64-apple-darwin
pnpm tauri build -- --target x86_64-apple-darwin

# Build aarch64 (Apple Silicon)
rustup target add aarch64-apple-darwin
pnpm tauri build -- --target aarch64-apple-darwin

# Combine into universal binary
lipo -create \
  src-tauri/target/x86_64-apple-darwin/release/glyph \
  src-tauri/target/aarch64-apple-darwin/release/glyph \
  -output glyph-universal

Windows: 32-bit and 64-bit

# 64-bit (default)
pnpm tauri build

# 32-bit
rustup target add i686-pc-windows-msvc
pnpm tauri build -- --target i686-pc-windows-msvc

Linux: Multiple Distros

# Debian/Ubuntu (.deb)
pnpm tauri build -- --bundles deb

# AppImage (universal)
pnpm tauri build -- --bundles appimage

# Both
pnpm tauri build -- --bundles deb,appimage

CI/CD Pipeline

GitHub Actions Example

.github/workflows/build.yml
name: Build

on:
  push:
    branches: [main]
  pull_request:

jobs:
  typecheck:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: pnpm/action-setup@v2
        with:
          version: 10.28.2
      - uses: actions/setup-node@v3
        with:
          node-version: 18
          cache: pnpm
      - run: pnpm install
      - run: pnpm check
      - run: pnpm build
  
  build-macos:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v3
      - uses: pnpm/action-setup@v2
      - uses: actions/setup-node@v3
      - uses: dtolnay/rust-toolchain@stable
      - run: pnpm install
      - run: pnpm tauri build
      - uses: actions/upload-artifact@v3
        with:
          name: macos-dmg
          path: src-tauri/target/release/bundle/dmg/*.dmg

Versioning

Version is stored in two places and must match:
package.json
{
  "version": "0.1.10"
}
src-tauri/Cargo.toml
[package]
version = "0.1.10"
If versions don’t match, build will fail. Use a script to sync versions:
scripts/bump-version.sh
#!/bin/bash
VERSION=$1
jq ".version = \"$VERSION\"" package.json > package.json.tmp
mv package.json.tmp package.json
sed -i '' "s/version = .*/version = \"$VERSION\"/" src-tauri/Cargo.toml
Usage: ./scripts/bump-version.sh 0.1.11

Bundle Size Analysis

Frontend Bundle

pnpm build
# Check output in terminal:
# dist/assets/index-a1b2c3.js   245.67 kB

Rust Binary Size

cd src-tauri
cargo build --release
ls -lh target/release/glyph
# Example: 12M (macOS), 8M (Linux), 10M (Windows)

Reduce Binary Size

  1. Strip symbols (enabled by default in release profile)
  2. Enable LTO (enabled by default)
  3. Use wee_alloc (minimal allocator):
    Cargo.toml
    [dependencies]
    wee_alloc = "0.4"
    

Debug Builds

For debugging production issues:
# Build with debug symbols
pnpm tauri build -- --debug

# Or modify Cargo.toml temporarily:
[profile.release]
strip = false
debug = true

Next Steps

Testing

Write and run tests

Architecture

Understand the codebase