Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions .agents/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,18 @@
## Safety & Process
- **Pull Requests Required**: Never push new features directly to the `main` branch. Always create a new branch and push your changes as a Pull Request (PR) for review.
- **Pre-PR Checks**: Run `npm run lint` and `npx vitest run` before opening any PR — don't open a PR with failing checks.
- **Preload/Types Contract**: Never modify `electron/preload.ts` or `src/types.d.ts` in isolation — these two files are a contract and must always be updated together.
- **Secrets Management**: Never store secrets, API keys, or credentials in code — API keys live in Electron's `safeStorage` only.
- **Preload/Types Contract**: IPC contract: `src/types.d.ts` `src/api.ts` via `invoke()`. Never modify these files in isolation.
- **Secrets Management**: Never add secrets to Rust source — use keyring crate via `commands/keychain.rs`.

## Code Conventions
- **Zustand Slices**: Zustand stores must use slice subscriptions (`state => state.x`), never subscribe to the whole store.
- **IPC Listeners**: All `ipcRenderer.on` registrations in `preload.ts` must return an unsubscribe function.
- **Lazy Loading**: Dynamic `import()` for any dependency over 1MB unpacked — check with `npx cost-of-modules` before adding new deps.
- **Timers**: No `setInterval` in renderer or main process — use targeted `setTimeout` chains or event-driven patterns.

## Electron-specific
- **Security Context**: `contextIsolation: true` and `nodeIntegration: false` are non-negotiable — never change these.
## Tauri & Rust
- **Security Context**: Follow Tauri's strict security model. Do not enable dangerous IPC scopes unless absolutely necessary.
- **IPC Types**: All new IPC channels must be declared in `src/types.d.ts` with proper types before use.
- **Power Management**: New background work in main process must handle `powerMonitor` suspend/resume events.
- **Asynchronous Rust**: Use `tauri::command(async)` for I/O bound operations in Rust to avoid blocking the main thread.

## Scope & Workflows
- **Focused PRs**: Don't refactor and add features in the same PR.
Expand Down
50 changes: 27 additions & 23 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,31 +36,34 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4

- name: Install Rust
uses: dtolnay/rust-toolchain@stable

- name: Install dependencies (Ubuntu only)
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev build-essential curl wget file libssl-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev

- uses: actions/setup-node@v4
with:
node-version: '22'

- run: npm ci

- run: npm run build

