Invoicery

Invoicery

Docker app from akshaybhandare's Repository

Overview

Invoicery is a self-hosted boutique workshop for crafting invoices, tracking expenses, managing inventory, and generating automated Indian GST (GSTR-1 and GSTR-3B) tax reports. Built with Bun, SQLite, and vanilla modern web tech, featuring offline-first local data ownership, automated interstate/intrastate tax routing, backup & restore, and a clean dark-mode UI.

Invoicery Logo

Invoicery ── Boutique Self-Hosted Invoicing & GST Assistant

Invoicery Banner

An elegant, offline-first billing dashboard, customer-ledger database, and Indian GST filing assistant.
Crafted with Bun, SQLite, and Vanilla JS/CSS. Self-contained, secure, and ready to self-host.

Features • Installation • Docker Freezing • Unraid Server • How it Works • API Documentation • Tests


🔮 The Philosophy Behind the "Sorcery"

Traditional accounting tools are either heavy, bloated cloud services that harvest your business data, or overly simplified command line trackers. Invoicery is designed as a boutique workshop for your invoicing needs.

It mixes the safety of an offline-first local database with the convenience of a modern web workspace. Bookkeeping shouldn't feel like a chore; with the right UI and automated tax routing, it feels like magic.


⚡ Key Features

  • Complete Local Data Ownership: Runs entirely in your local network/environment. No third-party servers, no subscription fees, no data leaks.
  • Instant Tax Classification: Input customer information once, and the backend tax engine calculates and applies CGST, SGST, or IGST based on the place of supply rules automatically.
  • Automated Indian GST Prep: Instantly structures your transactions into audit registers ready for GSTR-1 (B2B, B2CL, B2CS, CDNR, CDNUR, Export) and GSTR-3B tax filing.
  • Inventory Control & Ledger Sync: Integrated stocks auto-deduct upon sales invoices and auto-increment upon recording purchases.
  • Modern Dark Aesthetics: A bespoke UI constructed with high-contrast, premium dark mode styling and reactive SVG analytical widgets.
  • Bridges to External Apps: A secure API token system lets you hook up scanning devices, command line utilities, or inventory scripts directly to your billing book.
  • Seamless Backups: Pack up your entire database (data/billing.db) and uploaded files/receipts (attachments/) into a single portable zip file, and restore it with one click.

📐 How the Magic Works

Invoicery uses a lightweight local stack. Here is how your billing, expenses, and tax computations flow:

graph TD
    subgraph Client ["Client Browser (Vanilla JS/CSS)"]
        Dashboard["Dashboard Workspace"]
        InvForm["Invoice Creator"]
        ExpForm["Expense/Purchase Logs"]
    end

    subgraph Backend ["Isolated Bun Server v1.3.14"]
        Router["Server HTTP Router"]
        TaxEngine["Tax Routing Engine"]
        DB["SQLite Database (bun:sqlite)"]
        GstrGen["GSTR-1 & 3B compiler"]
    end

    InvForm -->|HTTP REST POST| Router
    ExpForm -->|HTTP REST POST| Router
    Router -->|Query/Insert| DB
    TaxEngine -->|Evaluate State Codes| DB
    DB -->|Read Data| GstrGen
    GstrGen -->|Transmit JSON summary| Dashboard

The State Tax Logic

When you create an invoice, Invoicery checks the Merchant State Code (from settings) against the Customer Place of Supply State Code:

  • Match (Intrastate): Split tax equally into CGST and SGST (e.g., 9% CGST + 9% SGST for an 18% rate).
  • Mismatch (Interstate): Allocate the entire tax rate to IGST (e.g., 18% IGST).

🚀 Local Installation

Prerequisites

Ensure you have the Bun runtime installed.

curl -fsSL https://bun.sh/install | bash

Running Locally

  1. Navigate to the workspace folder:

    cd invoicery
    
  2. Install project dependencies & type definitions:

    bun install
    
  3. Start the development server (runs with hot reloading):

    bun run dev
    
  4. Start the production server:

    bun run start
    

The application starts on port 3000 and binds only to 127.0.0.1 by default for local security compliance. Open http://localhost:3000 in your browser.


🐳 Docker Deployment (The Recommended Way to Freeze the App)

