01
Problem
Service quotes usually die in one of two places: a messy spreadsheet that screams “I’m still figuring this out,” or a PDF that took forty minutes to format and still had the wrong total.
System startup
Case study
Premium service quotation builder with live pricing and PDF export
QuoteLab is a modern quotation generator for polished, client-ready service quotes: interactive service selection, custom line items, live totals, and exportable PDFs—without looking like a spreadsheet that gave up.

Move your cursor — the preview tilts slightly. Real UI capture from production.
Story
Three beats — each locks in before the next. Scroll-driven, but readable as a linear narrative.
01
Service quotes usually die in one of two places: a messy spreadsheet that screams “I’m still figuring this out,” or a PDF that took forty minutes to format and still had the wrong total.
02
The pain isn’t math — it’s trust. People abandon quotes when the tool feels slower than typing a number into chat. The UI has to keep pace with negotiation.
03
QuoteLab is a focused quotation workspace: structured service selection, room for one-off items, and a live summary that stays honest as the quote evolves.
Code → product
One compare: the editor shows the real shape of the pricing module; the layer underneath is the live QuoteLab interface. Hover or drag to sweep from implementation to end result.
// Live totals — same module drives UI + PDF export
import type { Service, SelectedService, PricingLine } from "./types";
export interface PricingSnapshot {
lines: PricingLine[];
subtotal: number;
discount: number;
total: number;
}
function sumLines(lines: PricingLine[]): number {
return lines.reduce((acc, line) => acc + line.amount, 0);
}
export function calculatePricing(
services: Service[],
selected: SelectedService[],
discountCode: string
): PricingSnapshot {
const lines = buildLines(services, selected);
const subtotal = sumLines(lines);
const discount = applyDiscount(subtotal, discountCode);
const total = Math.max(0, subtotal - discount);
return { lines, subtotal, discount, total };
}
Drag the handle — code on the left reveals the live QuoteLab surface underneath.
Scroll narrative
Scroll through this band: the panel stays fixed while you move through three beats. The right column shows abstract slices of the system — not a full-page screenshot.
Step 1
Configure the quote
Currency, discounts, and optional branding load first — so totals stay honest before line items pile on.
Step 2
Compose line items
Catalog picks, custom services, and extras share one pricing model so you’re not maintaining two truths.
Step 3
Preview & export
Live PDF preview and export close the loop: what you see is what gets emailed.
Client & billing
Step 1 of 3 — keep scrolling to advance.
Capabilities
Filter by intent — selection & composition vs. totals, preview, and export.
Interactive service selection
Custom service creation
Extras, discounts, and currency support
Live pricing summary
Quote preview
PDF generation
Responsive UI
Project overview
A quotation workspace that behaves like a product — not a printable accident.
QuoteLab brings together the messy middle of quoting: selectable services, ad-hoc line items, pricing options, and a preview that stays in sync. The focus was product clarity, interaction design, and a frontend that stays calm when the quote gets complicated.
Signals
Counts tied to the actual build: no vanity KPIs, just scope made legible.
0
Shipped capabilities
Selection → preview → PDF
0
Stack anchors
Next.js · React · Tailwind
0
Core jobs
Select · tune · preview · send
Next.js and React for a responsive, component-driven UI; Tailwind CSS for rhythm and theme-friendly styling — clear boundaries between layout, quote state, and export.
Tightened hierarchy so “what am I buying?” beats “where do I click?” — primary actions read as actions; secondary controls stay available without stealing focus.
Reduced cognitive load in the pricing summary: numbers align, deltas are scannable, and empty states explain what to do next instead of punishing you with whitespace.
Responsive layout choices that preserve context: you shouldn’t lose the running total just because you’re on a narrow screen.
The flow is built around feedback: every meaningful change updates totals and the preview, so you’re never guessing what the client will see.
Export isn’t an afterthought — it’s the handshake. PDF output is there when the quote is “good enough to send,” not when you’ve given up and screenshotted the browser.
The demo is the proof — interactive selection, live totals, and export. This page is the pitch; the product is the receipt.
Visit live demo