Skip to main contentSkip to main content
Index:
11
Sector:
Print & Design
Type:
Bespoke software
Year:
2025
Our own product · Print & Design

Print Calculator & CRM

Our own tool: a pricing engine, quote builder and sales CRM for print businesses, built first for our own studio. Print quotes depend on paper, ink, imposition, setup fees, markup and VAT, and most shops manage that in spreadsheets, so underquoting eats margin. We built a single guided workflow that prices a job, sends a polished quote by email and tracks it through the pipeline, with no running cost.Accurate pricing, polished quotes, and full sales pipeline visibility, with zero infrastructure cost.

Read it your way. You are reading the plain-English version. Flip to Technical for how it is built.You are reading the technical version: architecture, integrations and engineering detail.

Glasgow GFX / Print Calculator & CRM / Sheet 01
Our own product / Glasgow / 2025

Price it. Quote it. Win it.

Cyan
100%
Magenta
100%
Yellow
100%
Key
100%

Our own pricing engine, quote builder and sales pipeline for print shops. A job is priced and quoted in about two minutes, it costs nothing a month to run, and every client record stays on your own computer.

A fully client-side Next.js 16 app: a pure pricing function over a pre-configured rate card, React Hook Form and Zod on every input, Zustand persisted to localStorage, HTML quote emails through Resend, shipped as a static export with no backend.

Running cost
£0/mo
Quote turnaround
~2 min
Client data privacy
100%
Sales pipeline stages
5
01 / The brief

Plate Key

Eight variables. One price.

Pricing print looks simple until you try it. One quote depends on the paper, its weight, the ink, what your printer can take, how many fit on a sheet, the setup, your markup and VAT. Most shops juggle all that in spreadsheets and gut feel, and every slip comes straight off the margin.Print pricing is deceptively complex. A single quote depends on paper type, weight, ink costs, printer capabilities, imposition layouts, setup fees, markup strategy, and VAT, variables that most print shops manage through spreadsheets, gut feel, or outdated software. Quoting errors eat directly into margins. Manual follow-ups fall through the cracks. Most off-the-shelf solutions demand monthly subscriptions, cloud accounts, and onboarding overhead that small print businesses neither need nor want.
  1. Var 01

    Paper type

    Silk, gloss, kraft or pearl

    stock.perM2 × sheet m²

  2. Var 02

    Weight

    Will it even go through the printer?

    stock.gsm ∈ printer.gsm

  3. Var 03

    Ink

    Draft, standard or high quality

    INK_PER_M2[quality] × sides

  4. Var 04

    Printer

    Which machine can run the job

    printerFor(size, stock)

  5. Var 05

    Imposition

    How many fit on one sheet

    ⌊aw ÷ iw⌋ × ⌊ah ÷ ih⌋, both ways round

  6. Var 06

    Setup

    Getting the press ready, plus spoiled sheets

    printer.makeReady + overs

  7. Var 07

    Markup

    Your margin, set per product

    cost × markup[product]

  8. Var 08

    VAT

    20%, or zero for leaflets

    net × vat[product]

Before: the spreadsheet
After: one docket
  • One guided flow prices the job, line by line
  • Imposition and ink costed every time, so no more underquoting
  • Every quote tracked through five stages to payment
  • Nothing to pay monthly and nothing to sign up to
02 / Price a job

Plate Cyan

Every penny shows its working.

Pick a product, a size and a paper, set the quantity and the finish, and the price builds itself line by line: paper, ink, setup, finishing, your margin and VAT. It even knows when a paper is too heavy for the printer. Try it. These are sample rates, but the sums are the real ones.Each control dispatches a partial job into a reducer that normalises it (valid size, finish and quantity for the product, and a stock some printer accepts at that size) and passes it to a pure priceJob(). Imposition tries both orientations with bleed and gripper; overs add a fixed make-ready allowance plus 2% running waste; money is integer pence end to end.
Product
Size
Paper stock
Quantity

250 business cards

12.1p each

1002505001k2.5k5k
Printed sides
Print quality
Finish

12.1p each / 250 business cards

£30.35

Job docket

No. Q-0412

Sample rates

250 business cards, Standard 85 × 55 mm, 350gsm silk, double sided

Standard print / Digital press

Paper
£2.27
Ink
£1.04
Setup
£10.00
Finishing
£0.00
Margin 90%
£11.98
VAT 20%
£5.06

Total inc VAT

£30.35

12.1p each / 250 business cards

Up on sheet
21
SRA3
15 sheets
Inc. overs
3

Price each, by quantity

1002505001k2.5k5k

Quote follows this job

Sample rates for illustration. The real app ships with real paper stocks, printers and products set up, and every rate is the shop's own to change.

