# Voiced An offline-first desktop invoicing app for **Test Vendor**, built by **Bongbetic**. Voiced turns a few details into a clean, GST-ready PDF invoice. It keeps a running invoice-number series in a local database, remembers your vendor and bank details, and exports print-ready PDFs — no account, no network required. ## Features - **Automatic invoice numbering** — a persistent series (e.g. `INV/2026-001`) that keeps counting up, with a one-click "start a new series" that resets the counter. - **Guided first-run setup** — your name, address, contact, PAN, GSTIN, logo, signature and bank details, pre-filled from your existing invoice and editable at any time. - **Two line-item modes** — a fixed amount, or a rate × quantity where the unit can be per second / minute / hour / session / unit (e.g. 10 sessions × ₹2,500). - **GST support** — toggle taxes on/off and split as **CGST + SGST** (within state) or **IGST** (inter-state), with live totals and Indian amount-in-words. - **Signatures** — attach a PNG/JPEG per invoice, or omit it and the invoice notes that it is computer-generated and needs no signature. - **PDF export** — a print-ready A4 invoice styled to match the original `format.pdf`. - **Saved clients**, invoice history with re-export, and light/dark (Carbon g10/g100) themes. - **Input validation** for PAN, IFSC, GSTIN, email and phone. ## Tech stack | Layer | Choice | | --------- | ------------------------------------------------------------------- | | Shell | [Tauri v2](https://v2.tauri.app/) (Rust core, WebView2 on Windows) | | UI | React + TypeScript + [IBM Carbon Design System](https://carbondesignsystem.com/) (`@carbon/react`) | | Fonts | IBM Plex, self-hosted (works offline) | | Storage | SQLite via `rusqlite` (bundled) | | PDF | `@react-pdf/renderer` with bundled IBM Plex | ## Prerequisites - **Node.js 20+** and npm - **Rust** (stable) via [rustup](https://rustup.rs/) - Linux dev only: WebKitGTK 4.1, libsoup3, GTK3, librsvg, `pkg-config`, `clang`/`llvm`/`lld` ## Development ```bash npm install npm run app:dev # launches the desktop app with hot reload ``` Other scripts: ```bash npm run build # type-check + build the web frontend npm run app:build # package the app for the current platform ``` ## Building for Windows (cross-compile from Linux/macOS) Tauri only supports the MSVC target. Cross-compiling uses [`cargo-xwin`](https://github.com/rust-cross/cargo-xwin) and produces an **NSIS installer** plus a portable `.exe`. A `.msi` still requires a real Windows host. ```bash # one-time setup rustup target add x86_64-pc-windows-msvc cargo install --locked cargo-xwin # plus NSIS (makensis), LLVM/LLD and clang on the host npm run app:build:windows ``` Output lands in `src-tauri/target/x86_64-pc-windows-msvc/release/bundle/nsis/` and the portable binary in the sibling `release/` folder. ### Notes for Linux hosts without an `nsis` package `makensis` is required for the installer, and Tauri also fetches a small NSIS plugin. On distributions that don't package NSIS (e.g. Void Linux): 1. Provide `makensis` (e.g. extract it from your distribution's or an upstream package) and put it on `PATH`. 2. Point `makensis` at a full NSIS data directory (3.11 recommended, for `Win/RestartManager.nsh`); it looks in the directory compiled into the binary unless `NSISDIR` is set. 3. Pre-seed Tauri's plugin cache so it does not have to download it: ``` mkdir -p ~/.cache/tauri/NSIS/Plugins/x86-unicode/additional # nsis_tauri_utils.dll (SHA1 75197fee3c6a814fe035788d1c34ead39349b860) # from https://github.com/tauri-apps/nsis-tauri-utils/releases ``` With those in place, `npm run app:build:windows` produces the NSIS `-setup.exe` and the portable `voiced.exe`. ## Installing on Void Linux Two ways to get a native `.xbps` package. ### Prebuilt binary package (no xbps-src needed) ```bash ./packaging/void/build-xbps.sh # -> build/void/repo/voiced-_1..xbps echo "repository=$(pwd)/build/void/repo" | sudo tee /etc/xbps.d/99-voiced-local.conf sudo xbps-install -Sy voiced ``` Launch **Voiced** from the application menu, or run `voiced`. Remove it with `sudo xbps-remove voiced`. The package installs `/usr/bin/voiced`, a desktop entry and hicolor icons, and depends on `libwebkit2gtk41`. **Fonts on Void.** The package also installs the bundled TTF fonts under `/usr/share/fonts/voiced//` and each family's OFL licence under `/usr/share/licenses/voiced/`. The `voiced/` subdirectory avoids file conflicts with Void's own `font-ibm-plex-ttf` and `noto-fonts-ttf`. The `INSTALL` and `REMOVE` scripts in `packaging/void/` run `fc-cache -f /usr/share/fonts/voiced` after install and removal. `xbps-create` packs them from the destdir root (checked with xbps 0.60.7). ### Building through xbps-src Copy `packaging/void/template` into a `void-packages` checkout and build it the standard way: ```bash mkdir -p void-packages/srcpkgs/voiced cp packaging/void/template packaging/void/INSTALL packaging/void/REMOVE void-packages/srcpkgs/voiced/ cd void-packages && ./xbps-src pkg voiced ``` See the comments at the top of the template about the private source archive and checksums. ## Where data lives | What | Location | | ------------------- | ------------------------------------------------------------- | | Database | `/voiced.db` — on Windows `%APPDATA%\com.bongbetic.voiced\` | | Logos & signatures | `/assets/` | ## Project layout ``` src/ React + Carbon frontend views/ Onboarding · NewInvoice · InvoiceHistory · SeriesSettings · AppSettings components/ AppShell · InvoicePreview · ImagePicker pdf/ InvoiceDocument (react-pdf template) lib/ api · types · invoice · numberToWords · validators · format · pdf src-tauri/ Rust backend (Tauri commands, SQLite schema, asset store) public/brand/ Bongbetic + vendor brand assets public/fonts/ IBM Plex (woff/woff2) packaging/void/ Void Linux packaging (xbps-src template + build script + desktop entry) ``` ## Ownership © Bongbetic. All rights reserved. This is a private application.