Inspiration

In the modern freelance and small business landscape, billing tools have become increasingly extractive. Most invoicing platforms are locked behind expensive recurring subscriptions, restrict invoice counts on free tiers, or aggressively harvest user data. Furthermore, privacy is rarely respected; client lists, billing amounts, and raw email addresses are stored in plaintext on distant servers, making them vulnerable to breaches.

Another common developer oversight in billing applications is the use of floating-point arithmetic for currency calculations. Over time, representational floating-point errors yield subtle discrepancies in invoices, which can lead to compliance issues and direct financial losses.

We set out to create RupaX, a client-side first, cryptographically secured invoice generator that treats billing as a secure utility rather than a subscription model. Inspired by the need for enterprise-grade tools that run locally, RupaX requires no account creation, does not collect plaintext personal identifiable information (PII), uses integer-based arithmetic to eliminate rounding errors, and features a clean, professional aesthetic optimized for all screen sizes.


What it does

RupaX is a lightweight, responsive web application that allows freelancers and businesses to generate, style, and download professional invoices in seconds. The core workflow features:

  1. Instant Real-Time Preview: As users edit fields on the left pane, the right canvas renders the exact invoice layout instantly, avoiding save-and-refresh loops.
  2. Cryptographic Integrity & Privacy: Before invoices are submitted to the server for PDF rendering, RupaX encrypts the payload using symmetric AES-128-CBC encryption (via the Fernet scheme) and signs it with an HMAC-SHA256 signature. Any tampering is immediately identified during retrieval. Furthermore, client and user email addresses are pseudonymized using one-way SHA-256 hashes, keeping contact lists safe from data leaks.
  3. Advanced Financial Calculations: RupaX natively handles global currency settings (including custom symbol overrides) and multiple tax structures (such as India GST, UK/EU VAT, and US Sales Tax). All math operates strictly in integer-based cents/paise to avoid representation errors.
  4. Interactive Fare Splitter: For multi-client bills or team expenses, RupaX includes an exact-math division utility supporting up to 100 people. Remainder pennies are distributed sequentially across participants rather than truncated, ensuring total sums match down to the exact decimal.
  5. Aesthetic Adaptability: Users can choose from eight design themes (such as Classic Warm, Executive Dark, Sunset Gold, and Mono Minimal) and switch between dark and light themes seamlessly.
  6. Mobile Optimization & Keyboard Shortcuts: Designed for on-the-go billing, the interface supports swipe gestures to toggle editor/preview panes on smaller viewports and keyboard shortcuts (Ctrl+Enter to generate, Ctrl+K to focus) on desktops.

How I built it

RupaX is built with a decoupled architecture designed for speed and security:

The Frontend

The client interface is constructed using vanilla HTML5, CSS Custom Properties (Variables), and modular JavaScript. By avoiding bloated framework setups (such as React or Tailwind), the application achieves an sub-second load time.

  • State Persistence: Form drafts are saved locally in the browser’s localStorage (key: rupax_draft_v5) to prevent data loss on page refreshes.
  • Canvas Compression: Logo files uploaded via drag-and-drop are downscaled and compressed client-side using an HTML5 Canvas to keep payloads under 2MB.
  • OpenStreetMap Reverse Geocoding: The Geolocation API is combined with Nominatim OpenStreetMap reverse-geocoding to allow users to auto-detect and populate their business address.

The Backend

The server acts as a stateless document generation engine:

  • API Framework: FastAPI manages the backend endpoints with Pydantic validating incoming JSON payloads.
  • PDF Rendering: The platform uses WeasyPrint to transform CSS-styled HTML templates into high-fidelity PDFs, bypassing the resource overhead of headless browsers.
  • Security & Database ORM: SQLModel handles type-safe interactions with PostgreSQL (in production) or SQLite (in development). The database only stores ciphertext payloads, HMAC signatures, and SHA-256 hashes. Invoices and their compiled PDFs are deleted after a strict 7-day retention period.
  • Rate Limiting: slowapi restricts invoice creation to 20 requests per IP per hour to protect the server from spam.

Challenges I ran into

Building a financial tool in JavaScript and Python presented three major obstacles:

1. Eliminating Floating-Point Errors

JavaScript represents numbers using IEEE 754 double-precision floats. This means operations like 0.1 + 0.2 return 0.30000000000000004. In invoice generation, this behavior accumulates discrepancies. To fix this, we created a utility function, parseMoneyToCents, which strips non-numeric symbols, converts values to floats, and immediately rounds them to integer cents or paise. All calculations (subtotals, tax percentages, and final balances) are executed on these integers, converting them back to decimals only during final string formatting.

2. WeasyPrint Print Alignment

Server-side HTML-to-PDF converters often struggle to translate complex CSS grids and flexbox rules into pages. Standard browsers support modern layout engines, but WeasyPrint has a custom CSS renderer. We resolved this by refactoring the CSS template used in the print preview window, switching from advanced flexbox configurations to traditional table layouts and explicit page break instructions (page-break-inside: avoid).

3. Server-Side Cold Starts

Because the backend is hosted on a free Render tier, the service falls asleep after periods of inactivity. This caused a 30-second delay when a user clicked "Generate PDF". We resolved this by implementing an active visibility observer in the frontend that pings the Render server when the tab becomes active, waking the API container while the user is still filling out their business details.


Accomplishments that I'm proud of

  • Zero-Plaintext Storage: Designing a flow where business details are saved locally, emails are one-way hashed, and invoice payloads are stored as AES ciphertext. Even in the event of a total database breach, the attacker cannot read invoice contents or extract client emails.
  • Performance Optimization: The entire frontend is written in vanilla code, allowing it to load in milliseconds, feel smooth with transitions, and handle dynamic previews on both mobile and desktop.
  • No-Friction Design: The application requires no sign-up or verification. Users open the site, build their invoice, download their PDF, and retrieve a temporary token to share with clients.

What I learned

  • Client-Side Image Manipulation: Using browser canvas contexts to crop and compress user-submitted logos in-memory, avoiding the need to process raw heavy images on the server.
  • Cryptographic Signing Patterns: Designing security signatures using HMAC-SHA256, ensuring that the database records cannot be silently modified by unauthorized actors.
  • CSS Page Paged Media Module: Working with CSS print directives (@media print, @page) to control margins, letter formatting, and print-ready typography.

What's next for An Invoice Generator

For future updates to RupaX, we plan to implement:

  • Local WebAssembly (WASM) PDF Generation: Bringing PDF generation entirely client-side using tools like pdf-lib or a compiled version of WeasyPrint. This would allow RupaX to operate 100% offline, removing backend dependencies entirely.
  • Client-Side History Dashboard: Using IndexedDB to store a searchable history of previous invoices directly in the user's browser, enabling full record management without external databases.
  • Payment Integration Links: Adding a feature that generates UPI QR codes (for Indian merchants) or custom Stripe Payment Links directly inside the invoice layout, allowing clients to pay instantly upon viewing the document.

Built With

Share this project:

Updates