The pricing function (simplified)
type Job = {
  product: ProductId; size: SizeId; stock: StockId;
  qty: number; sides: 1 | 2;
  quality: 'draft' | 'standard' | 'high';
  finish: FinishId;
};

type PriceResult =
  | { ok: true; parts: Record<Segment, Pence>; total: Pence;
      printer: Printer; layout: Imposition; sheets: number }
  | { ok: false; reason: string }; // e.g. 350gsm will not feed

// Pure: no I/O, no clock, no network. Rates come from the
// pre-configured rate card; whole pence throughout.
export function priceJob(job: Job): PriceResult;
priceJob(job), worked
sheets    = ceil(250 ÷ 21) + 3 overs               15
paper     = 15 × 0.144 m² × 105p                   £2.27
ink       = 15 × 2 × 0.144 m² × 24p × 1            £1.04
setup     = Digital press make-ready               £10.00
finishing = none                                   £0.00
margin    = £13.31 × 90%                           £11.98
vat       = £25.29 × 20%                           £5.06
total     =                                        £30.35

Recalculated 0 times this visit / 0 network requests / no loading state

Change anything and the price is worked out again before your finger leaves the button. Nothing is sent anywhere to do it: the sums happen right here on the page, the same way they do in the shop's app.

03 / Send the quote

Plate Magenta

One click from price to inbox.

The job you just priced is already a quote. Add a name and an email, write a short note, and it goes out looking like it came from a proper print shop, with a matching version ready to print or save. Add more jobs from the docket and they become extra lines on the same quote.Quotes are assembled line by line from priced jobs, validated with React Hook Form and a Zod schema, and rendered as an HTML email delivered through Resend, with a PDF-ready layout built from the same line data. Below: the schema, the template and the exact payload this form would hand to the email service.
On this quote
  • 250 business cards, Standard 85 × 55 mm, 350gsm silk, double sided£30.35 / follows the calculator

88 / 280

Valid for

£30.35

From
Your Print Shop <quotes@print-shop.example>
To
Ailsa Grant <ailsa@example.com>
Subject
Your print quote Q-0412: £30.35 inc VAT
Your Print ShopQ-0412

Hi Ailsa,

Thanks for getting in touch. Here is the price we talked about, printed here in Glasgow.

Quote lines
ItemNet
01250 business cards, Standard 85 × 55 mm, 350gsm silk, double sided£25.29
Net
£25.29
VAT
£5.06
Total
£30.35
Accept this quoteValid for 30 days

Sample client and rates. The real app sends this as a formatted email, with a matching PDF-ready layout for offline sharing.

Quote form: React Hook Form + Zod (simplified)
const quoteForm = z.object({
  name: z.string().trim().min(2, 'Add the client’s name'),
  email: z.string().trim().email('Enter a valid email address'),
  note: z.string().max(280).optional(),
  validDays: z.union([z.literal(14), z.literal(30)]),
});

const form = useForm<QuoteForm>({ resolver: zodResolver(quoteForm) });
Quote email template (simplified)
export function QuoteEmail({ quote, shop }: Props) {
  return (
    <Html><Preview>{quote.ref}: {gbp(quote.total)} inc VAT</Preview>
      <Body style={paper}>
        <Letterhead shop={shop} />
        <Text>Hi {quote.client.name},</Text>
        <Text>{quote.note}</Text>
        <LineTable lines={quote.lines} />   {/* same rows as the PDF */}
        <Totals net={quote.net} vat={quote.vat} total={quote.total} />
        <Button href={acceptUrl(quote)}>Accept this quote</Button>
        <Text>Valid for {quote.validDays} days.</Text>
      </Body>
    </Html>
  );
}
The payload for Resend, live from this form
{
  "from": "Your Print Shop <quotes@print-shop.example>",
  "to": "ailsa@example.com",
  "subject": "Your print quote Q-0412: £30.35 inc VAT",
  "react": "<QuoteEmail ref=\"Q-0412\" lines={1} validDays={30} />",
  "tags": [
    {
      "name": "quote",
      "value": "Q-0412"
    },
    {
      "name": "lines",
      "value": "1"
    }
  ]
}
04 / The pipeline

Plate Yellow

Five stages. Nothing forgotten.

Every job moves through the same five stages, from first enquiry to paid and done. Drag a card along, or use its arrows, and watch the totals change: what is in play, how many quotes you win, which deposits have come in and what is still owed. The quote you send above lands under Quoted.Deals move between enquiry, quoted, accepted, deposit paid and completed. Payment state is derived from the stage (nothing, a 50% deposit, or the full balance), and stage totals, win rate, average order and outstanding balance are computed from the deal list rather than stored, so they can never drift.
Open pipeline
£391.77
Win rate
67%
Average order
£113.60
Deposits held
£16.03
Still to collect
£171.96

