- ErpnextSink implements InvoiceSink. Pushing an issued invoice ensures the Customer and Address (read-back of the returned name, local PIN/state/GSTIN checks), creates the Sales Invoice, optionally submits it in a second call, and attaches the archived PDF as a private file once. - Idempotent: a mirrored-name 409 is compared by grand total (same total records as synced, different total is a conflict and never overwrites); series mode looks up an existing document by its remarks before re-posting; an identical re-push sends nothing. - Create and submit are separate calls so a draft survives a failed submit. A failed push is recorded in erpnext_sync with a readable message. Bulk push never aborts on one failing row. - Payment push requires a submitted parent, maps TDS to Payment Entry deductions and is idempotent through the stored entry name. - Migration M11 rebuilds erpnext_sync to allow a conflict status and adds attachment_sha256. - Commands for single and bulk push, payment push, sync status and the open-in-ERPNext URL, with typed wrappers. No UI yet. Tested against a mock server only. The Payment Entry deductions fields, the series-mode submit route and the payment amount semantics need a live ERPNext check.
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 (Rust core, WebView2 on Windows) |
| UI | React + TypeScript + IBM Carbon Design System (@carbon/react) |
| Fonts | IBM Plex, self-hosted (works offline) |
| Storage | SQLite via rusqlite (bundled) |
@react-pdf/renderer with bundled IBM Plex |
Prerequisites
- Node.js 20+ and npm
- Rust (stable) via rustup
- Linux dev only: WebKitGTK 4.1, libsoup3, GTK3, librsvg,
pkg-config,clang/llvm/lld
Development
npm install
npm run app:dev # launches the desktop app with hot reload
Other scripts:
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
and produces an NSIS installer plus a portable .exe. A .msi still requires a real
Windows host.
# 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):
-
Provide
makensis(e.g. extract it from your distribution's or an upstream package) and put it onPATH. -
Point
makensisat a full NSIS data directory (3.11 recommended, forWin/RestartManager.nsh); it looks in the directory compiled into the binary unlessNSISDIRis set. -
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)
./packaging/void/build-xbps.sh # -> build/void/repo/voiced-<version>_1.<arch>.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/<family>/ 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:
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 | <app-data>/voiced.db — on Windows %APPDATA%\com.bongbetic.voiced\ |
| Logos & signatures | <app-data>/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.