- name: Build Electron app
run: npx electron-builder
- name: Build and Upload Tauri App
uses: tauri-apps/tauri-action@v0
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Upload Release Assets
uses: softprops/action-gh-release@v3
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
with:
tag_name: ${{ needs.create-tag.outputs.new_tag }}
fail_on_unmatched_files: false
files: |
release/*.zip
release/*.dmg
release/*.exe
release/*.AppImage
release/*.deb
release/*.yml
release/*.blockmap
tagName: ${{ needs.create-tag.outputs.new_tag }}
releaseName: 'PaperCache ${{ needs.create-tag.outputs.new_tag }}'
releaseBody: 'See the assets to download this version and install.'
releaseDraft: false
prerelease: false

update-homebrew:
needs: [create-tag, build-and-release]
Expand All @@ -73,22 +76,23 @@ jobs:
token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
path: homebrew-tap

- name: Download macOS ZIP
- name: Download macOS DMG
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION=${{ needs.create-tag.outputs.new_version }}
gh release download v$VERSION --pattern "*.zip" --repo $GITHUB_REPOSITORY
gh release download v$VERSION --pattern "*.dmg" --repo $GITHUB_REPOSITORY

# Calculate SHA256 of the downloaded ZIP
ZIP_FILE=$(ls *.zip | head -n 1)
SHA256=$(shasum -a 256 "$ZIP_FILE" | awk '{ print $1 }')
# Calculate SHA256 of the downloaded DMG
DMG_FILE=$(ls *.dmg | head -n 1)
SHA256=$(shasum -a 256 "$DMG_FILE" | awk '{ print $1 }')

# Update the rb file
cd homebrew-tap
sed -i '' "s/version \".*\"/version \"$VERSION\"/" Casks/papercache.rb
sed -i '' "s/sha256 arm: * \".*\"/sha256 arm: \"$SHA256\"/" Casks/papercache.rb
sed -i '' "s/PaperCache-[0-9]*\.[0-9]*\.[0-9]*-/PaperCache-#{version}-/g" Casks/papercache.rb
sed -i '' "s/\.zip/\.dmg/g" Casks/papercache.rb

# Commit and Push
git config user.name "github-actions[bot]"
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,8 @@ dist-electron
release
*.env
coverage/

# Rust and Tauri build outputs
target/
src-tauri/target/
src-tauri/gen/
32 changes: 22 additions & 10 deletions PERFORMANCE_AUDIT.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,37 @@
# Performance Audit: PaperCache V0.4.0
# Performance Audit: PaperCache V0.5.0-beta (Tauri Migration)

**Date:** October 26, 2024
**Date:** June 22, 2026
**Auditor:** VariableThe
**App Version:** 0.4.0 (Post-Refactor)
**App Version:** 0.5.0-beta (Tauri Migration)

## 1. Executive Summary (The TL;DR)
This document details the performance improvements made in V0.4.0. The primary goals were eliminating main-thread I/O blocking, reducing the initial JS parse time, and fixing React state-induced UI stutters.
This document details the performance improvements made in V0.5.0-beta by migrating from Electron to Tauri and Rust. The primary goals were drastically reducing the application size and background RAM usage by eliminating the embedded Node.js runtime and Chromium binaries.

| Metric | V0.3.0 (Baseline) | V0.4.0 (Current) | Delta |
| Metric | V0.4.0 (Electron) | V0.5.0-beta (Tauri) | Delta |
| :--- | :--- | :--- | :--- |
| **Initial Bundle Size (JS)** | 18.4 MB | 1.1 MB | **-94%** |
| **Cold Start to Interactive** | 1,450 ms | 320 ms | **-77%** |
| **Idle CPU Usage** | 2.5% | 0.0% | **Zero polling** |
| **IPC Save Latency (500 notes)**| 450 ms (UI Freeze) | 12 ms (Async) | **Non-blocking** |
| **App Installer Size (DMG)** | ~80.0 MB | ~7.3 MB | **-90%** |
| **Idle RAM Usage** | ~120 MB | ~40 MB | **-66%** |
| **Idle CPU Usage** | 0.0% | 0.0% | **Maintained** |
| **IPC Save Latency (500 notes)**| 12 ms (Async) | <5 ms (Rust fs) | **Faster** |

## 2. Testing Methodology & Environment
*To ensure reproducibility, all metrics were captured under the following conditions:*
- **Hardware:** MacBook Air M4, 16GB RAM (Baseline mid-tier dev machine).
- **OS:** macOS 15.7.5
- **Dataset:** Workspace containing 500 markdown notes, averaging 2KB each.
- **Tooling:** Chromium DevTools (Performance & Memory tabs), Electron `process.memoryUsage()`, and custom `performance.mark()` IPC timers.
- **Tooling:** Activity Monitor, `ls -lh`, and Rust `std::time::Instant`.

## 3. The Tauri Migration (V0.5.0-beta)
*Goal: Remove the massive Electron overhead for a background utility.*

- **Removed Node.js & Chromium:** Replaced with Rust backend and native OS webview (WebKit on macOS).
- *Impact:* The `.dmg` size plummeted from ~80MB down to 7.3MB.
- **Rust Backend:** All IPC calls now run through a highly optimized Rust backend using `std::fs` asynchronously.
- *Impact:* IPC latency is effectively instantaneous, with lower memory overhead for background processes.

---

## Historical: V0.4.0 Performance Audit

## 3. Bundle & Ship Size Optimization
*Goal: Reduce the amount of JavaScript V8 must parse on cold start.*
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,11 @@ xattr -cr /Applications/PaperCache.app
git clone https://github.com/VariableThe/PaperCache.git
cd PaperCache
npm install
npm run dev
npm run tauri dev # for local development
npm run tauri build # for production bundling
```

Built with Electron, React, TypeScript, and Vite.
Built with Tauri, Rust, React, TypeScript, and Vite.

---

Expand Down
Loading
Loading