To freeze the environment and guarantee that future OS updates, library updates, or node runtime changes never break your billing system, run Invoicery inside an isolated Docker container.

  1. Build and start the services:

    docker compose up -d --build
    
  2. Access the application: Open http://localhost:3000. Inside Docker, the server binds to 0.0.0.0 securely to allow port forwarding to your host.

  3. Persistent Directories: The docker-compose.yml links directories from your host machine so your records are never lost when containers reboot:

    • ./data/ ── Storehouse for persistent SQLite database (data/billing.db).
    • ./attachments/ ── Storehouse for invoice PDF and receipt uploads.

🖥️ Unraid Server Deployment

You can deploy Invoicery to an Unraid server using either Docker Compose or Unraid's Docker Web UI.

Option A: Docker Compose (Recommended)

If you use Docker Compose Manager, Dockge, or Portainer on Unraid:

  1. Transfer or clone the repository into your appdata folder: /mnt/user/appdata/invoicery/
  2. Open the Unraid Terminal (or SSH in) and run:
    cd /mnt/user/appdata/invoicery
    docker compose up -d --build
    
  3. Access the web app at http://<YOUR_UNRAID_IP>:3000.

Option B: Unraid Web UI (Manual Container Setup)

  1. Build the image on your Unraid server terminal:
    cd /mnt/user/appdata/invoicery
    docker build -t invoicery:latest .
    
  2. Go to Unraid Docker tab ➔ Add Container.
  3. Set Name to invoicery and Repository to invoicery:latest.
  4. Add Port Mapping:
    • Container Port: 3000 | Host Port: 3000 (or your choice of host port)
  5. Add Volume Mappings:
    • Container Path: /app/data ➔ Host Path: /mnt/user/appdata/invoicery/data
    • Container Path: /app/attachments ➔ Host Path: /mnt/user/appdata/invoicery/attachments
  6. Add Environment Variables:
    • PORT: 3000
    • HOST: 0.0.0.0
    • NODE_ENV: production
    • DB_PATH: /app/data/billing.db
  7. Click Apply.

⚙️ Environment Variables

You can configure port and bindings easily. These are pre-configured in the Docker Compose workspace but can be modified for local runs:

Variable Default Description
PORT 3000 Port server runs on
HOST 127.0.0.1 Binding address (set to 0.0.0.0 for Docker/LAN access)
NODE_ENV production Running profile flag
DB_PATH ./data/billing.db Relative or absolute path to SQLite database

🔌 Developer API

Invoicery includes a secure programmatic integration layer to connect custom external scripts.

Authentication

Include one of the following credentials inside your HTTP headers (manage your custom keys in the Settings panel):

  • Custom Key Header: x-api-key: <your_key>
  • Standard Authorization Header: Authorization: Bearer <your_key>

Key Endpoint Routings

Method Endpoint Payload Format Description
GET /api/dashboard JSON Real-time analytics charts and summaries
POST /api/invoices JSON Generates a sales record & subtracts stock
POST /api/purchases JSON Creates a vendor receipt & increments stock
POST /api/products/adjust JSON Direct stock adjustment override
GET /api/backup Binary Stream Combines data/billing.db and attachments into a ZIP
POST /api/restore Multipart FormData Overwrites active database from a backup ZIP

🧪 Test Suite

Run the full local test suite (incorporating tax calculation rounding, schema validation, state matching, and layout integrity checks) via:

bun test

Details

Repository
ghcr.io/akshaybhandare/invoicery:latest
Last Updated2026-10-12
First Seen2026-10-11

Runtime arguments

Web UI
http://[IP]:[PORT:3000]
Network
bridge
Shell
sh
Privileged
false

Template configuration

WebUI PortPorttcp

Port used by the Invoicery web interface.

Target
3000
Default
3000
Data Storage PathPathrw

Persistent directory for storing Invoicery SQLite database (billing.db).

Target
/app/data
Default
/mnt/user/appdata/invoicery/data
Attachments Storage PathPathrw

Persistent directory for storing invoice PDFs and receipt uploads.

Target
/app/attachments
Default
/mnt/user/appdata/invoicery/attachments
HOSTVariable

Network binding address (set to 0.0.0.0 to allow access from local network).

Default
0.0.0.0
PORTVariable

Internal server port.

Default
3000
NODE_ENVVariable

Running profile environment.

Default
production
DB_PATHVariable

Path to SQLite database file inside container.

Default
/app/data/billing.db