DEV Community

Jeffrey Desenfans
Jeffrey Desenfans

Posted on

How I Built a 100% Client-Side PDF CMYK & Bleed Checker with Next.js (Zero Server Uploads)

**When graphic designers prep files for commercial printing, they face a recurring nightmare: RGB color shifts, missing 3mm bleeds, and un-embedded fonts ruining a physical print run.

Most preflight tools rely on expensive desktop suites like Adobe Acrobat Pro or online converters that force users to upload confidential client artwork to remote servers.

I decided to solve this by building PDF Print Checker—a lightweight Next.js web application that performs complete PDF inspection 100% inside the user's browser.

Here is a breakdown of how the client-side architecture works and why handling binary PDF parsing in JavaScript is easier than it sounds.**


Why Process PDFs Entirely Client-Side?

Moving heavy file processing from backend servers into the user's browser solves three major development hurdles:

  • Zero Infrastructure Costs: Parsing 100MB+ vector files on Node servers burns memory and inflates AWS/Vercel serverless billings.
  • 100% Privacy by Design: Client artwork never leaves the browser local memory, eliminating GDPR and data compliance headaches.
  • Instant Speed: Eliminating file upload latency gives users immediate feedback.

The Technical Architecture

  • Framework: Next.js (App Router, static landing pages)
  • Parsing Engine: pdfjs-dist (Mozilla's PDF.js library for low-level stream inspection)
  • Styling: Tailwind CSS + Glassmorphism UI
  • Hosting: Vercel Edge

Key Preflight Checks Implemented

1. Color Space Extraction (CMYK vs. RGB)

Rather than rasterizing the entire PDF into bitmap images, the app inspects the raw stream operators (CS, cs, DeviceRGB, DeviceCMYK, ICCBased). This lets us catch vector shapes or raster assets using RGB profiles without melting the user's CPU.

2. Bleed Area Verification (MediaBox vs. TrimBox)

PDF spec definitions rely on distinct page boundaries:

  • MediaBox: The physical page size.
  • TrimBox: The intended size of the finished printed product.

By calculating the delta between the MediaBox and TrimBox coordinate arrays, we determine if the required 3mm bleed margin is present:


javascript
// Extracting TrimBox vs MediaBox difference in points
const mediaBox = page.view; // [x1, y1, x2, y2]
const trimBox = page.trimBox || mediaBox;

const bleedLeftPoints = Math.abs(trimBox[0] - mediaBox[0]); 
const bleedLeftMm = bleedLeftPoints * 0.352778; // Convert points (1/72 inch) to mm

const hasValidBleed = bleedLeftMm >= 3.0;
Enter fullscreen mode Exit fullscreen mode

Top comments (1)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.