Skip to content

AxelReviron/Tunasse

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

56 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tunasse

Vue.js Ionic Dexie.js PWA

Privacy first

Tunasse stores everything locally on your device using IndexedDB. There is no account, no analytics, and no cloud where your data is held. Your financial data is yours — it lives on your devices.

Optional device sync lets you keep your devices in sync over a direct peer-to-peer connection. Data is encrypted end-to-end by DTLS; no server ever sees it in the clear.

Features

  • Dashboard — Balance overview, monthly income/expense, recurring bills tracker (already paid / still to pay), charts by account and budget
  • Transactions — Income, expenses and transfers between accounts; search and filters by type, date range; recurring transactions
  • Budgets — Monthly caps per category with progress tracking
  • Accounts — Multiple accounts, multiple currencies, balance computed from transactions
  • Offline — Fully functional without internet; installable as a PWA on any device

Tech stack

Layer Technology
UI framework Ionic Vue
Reactivity Vue 3 Composition API (<script setup>)
Local database Dexie.js (IndexedDB wrapper)
PWA vite-plugin-pwa — Workbox + Web App Manifest
Routing Vue Router
Build Vite + TypeScript
i18n Vue I18n (English / French)
Charts Chart.js via vue-chartjs
Device sync Trystero (WebRTC, peer-to-peer)

Getting started

docker build -t tunasse-dev .
docker run --rm --name tunasse -p 8100:8100 -v $(pwd):/app -v /app/node_modules tunasse-dev

Run a command inside the container:

docker exec -it tunasse sh

Build for production:

npm run build

Device sync

Sync between your own devices is peer-to-peer over WebRTC, built on Trystero. Peers that share the same passphrase join the same room and exchange data encrypted end-to-end by DTLS. No server ever receives or stores your data.

The signaling layer (used to exchange ICE candidates and establish the connection) carries no user data — only short connection-setup metadata.

Network path

WebRTC tries, in order:

  1. Direct LAN — preferred whenever both peers are on the same network. Desktop-to-desktop sync on the same Wi-Fi goes here, with no third-party server involved.
  2. TURN relay — fallback when a direct path fails (e.g. iOS Safari ↔ Chromium peers)

No third-party STUN or TURN server is ever used. If you need a TURN relay (typically for iOS ↔ desktop sync), you run your own — see Self-hosting a TURN server below.

Self-hosting a TURN server

A TURN server is only needed when direct peer-to-peer connections fail. The coturn/ directory contains a ready-to-use coturn Docker setup.

Requirements: Docker, Docker Compose, and a machine reachable by both devices (local network or VPS).

cd coturn
cp turnserver.conf.example turnserver.conf

Edit turnserver.conf and replace YOUR_USERNAME and YOUR_PASSWORD with credentials of your choice:

user=alice:supersecret

Then start the server:

docker compose up -d

The server listens on port 3478 (TCP + UDP). Make sure that port is reachable from your devices (open it in your firewall if needed).

Connecting the app

Open Tunasse → Settings → Advanced → TURN server and fill in:

Field Value
Host IP or hostname of the machine running coturn
Port 3478
Username the value you set in turnserver.conf
Password the value you set in turnserver.conf

Hit Save — the app will test connectivity and show a green indicator if the server is reachable.

Roadmap

  • PWA icons
  • Settings page — Import/Export, full data reset
  • Onboarding

About

Personal finance manager, privacy first.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors