DEV Community

Cover image for Building a Free Quote Generator With No Backend (PDF Generated in the Browser)
Palks Studio
Palks Studio

Posted on

Building a Free Quote Generator With No Backend (PDF Generated in the Browser)

Creating a quote should be simple.

Yet most tools require:

  • account creation
  • email registration
  • server-side storage
  • sometimes even a subscription.

I wanted to try a different approach.

A quote generator that runs entirely in the browser.

No backend.

No API.

No database.

You can test it here:

https://palks-studio.com/fr/generateur-devis

The tool generates a professional PDF quote directly in the browser without sending any data to a server.


The Core Idea

Everything happens client-side.

User fills the form



JavaScript processes the data



PDF is generated locally



Browser downloads the file

No network request is required.

The only external dependency is the jsPDF library.


Loading the PDF Library

The generator relies on jsPDF to build the document directly in JavaScript.

<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
Enter fullscreen mode Exit fullscreen mode

Once loaded, creating a PDF is straightforward.

const { jsPDF } = window.jspdf;

const doc = new jsPDF({
  unit: "mm",
  format: "a4"
});
Enter fullscreen mode Exit fullscreen mode

From there, everything can be drawn directly into the document.


Structuring the Quote Form

The form mirrors a real quote structure.

It contains:

  • issuer information
  • client information
  • quote metadata
  • service lines
  • totals
  • payment details

Example structure:

<div class="card">

  <div class="card-header">
    <div class="card-header-title">Your company</div>
  </div>

  <div class="card-body">
    <input name="issuer_name" required>
    <input name="issuer_email">
    <input name="issuer_phone">
  </div>

</div>
Enter fullscreen mode Exit fullscreen mode

Each section of the form maps directly to a block inside the generated PDF.


Dynamically Adding Quote Lines

Quotes require flexible service lines.

Users can dynamically add or remove rows.

function addLine() {

  lineCount++;

  const row = document.createElement("div");
  row.className = "line-row";

  row.innerHTML = `
    <input name="lines[${lineCount}][desc]">
    <input name="lines[${lineCount}][qty]" type="number">
    <input name="lines[${lineCount}][price]" type="number">
  `;

  container.appendChild(row);

}
Enter fullscreen mode Exit fullscreen mode

Each line contains:

  • description
  • quantity
  • unit price
  • VAT rate

Totals update instantly when values change.


Calculating Totals in Real Time

All calculations are transparent and client-side.

function updateTotals() {

  let subtotal = 0;
  let vatTotal = 0;

  document.querySelectorAll(".line-row").forEach(row => {

    const qty   = parseFloat(row.querySelector('[name*="[qty]"]').value) || 0;
    const price = parseFloat(row.querySelector('[name*="[price]"]').value) || 0;
    const vat   = parseFloat(row.querySelector('[name*="[tva]"]').value) || 0;

    const lineHT = qty * price;

    subtotal += lineHT;
    vatTotal += lineHT * vat / 100;

  });

  const total = subtotal + vatTotal;

}
Enter fullscreen mode Exit fullscreen mode

The UI immediately displays:

  • Subtotal
  • VAT
  • Total amount

before the PDF is generated.


Generating the PDF

When the user confirms, the script builds the document.

const { jsPDF } = window.jspdf;

const doc = new jsPDF({
  unit: "mm",
  format: "a4"
});
Enter fullscreen mode Exit fullscreen mode

Then the script draws the document:

  • header
  • issuer block
  • client block
  • service table
  • totals
  • notes
  • footer

Example:

doc.text("QUOTE", 18, 30);
doc.text(quoteNumber, 18, 38);
Enter fullscreen mode Exit fullscreen mode

Every field comes directly from the form inputs.


Handling Dynamic Content Heights

PDF layout can break when text becomes longer than expected.

To prevent layout issues, the generator wraps text dynamically.

doc.splitTextToSize(text, maxWidth);
Enter fullscreen mode Exit fullscreen mode

Each block calculates its own height before being drawn.

This prevents overlapping elements and keeps the layout stable.


Why Avoid a Backend?

For this type of tool, a backend is often unnecessary.

Running everything in the browser provides several advantages.

Privacy.

No data is transmitted to any server.

Simplicity.

No authentication, no database, no API.

Lightweight hosting.

The entire generator is essentially a single HTML page.

It can run on:

  • static hosting
  • GitHub Pages
  • any simple web server

Limitations

This approach also has some limitations.

There is no:

  • quote history
  • client management
  • automated emailing
  • electronic signature workflow

But for generating quick quotes, it works extremely well.


Design Goals

The goal was not to build a SaaS product.

The goal was to build a tool that is:

  • simple
  • frictionless
  • immediately usable

No login.

No tracking.

No data collection.

Just a form and a downloadable PDF.


Try the Generator

You can test it here:

https://palks-studio.com/fr/generateur-devis

It works on:

  • desktop
  • mobile
  • any modern browser

Final Thoughts

Modern web tools often become unnecessarily complex.

For some use cases, a simple client-side application is more than enough.

A single HTML file with JavaScript can already provide:

  • a structured form
  • dynamic calculations
  • professional PDF generation

Sometimes simplicity is the best solution.

Top comments (0)