Font import: - Migration M6 adds user_fonts; files are stored content-addressed under the local data dir. New Rust commands inspect, import, list, read and remove fonts, refusing WOFF2, collections, variable fonts and restricted fsType, and unpacking WOFF1 to plain sfnt. - Imported fonts register in the render worker as user:<Face> families with an italic alias, and are pinned in the frozen render prefs so issued invoices can still re-render. Fonts referenced by issued invoices are hidden, never deleted. - Size and tracking compensations tuned for the substitutes apply only while the face is not overridden; default output and fingerprint goldens are unchanged. - Settings gets a Fonts section with a licence acknowledgement. Void packaging: - Install fonts to /usr/share/fonts/voiced with per-family OFL licences, set font_dirs, and add INSTALL/REMOVE scripts that run fc-cache. xbps-create carries both scripts (verified in a void-glibc container). - Fix xbps-create dependency specs in build-xbps.sh.
154 lines
6.4 KiB
Markdown
154 lines
6.4 KiB
Markdown
# 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-<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:
|
||
|
||
```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 | `<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.
|