01 Enquiry2

£105.14

  • Morag’s Bakehouse

    Flyers, 1,000: 1,000 flyers, A5 148 × 210 mm, 170gsm gloss, double sided

    £71.06

  • The Wee Gig Night

    Posters, 25: 25 posters, A2 420 × 594 mm, 200gsm poster satin, single sided

    £34.08

02 Quoted2

£98.64

  • Studio Ishbel

    Business cards, 250: 250 business cards, Standard 85 × 55 mm, 300gsm pearlescent, double sided, soft-touch lamination

    £59.17

  • Calum Reid Joinery

    Business cards, 500: 500 business cards, Standard 85 × 55 mm, 400gsm uncoated board, double sided

    £39.47

03 Accepted1

£155.94

  • Leaf & Loaf Café

    Folded leaflets, 1,000: 1,000 folded leaflets, A4 flat 210 × 297 mm, 120gsm recycled uncoated, double sided, roll fold to dl

    £155.94

    Awaiting 50% deposit

04 Deposit paid1

£32.05

  • Glenview Running Club

    Posters, 50: 50 posters, A3 297 × 420 mm, 170gsm gloss, single sided

    £32.05

    £16.03 paid / £16.02 due

05 Completed2

£266.42

  • Northside Florist

    Business cards, 1,000: 1,000 business cards, Standard 85 × 55 mm, 300gsm kraft, double sided, round corners

    £69.56

  • Hanna Lind Photography

    Flyers, 2,500: 2,500 flyers, A6 105 × 148 mm, 350gsm silk, double sided, matt lamination

    £196.86

Sample clients and jobs, invented for illustration and priced by the sample rates above. Deposits are taken at half the quote.

Pipeline store (simplified)
// A Zustand slice, persisted with the rest of the store
moveDeal: (id: DealId, to: StageId) =>
  set((s) => ({
    deals: s.deals.map((d) =>
      d.id === id ? { ...d, stage: to, paid: paidAt(d, to) } : d
    ),
  })),

// paidAt: nothing until Deposit paid, then 50%, then the lot.
// Derived, never stored: stage totals, win rate, outstanding.
const stats = useStore(useShallow((s) => pipelineStats(s.deals)));
05 / Your data stays here

Plate Key

It never leaves the building.

Most business software keeps your customers on someone else's computer and charges you every month for it. This keeps everything on yours. Flip the switch to see where a client's details usually travel, and what that costs.Fully client-side: Zustand with localStorage for state, a static export for delivery, no database, no backend and no auth surface. The same pattern runs on this page: your demo session is persisted to this browser and offered back on reload.
Your browser, on your computer
Kept here, and only here
  • Client records8
  • Quotes6
  • Pipeline stages5
  • Vendor’s cloud database: never receives your data
  • Vendor backups: never receives your data
  • Login provider: never receives your data
  • Product analytics: never receives your data
  • Your client’s inbox, when you send: your client data goes here
Monthly bill, two people

£0

No hosting, no database, no subscription

Over a year

£0

Runs from any web host

On this device, right now

Nothing yet. Price a job or move a card above and it is saved here, in this browser only. Reload the page and it will offer it back.

The subscription side is an illustration of the usual model, not a named product. The right-hand panel is real: this page saves your demo in your own browser and nowhere else.

There is no account to make and no password to forget. Your client list, quotes and pipeline sit on the computer you use, so they are yours, and the only thing that ever leaves is the quote you choose to email.

Persistence and export (simplified)
// The store
export const useStore = create<State>()(
  persist(
    (...a) => ({ ...pricingSlice(...a), ...quoteSlice(...a), ...pipelineSlice(...a) }),
    { name: 'print-calculator', storage: createJSONStorage(() => localStorage) }
  )
);

// next.config.ts
export default { output: 'export' }; // plain HTML, CSS and JS: any host, no server

State lives in one Zustand store persisted to localStorage, so there is no database, no auth and no API to secure. The build is a static export: HTML, CSS and JS on any host, which is why the running cost is £0.

The only outbound call in normal use is the quote email through Resend. Pricing, quoting and the pipeline make no network requests at all, which is also why every recalculation is instant.

This demo reads its own save back through a version check and per-record validation in parseSession(): anything malformed is dropped, never trusted.

