- Bump the version to 1.0.0 in package.json, Cargo.toml, tauri.conf.json and the Void template. Fingerprint goldens are unchanged. - Rewrite the README: features, data paths on Linux and Windows, backup and restore (backups contain the ERPNext API secret), bundled fonts and licences, font overrides, the ERPNext recipe, build and packaging commands, gates and known limitations. - Add docs/RELEASE.md with the release steps and a manual first-run checklist. - Void template: use a plain npm ci (the optional-dependency omit breaks vite and tsc), and note vendoring and that no OpenSSL is needed. Verified: build-xbps.sh builds voiced-1.0.0_1; it installs and removes cleanly in a clean void-glibc container with fonts, licences and fc-cache handling in place. The cross-compiled NSIS installer is 11.45 MiB and has not been run on Windows.
This commit is contained in:
@@ -1,84 +1,181 @@
|
||||
# Voiced
|
||||
|
||||
An offline-first desktop invoicing app for **Arun P**, built by **Bongbetic**.
|
||||
An offline-first GST invoicing desktop app for **Arun P**, 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.
|
||||
Voiced turns a few details into a clean, print-ready PDF invoice. It keeps a running invoice-number series in a
|
||||
local database, remembers your vendor, client and bank details, and works without an account or a network
|
||||
connection. The only optional network feature is the ERPNext push, which you configure yourself.
|
||||
|
||||
Targets: Void Linux (xbps, WebKitGTK 2.50 or newer) and Windows 10/11 (NSIS installer, WebView2).
|
||||
|
||||
## Features
|
||||
|
||||
- **Automatic invoice numbering** — a persistent series (e.g. `AP/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.
|
||||
- **Invoices.** Automatic numbering in a persistent series (for example `AP/2026-001`) with a one-click new series,
|
||||
drafts, issue and cancel. An issued invoice is immutable: it stores a snapshot of the vendor, client, GST figures
|
||||
and layout. Line items are a fixed amount or rate x quantity (per second, minute, hour, session or unit), with
|
||||
item presets.
|
||||
- **GST.** All money and tax maths is done in integer paise. CGST+SGST, IGST or UTGST follow from the supplier's
|
||||
state and the place of supply, and a mismatch is rejected. An unregistered vendor gets a plain "Invoice" with no
|
||||
tax. GSTIN, PAN, IFSC, email and phone are validated; amounts are written in Indian words.
|
||||
- **Templates.** 14 templates: Voiced Standard (Classic) and 13 designs measured from Canva originals (Linea,
|
||||
Monogram, Serenity, Crimson Grid, Tangerine Ledger, Slate Band, Teal Swoosh, Purple Pop, Citrus Split, Monolith,
|
||||
Cobalt Stripe, Marble, Highlighter). Your logo fills the template's logo slot; a few templates offer an opt-in
|
||||
logo position. Specs are in `docs/templates/`.
|
||||
- **Page setup.** A4 or Letter, and margin presets (template, narrow 36 pt, normal 54 pt).
|
||||
- **Export modes.** *Searchable* PDF (text layer kept) or *flattened* (pages rasterised at 300 DPI and rebuilt as
|
||||
an image-only PDF). Issued PDFs are archived by content hash, and "Original as issued" re-exports the exact
|
||||
archived bytes.
|
||||
- **Fonts.** 11 bundled font families (see "Fonts and licences"). The three commercial template faces (Now, Gotham,
|
||||
Open Sauce One) can be overridden with your own licensed files under Settings, Fonts.
|
||||
- **Clients and presets.** Saved clients with structured addresses, state and GST category; item presets.
|
||||
- **Payments.** Record payments against an issued invoice, including TDS deducted by the client. Outstanding
|
||||
balance is cash plus TDS against the invoice total.
|
||||
- **History.** Filterable invoice list, detail view with payments, and CSV or JSON export of the list.
|
||||
- **Backup and restore.** Manual and automatic daily backups of the database, assets, PDF archive and imported fonts.
|
||||
- **Export for other software.** `voiced.invoice.v1` JSON and line-item CSV for selected invoices
|
||||
(see `docs/voiced-invoice-v1.md`).
|
||||
- **ERPNext integration.** Push an invoice (as draft or submitted) with its PDF attached, and record payments, to an
|
||||
ERPNext v15 site.
|
||||
- Light and dark (Carbon g10/g100) themes.
|
||||
|
||||
## 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 |
|
||||
| Layer | Choice |
|
||||
| ------- | ------------------------------------------------------------------------------------------- |
|
||||
| Shell | [Tauri v2](https://v2.tauri.app/) (Rust core, WebKitGTK on Linux, WebView2 on Windows) |
|
||||
| UI | React 19 + TypeScript + [IBM Carbon](https://carbondesignsystem.com/) (`@carbon/react`) |
|
||||
| Storage | SQLite via `rusqlite` (bundled), numbered migrations |
|
||||
| PDF | `@react-pdf/renderer` 4.9.0 in a Web Worker, pdf.js for preview and flattening |
|
||||
| ERPNext | `reqwest` with rustls (ring provider); all HTTP runs in Rust |
|
||||
|
||||
## 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`
|
||||
- **Node.js 22** and npm
|
||||
- **Rust** stable, via [rustup](https://rustup.rs/)
|
||||
- Linux 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
|
||||
npm run app:dev # tauri dev, served from localhost:1420 (does not exercise the tauri:// protocol)
|
||||
```
|
||||
|
||||
Other scripts:
|
||||
| Command | What it does |
|
||||
| --- | --- |
|
||||
| `npm run build` | `tsc --noEmit` and `vite build` (the type-check gate) |
|
||||
| `npm test` | `vitest run`, about 7 minutes; run on a quiet machine because load starves the sweep tests |
|
||||
| `npm run fonts:verify` | Checks the bundled fonts against `public/fonts/manifest.json` (`fonts:manifest` regenerates it) |
|
||||
| `npm run logo:measure` | Regenerates `src/pdf/templates/slots.generated.ts` from the Canva PDFs; must be idempotent |
|
||||
| `npm run thumbnails` | Regenerates `public/templates/*.png` |
|
||||
| `npm run templates:compare` | Canva vs Voiced side-by-side PNGs under `/tmp` |
|
||||
| `cargo test --manifest-path src-tauri/Cargo.toml` | Rust unit tests |
|
||||
| `npm run app:build` | Production build for the current platform (custom-protocol) |
|
||||
|
||||
```bash
|
||||
npm run build # type-check + build the web frontend
|
||||
npm run app:build # package the app for the current platform
|
||||
```
|
||||
The release procedure, including the manual first-run checklist, is in `docs/RELEASE.md`.
|
||||
|
||||
## Building for Windows (cross-compile from Linux/macOS)
|
||||
## Where data lives
|
||||
|
||||
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.
|
||||
The Tauri identifier is `com.bongbetic.voiced`. Voiced uses two directories, which differ only on Windows:
|
||||
|
||||
| What | Linux | Windows |
|
||||
| --- | --- | --- |
|
||||
| `app_data_dir`: database `voiced.db`, `assets/` (logos, signatures), `backups/` (`auto/`, `pre-restore-*`, pre-migration copies) | `~/.local/share/com.bongbetic.voiced/` | `%APPDATA%\com.bongbetic.voiced\` |
|
||||
| `app_local_data_dir`: `archive/<sha256>.pdf` (issued PDFs), `fonts/` (fonts you import) | `~/.local/share/com.bongbetic.voiced/` | `%LOCALAPPDATA%\com.bongbetic.voiced\` |
|
||||
|
||||
On Linux `XDG_DATA_HOME` moves both. On Windows the archive and imported fonts stay out of the roaming profile so a
|
||||
growing archive and licensed font files are not copied between machines. The window size and position are kept by
|
||||
the window-state plugin in the app config directory (`~/.config/com.bongbetic.voiced/` on Linux).
|
||||
|
||||
## Backup and restore
|
||||
|
||||
Settings, Data tab.
|
||||
|
||||
- **Backup now** writes a zip: a consistent snapshot of `voiced.db`, `assets/`, `archive/`, `fonts/` and a
|
||||
`manifest.json` with a sha256 for every file.
|
||||
- **Automatic backup.** Once per calendar day, while the app is open, Voiced writes
|
||||
`backups/auto/voiced-auto-YYYYMMDD.zip` and keeps the newest 14.
|
||||
- **Restore** validates the zip (manifest, hashes, database integrity check) and stages it. Nothing live changes until
|
||||
the next start: use the "Restart" button or close and reopen the app. On that start the current database, assets,
|
||||
archive and fonts are moved to `backups/pre-restore-<timestamp>/` (a safety copy that is never pruned), then the
|
||||
restored files are moved in. If anything fails the app rolls back and starts on the old data. A backup from an
|
||||
older schema is migrated after restoring.
|
||||
- **Backups contain secrets.** The ERPNext API secret is stored in the SQLite database, so every backup (manual,
|
||||
automatic and pre-restore) holds it in plain form, together with your clients, invoices and bank details. Keep
|
||||
backup files on storage you trust, do not email or upload them casually, and rotate the ERPNext API key if a
|
||||
backup is lost.
|
||||
|
||||
## Fonts and licences
|
||||
|
||||
Eleven families are bundled as static TTF files in `public/fonts/<family>/`, each with its `OFL.txt`: DM Sans,
|
||||
IBM Plex Mono, IBM Plex Sans, Inter, Jost, Lustria, Montserrat, Noto Sans Devanagari, Noto Sans Kannada, Open Sans
|
||||
and Poppins. All are under the SIL Open Font License 1.1. `public/fonts/manifest.json` lists every file with its
|
||||
hash and metrics, and `npm run fonts:verify` checks it. PDFs embed subsets, so the app never depends on system
|
||||
fonts.
|
||||
|
||||
The Void package also installs these fonts system-wide under `/usr/share/fonts/voiced/<family>/` and each OFL text
|
||||
as `/usr/share/licenses/voiced/<family-folder>-OFL.txt`.
|
||||
|
||||
**Now, Gotham and Open Sauce One** are not bundled. Voiced draws Now with Jost, Gotham with Montserrat and Open
|
||||
Sauce One with Poppins (Marble, Citrus Split and Purple Pop use these faces). If you hold a licence
|
||||
for the real fonts, import the files under Settings, Fonts (TTF, OTF or WOFF, one file per weight; WOFF2, variable
|
||||
and font-collection files are refused). Importing is your confirmation that your licence covers this use. The files
|
||||
are stored on this computer only, are included in backups, and issued invoices keep the fonts they were issued with.
|
||||
|
||||
## ERPNext integration
|
||||
|
||||
Settings, Integrations. Verified live against ERPNext v15.121.6 (Frappe 15.121), with and without India Compliance
|
||||
15.32. v14 and v16 have not been tested.
|
||||
|
||||
1. **Integration user.** In ERPNext create a dedicated user (type System User) with the roles **Accounts User** and
|
||||
**Sales User**. Open the user, Settings tab, API Access, Generate Keys, and copy the secret once. Accounts User
|
||||
covers invoices, payments and attachments; Sales User covers customers and addresses (Accounts User alone gets
|
||||
HTTP 403 on Customer). Do not use Administrator or System Manager keys. If you change roles, run
|
||||
`bench clear-cache`.
|
||||
2. **Rounding.** In ERPNext System Settings set Rounding Method to **Commercial Rounding**. ERPNext defaults to
|
||||
Banker's Rounding while Voiced rounds half-paise up, so some totals would differ by 1 paise. Voiced detects a
|
||||
mismatch after creating the draft, keeps it as a draft, never submits it, and names this fix.
|
||||
3. **Connect.** Enter the site address, API key and secret and run "Test connection". Use `https://` for real
|
||||
servers; plain `http://` is accepted only for `localhost`, `127.0.0.1`, `*.localhost` and `*.test`. The secret is
|
||||
never shown again, and it is not sent to a different server than the one it was saved for.
|
||||
4. **Company, accounts and units.** Pick the company, the output tax accounts (CGST, SGST, IGST), the bank account for
|
||||
payments and the unit-of-measure mapping from the loaded option lists.
|
||||
5. **Naming.** *Mirror* (default) names the ERPNext document with the Voiced number, which needs a site with API v2
|
||||
naming (Frappe 15.73 or newer). *Series* lets an ERPNext naming series name the document and puts the Voiced
|
||||
number in the remarks.
|
||||
6. **India Compliance.** Detected by the connection test. It requires a 6 or 8 digit HSN/SAC code on each row
|
||||
(checked at submit), limits document names to 16 characters (mirror mode checks this before posting), and Voiced
|
||||
always sends `is_reverse_charge` as 0 with a warning.
|
||||
|
||||
Not covered: overseas and SEZ customers, multi-currency, reverse charge booked on RCM accounts, e-invoice and
|
||||
e-waybill, TLS-terminating proxies beyond plain HTTPS, and Windows. The live test setup is in
|
||||
`scripts/erpnext-e2e/README.md`.
|
||||
|
||||
## Building for Windows (NSIS, cross-compiled from Linux)
|
||||
|
||||
Tauri supports only the MSVC target. [`cargo-xwin`](https://github.com/rust-cross/cargo-xwin) cross-compiles it
|
||||
and Tauri produces an **NSIS installer** (a `.msi` needs 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
|
||||
# plus makensis (NSIS), LLVM/LLD and clang on the host
|
||||
|
||||
npm run app:build:windows
|
||||
npm run app:build:windows # embeds the small WebView2 bootstrapper (needs internet if WebView2 is missing)
|
||||
npm run app:build:windows:offline # embeds the full WebView2 runtime (over 100 MB larger), for offline machines
|
||||
```
|
||||
|
||||
Output lands in `src-tauri/target/x86_64-pc-windows-msvc/release/bundle/nsis/` and the
|
||||
portable binary in the sibling `release/` folder.
|
||||
Output: `src-tauri/target/x86_64-pc-windows-msvc/release/bundle/nsis/Voiced_<version>_x64-setup.exe`, and the portable
|
||||
binary in the sibling `release/` folder. The installer is a per-user install (`installMode: currentUser`). The
|
||||
frontend, fonts and pdf.js are compiled into the executable. Size budget: about 25 MB for the standard installer.
|
||||
`cargo tree -i aws-lc-sys --target x86_64-pc-windows-msvc` must print nothing (the TLS stack is rustls with the ring
|
||||
provider only, which cross-compiles cleanly).
|
||||
|
||||
### Notes for Linux hosts without an `nsis` package
|
||||
Hosts without an `nsis` package (for example Void Linux):
|
||||
|
||||
`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.
|
||||
1. Provide `makensis` and put it on `PATH`.
|
||||
2. Point it at a full NSIS data directory (3.11 recommended, for `Win/RestartManager.nsh`) with `NSISDIR`.
|
||||
3. Pre-seed Tauri's plugin cache so it does not have to download it:
|
||||
|
||||
```
|
||||
@@ -87,13 +184,10 @@ distributions that don't package NSIS (e.g. Void Linux):
|
||||
# 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`.
|
||||
The installer has not been run on a real Windows machine.
|
||||
|
||||
## Installing on Void Linux
|
||||
|
||||
Two ways to get a native `.xbps` package.
|
||||
|
||||
### Prebuilt binary package (no xbps-src needed)
|
||||
|
||||
```bash
|
||||
@@ -102,52 +196,91 @@ echo "repository=$(pwd)/build/void/repo" | sudo tee /etc/xbps.d/99-voiced-local.
|
||||
sudo xbps-install -Sy voiced
|
||||
```
|
||||
|
||||
Launch **Voiced** from the application menu, or run `voiced`. Remove it with
|
||||
`sudo xbps-remove voiced`.
|
||||
The script runs `npx tauri build --no-bundle --features custom-protocol` (using your existing `node_modules`), stages
|
||||
the install tree and runs `xbps-create` and `xbps-rindex`. 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).
|
||||
The package installs `/usr/bin/voiced`, a desktop entry, hicolor icons, the bundled fonts under
|
||||
`/usr/share/fonts/voiced/<family>/`, the OFL texts under `/usr/share/licenses/voiced/`, and `INSTALL` and `REMOVE`
|
||||
action scripts that run `fc-cache -f /usr/share/fonts/voiced` after install and removal. The `voiced/` font
|
||||
subdirectory avoids file conflicts with Void's `font-ibm-plex-ttf` and `noto-fonts-ttf`. It depends on
|
||||
`libwebkit2gtk41>=2.50`, `fontconfig`, `xdg-utils`, `hicolor-icon-theme` and `desktop-file-utils`.
|
||||
|
||||
### 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/` |
|
||||
`INSTALL` and `REMOVE` must sit next to the template; xbps-src packs them. The source is a tagged archive of the
|
||||
private repository (see the comments at the top of the template; `checksum=SKIP` until a tarball is published).
|
||||
xbps-src builds in a network-less chroot, so vendor the dependencies first: run `cargo vendor` in `src-tauri/` (with a
|
||||
`.cargo/config.toml` pointing at `vendor/`) and populate the npm cache, and include the results in the source
|
||||
archive. The template runs `npm ci` (not `--omit=optional`: that removes
|
||||
the native rollup and esbuild binaries the Vite build needs, and `@napi-rs/canvas` is type-checked by `tsc`).
|
||||
No OpenSSL is needed (rustls), and the
|
||||
dependencies of the ERPNext and backup code (`reqwest`, `zip`) are pure Rust.
|
||||
|
||||
## 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)
|
||||
src/ React + Carbon frontend
|
||||
views/ Onboarding, NewInvoice, InvoiceHistory, InvoiceDetail, Clients, AppSettings, SeriesSettings
|
||||
components/ AppShell, TemplatePicker, PageSetupControls, PdfPreview, LogoBranding,
|
||||
FontOverrideTable, DataBackupPanel, ErpnextSettingsPanel, RecordPaymentModal, ...
|
||||
hooks/ Export, PDF preview, user fonts, shortcuts
|
||||
lib/ Typed Tauri wrapper (api.ts), money, GST helpers, exportFlow, historyExport,
|
||||
invoiceExportV1, ERPNext UI helpers
|
||||
pdf/ PDF engine
|
||||
model/ buildRenderModel (invoice -> render model)
|
||||
engine/ geometry (A4/Letter, margins), logo slots, layout fingerprint
|
||||
templates/ <family>/ with tokens.ts, plan.ts, Layout.tsx; registry.ts, catalog.ts, contract.ts
|
||||
blocks/ decor/ Shared layout blocks and decor
|
||||
fonts/ Font registration, roles, glyph priming
|
||||
render/ renderCore, Web Worker, latest-wins client
|
||||
flatten.ts assemble.ts Rasterise at 300 DPI and rebuild an image-only PDF
|
||||
src-tauri/src/ Rust backend
|
||||
db.rs Schema as numbered migrations (copies the DB aside before migrating)
|
||||
gst.rs Integer-paise money and GST maths
|
||||
logo.rs Logo trimming, quantising, measuring
|
||||
commands/ Tauri commands: invoice, series, clients, payments, presets, settings, assets,
|
||||
archive, fonts, backup, files, raw (binary IPC), erpnext, logo
|
||||
integrations/erpnext/ ERPNext client, mapping, discovery, push
|
||||
selftest.rs Unattended real-webview self-test
|
||||
public/fonts/ Bundled TTF families, OFL texts, manifest.json (plus legacy IBM Plex web fonts)
|
||||
public/templates/ Template thumbnails
|
||||
docs/ Template specs, voiced.invoice.v1, release checklist
|
||||
scripts/ Font, logo, template, thumbnail and ERPNext end-to-end tooling
|
||||
packaging/void/ xbps-src template, build-xbps.sh, desktop entry, INSTALL and REMOVE scripts
|
||||
```
|
||||
|
||||
## Tests and gates
|
||||
|
||||
Before a release (details in `docs/RELEASE.md`): `npm run build`, `npm test`, `npm run fonts:verify`,
|
||||
`cargo test --manifest-path src-tauri/Cargo.toml`, and the real-webview self-test on a debug or installed build:
|
||||
|
||||
```bash
|
||||
npm run tauri -- build --debug --no-bundle --features custom-protocol
|
||||
VOICED_SELFTEST_OUT=/tmp/voiced-e2e/report.json XDG_DATA_HOME=/tmp/voiced-e2e/data \
|
||||
XDG_CONFIG_HOME=/tmp/voiced-e2e/config timeout 180 src-tauri/target/debug/voiced
|
||||
```
|
||||
|
||||
The app is inert unless `VOICED_SELFTEST_OUT` is set; `ok: true` is expected in the report. The same checks run from
|
||||
Settings, Diagnostics.
|
||||
|
||||
## Known limitations
|
||||
|
||||
- Windows and WebView2 have never been run on a real machine; the NSIS installer is cross-compiled only.
|
||||
- The 13 Canva-derived templates are re-creations of Canva designs. Canva's content licence may restrict this, so
|
||||
ship them only in this vendor's build until it is confirmed.
|
||||
- The SAC code for the vendor's services and the signature rule still need confirmation from a chartered accountant.
|
||||
- Now, Gotham and Open Sauce One are replaced by free look-alikes unless you import licensed files.
|
||||
- ERPNext: only v15 is verified; HTTP is allowed only for local hosts; see "Not covered" above.
|
||||
- Not implemented (deferred): copies and watermarks, PDF/A, custom margins, user background textures, SVG logo
|
||||
import, CESS, composition and SEZ invoices.
|
||||
|
||||
## Ownership
|
||||
|
||||
© Bongbetic. All rights reserved. This is a private application.
|
||||
|
||||
Reference in New Issue
Block a user