Results
£0/mo
Running cost
~2 min
Quote turnaround
100%
Client data privacy
5
Sales pipeline stages
  • 01Prices came out right from day one: the sheet layouts and ink costs are worked out every time, so each job is priced from its real costsQuoting accuracy improved immediately, imposition calculations and ink cost modelling eliminated the margin erosion caused by underquoting
  • 02A quote that used to take hours of checking spreadsheets now takes a couple of minutes, step by stepQuote turnaround cut from hours to minutes, what previously required cross-referencing spreadsheets is now a guided workflow
  • 03For the first time the whole sales picture is on one screen: how many quotes turn into jobs, which deposits are still owed, and what is coming inFull pipeline visibility for the first time, conversion rates, outstanding deposits, and revenue at a glance
  • 04Nothing to pay to keep it running: no hosting bill, no database and no monthly subscriptionZero infrastructure cost, no database, no hosting backend, no recurring SaaS fees
  • 05Useful from the first time it opens, already set up with real papers, printers and products, so there is nothing to learn firstProductive from the first launch, pre-configured with real industry defaults, zero onboarding required
Start a project like this

Need software built for your business?

We build software like this for clients too. Tell us what your business needs to run on, and we will come back with a fixed written quote after a short discovery call.

Bespoke software from £10,000

Prices, timelines and what is included: Bespoke software development in Glasgow.

Start a project like thisCall 0141 345 5841

Studio: Unit 204b, 36-38 Washington Street, Glasgow G3 8AZ. Phone 0141 345 5841.

Spec sheet

The architecture, integrations, performance numbers and code standards behind this project live in the technical version, for whoever looks after your IT.

Spec Sheet

Accurate pricing, polished quotes, and full sales pipeline visibility, with zero infrastructure cost.

Architecture
Framework
Next.js 16 with React 19 and Turbopack
State & Persistence
Zustand with localStorage, fully client-side, zero backend
Forms
React Hook Form with Zod schema validation for every input
UI System
Radix UI primitives with Tailwind CSS and CVA variants
Deployment
Static export, runs on any hosting, no server required
Integrations
Email Delivery
Resend API for transactional quote emails with HTML templates
Pricing Data
Pre-configured paper stocks, printer profiles, and ink cost tables
VAT Calculation
UK VAT rates applied automatically with configurable exemptions
Performance
Data Privacy
100% client-side, all data stays on the device, never leaves the browser
Infrastructure Cost
£0/month, no database, no backend, no recurring SaaS fees
Startup Time
Productive from first launch, pre-configured with real industry defaults
Calculation Speed
Instant recalculation on every input change, no loading states
Code Quality
  • →TypeScript strict mode with noUncheckedIndexedAccess
  • →Zod validation on every form and calculation input
  • →Immutable state updates via Zustand
  • →Component-driven architecture with Radix UI primitives
  • →Accessible markup meeting WCAG 2.1 AA standards
  • →Zero runtime dependencies on external services for core functionality
Technologies
  • Next.js 16
  • TypeScript
  • Tailwind CSS
  • Radix UI
  • Zustand
  • React Hook Form
  • Zod
  • Resend

Questions about Print Calculator & CRM

What is Print Calculator & CRM?

Our own tool: a pricing engine, quote builder and sales CRM for print businesses, built first for our own studio. Print quotes depend on paper, ink, imposition, setup fees, markup and VAT, and most shops manage that in spreadsheets, so underquoting eats margin. We built a single guided workflow that prices a job, sends a polished quote by email and tracks it through the pipeline, with no running cost.

How is it built, in plain terms?

A self-contained web app that stores its data in the browser, so there is no server, no login and no monthly fee.

What does it do for a business?

Quote turnaround cut from hours to roughly two minutes, at no running cost.

How long did the project take?

6 weeks.

How much does bespoke software like this cost?

Bespoke software projects start from £10,000. We reply with a fixed written quote after a short discovery call, so you know the price before any work starts.

Where is Glasgow GFX based?

Our studio is at Unit 204b, 36-38 Washington Street, Glasgow G3 8AZ, and we work with businesses across the UK. Phone 0141 345 5841.

Next Project

Font Creator for Adobe Illustrator

A native Illustrator extension that eliminates the multi-tool font creation workflow, draw letterforms, assign glyphs, and export production-ready OpenType fonts without leaving the app.

Have a project?

Websites, web apps and bespoke software for businesses across the UK, built in Glasgow. Tell us what you need and we will come back with a fixed written quote after a discovery call.

Glasgow GFX Studio

Visit
The Pentagon Business Centre
Unit 204b, 36-38 Washington Street
Glasgow G3 8AZ
Hours
Mon to Fri 9:00 to 18:00
Sat 10:00 to 18:00
Sun closed
Clients
Web and software clients across the UK, from the Washington Street studio in Glasgow.