Uxopian Software Blog

"We Could Build a Document Viewer in a Sprint"

Written by Uxopian | Aug 21, 2026, 9:07:50 AM

“We Could Build a Document Viewer in a Sprint

UX
Uxopian Editorial
ARender Engineering  ·  Uxopian Software

On the spectacular, fractal, occasionally hilarious difficulty of showing people their own documents.

Every year or two, someone in a steering committee says it.

“Why are we paying for a viewing component? There are open-source PDF libraries. One of our developers put a prototype together last week. It’s basically done.”

And to be fair to that person: the prototype probably worked. It opened a PDF — a nice, clean, born-digital PDF, produced that morning by a modern tool, with embedded fonts and no annotations and no signatures and no forms and no rotation and no password and a file size of 400 KB. It rendered beautifully. Everyone nodded. The line item got challenged.

This post is for the people in that meeting — and especially for software vendors: the ECM platforms, the claims systems, the case-management suites, the vertical SaaS products where documents flow through the product but viewing is not the product. Because here is the strategic point hiding under the technical one: a document viewer is not a feature you build. It is a liability you adopt. The day your prototype ships, every strange file your customers have ever archived becomes your roadmap, your on-call rotation, your CVE feed, your regression suite — forever. Your engineers stop building the product customers chose you for, and start debugging Thai word-breaking. You haven't added a feature; you've founded a second company inside your company — a rendering company, with no revenue of its own, competing for your best people. The build-vs-buy question for viewing isn't about whether you can. It's about whether you want to own everything in the list below.

And no — 2026 does not change this. Your AI pair-programmer will scaffold a viewer in an afternoon, and it will be exactly the prototype from the meeting: flawless on the clean, born-digital PDF, blind to the archive. GenAI compresses the first month of this work. It does not compress the twenty years, because the hard part was never writing the code — it's having met the documents. What follows is not generatable knowledge. It is collected evidence.

We recently did something a little masochistic: we opened the specimen cabinet — the collection of misbehaving documents, rendering mysteries and “can you look at this file?” curiosities that twenty years in the field deposit on a rendering team — and classified only four years of it, 2,382 real-world cases, one by one. What kind of document? What kind of problem? What did the user actually see on their screen?

About one in five cases — 518 — was a document fidelity problem: something displayed wrong, incompletely, illegibly, or not at all. And here is the first surprise, the one we'd like every “it's basically done” prototype-builder to sit with for a moment:

The #1 troublemaker was not some exotic legacy format. It was PDF. The “solved” one. Followed — and this is the part nobody expects — by email.

The rest of this post is the list. The liste à la Prévert, as we say in French: the long, absurd, poetic inventory of everything that turned out to be harder than it looked. Not hypotheticals — every single item below is the ghost of at least one real document that landed on a real desk and refused to behave.

So. You can build a content viewer easily?

Have you thought about…

1. The format zoo (or: “we only need PDF and Office” — no you don’t)

Every viewer project starts with the same scoping meeting. “Our users only have PDFs and Word documents.” Six months after go-live, here is what actually walks through the door:

  • PDF — of course. Except “PDF” is not a format, it’s a 1,000-page specification with eight versions, three conformance families (PDF/A, PDF/X, PDF/UA), and thirty years of creative interpretations. More on this below.
  • DOCX, XLSX, PPTX — the modern Office trio. Each one is a ZIP archive of XML files with its own multi-thousand-page specification (OOXML: ~6,000 pages, and yes, people have read them so you don’t have to).
  • DOC, XLS, PPT — the legacy Office trio, which are not XML at all but binary OLE compound files, essentially serialized memory dumps of 1990s Microsoft applications. Still arriving daily in 2026. Banks and insurers have archives full of them, and regulators do not accept “that format is old” as an answer.
  • RTF — invented in 1987, still in production everywhere, and the source of a steady trickle of grief: RTF files that won’t open, RTF pagination that differs from Word, RTF formatting that half-survives.
  • ODT, ODS, ODP — the OpenDocument family, because some administration somewhere standardized on LibreOffice in 2009.
  • MSG and EML — email messages. A format so deceptively deep it gets its own chapter below.
  • TIFF — the darling of scanning departments. Single-page, multi-page, 10,000-page, Group 4 compressed, LZW compressed, striped, tiled, with photometric interpretations that invert black and white if you read one flag wrong.
  • JPEG, PNG, GIF, BMP — easy, right? Wait until someone uploads a 1.2 gigapixel scan.
  • HEIC / HEIF — every photo taken by a recent iPhone. Your claims adjusters’ customers send these by the thousands. Three separate cases in our corpus just about HEIC support.
  • WebP — same story, from the Android side.
  • EPS and PostScript — yes, in 2026. Logistics and engineering never throw anything away.
  • XPS and OXPS — Microsoft’s “PDF killer” that didn’t kill PDF but did colonize a surprising number of Windows print workflows.
  • Visio (VSD/VSDX) — because the network team documented everything in it.
  • CAD formats — the facilities department would like to view the building plans, please.
  • Factur-X / ZUGFeRD — the electronic invoice: a PDF with an embedded XML invoice inside it, where the embedded attachment is legally the real document. Did your prototype surface embedded PDF attachments? Did it even know they were there?
  • HTML files — which are documents too, apparently, and someone wants them paginated for printing.
  • XML files — sometimes raw, sometimes with a stylesheet, sometimes secretly an email export, sometimes secretly a Word document (yes, “Word 2003 XML” is a thing, text/xml mimetype and all).
  • Plain text — surely trivial? Keep reading to the encodings chapter.
  • Video — “can the viewer play the call-center recording next to the claim file?” And then: “can we redact a segment of it?” (Real request.)
  • 7-Zip archives, ZIP files — “the document” is sometimes a container of documents, and users expect to browse into it.
  • Files with no extension, files with the wrong extension, files whose first bytes lie about what they are. Our corpus includes: text files misidentified as emails, a PDF misidentified because of an unexpected MIME header, a file that began with a NUL character and took down the conversion path, and documents that were “converted to the wrong format” because extension, mimetype, and magic bytes each told a different story. You need content-sniffing, and your content-sniffing will have bugs, and those bugs will find users.

Did you know that “what format is this file?” — the very first question your viewer must answer, before rendering a single pixel — is itself hard enough to keep an engineering team permanently busy?

2. PDF, the “solved” format, would like a word

PDF generated more fidelity cases than any other format in our corpus. Not because PDF is bad — because PDF is where everything ends up, and because the real-world PDF population is wilder than any test suite.

Have you thought about…

  • Encrypted PDFs — user passwords, owner passwords, RC4, AES-128, AES-256, and the delightful case of a PDF that is encrypted with an empty password (legal to open silently, but only if you implement that path).
  • Password-protected PDFs that must still be viewable by authorized users through your permission system, without the user ever typing the password.
  • Digitally signed PDFs — where the viewer must not only render the signature appearance, but display validation status, and detect whether the document was modified after signing. One case: “electronically signed PDF unreadable.” Another: “signature validation not shown.” Users treat both as catastrophic, because legally, both are.
  • DocuSign-style signature annotations that exist in a gray zone between form field, annotation, and image — and vanish in naive renderers.
  • PDF forms (AcroForms) — text fields, checkboxes, radio groups, dropdowns, each with appearance streams that may or may not exist, may or may not be up-to-date with the field value, and may need regenerating on the fly. Our corpus: “form data not visible”, “form field content loss”, “form text duplicated”, “form field truncation”, “dropdown content missing.” Five different failure modes for one feature.
  • XFA forms — the other PDF forms technology, where the PDF is just a husk containing an XML application that Adobe deprecated years ago and that government agencies worldwide continue to emit at industrial scale. Five separate XFA cases in our corpus. If your renderer doesn’t speak XFA, the user sees a single page politely telling them to open the document in Adobe Reader. Your users will not find this acceptable.
  • PDFs containing JavaScript — that compute field values, format dates, or (fun!) refuse to display content until executed. “PDF with JavaScript rendering failure” — real case.
  • PDF portfolios — PDFs that are actually containers of other PDFs, with a Flash-era navigation UI. Yes, they still exist. Yes, a customer opened one. Yes, the fonts inside came out distorted.
  • Embedded attachments — invoices inside PDFs (Factur-X), source Word files inside PDFs, evidence files inside court filings. “PDF embedded attachments extraction” — real case.
  • PDFs with embedded .joboptions files — Adobe Distiller settings shipped along inside the document, confusing parsers. We could not have invented this.
  • A PDF that begins with a UTF-8 BOM before the %PDF header — rendered as plain text by the naive detection path. Real case.
  • PDFs where the first page renders completely black. PDFs where every page renders black. PDFs where white overlay rectangles cover the text (someone’s idea of redaction, or a transparency group gone wrong). All real.
  • Blend modes and transparency groups — “highlight blend mode broken”: a highlight annotation that should multiply against the text underneath and instead paints opaque yellow over it, hiding exactly the words it was meant to emphasize.
  • JBIG2 compression — the scanned-document codec so aggressive it once made Xerox copiers silently change digits in numbers. Your renderer must decode it. Correctly.
  • JPEG 2000 — the other exotic codec, standard in medical and archival documents, unsupported by browsers, so guess who has to decode it.
  • CCITT Group 4, LZW, RunLength, ASCII85 — the full 1990s compression museum, all still live in production documents.
  • CMYK JPEGs inside PDFs, with and without Adobe’s inverted-channel quirk. Get this wrong and every scanned page looks like a photo negative.
  • Color spaces — DeviceN, Separation, ICC profiles, spot colors, overprint simulation. A logistics customer’s shipping labels rendered wrong until Separation color spaces were honored.
  • Rotated pages — /Rotate 90, 180, 270, per page, interacting with annotation coordinates, text extraction, and printing. Our corpus: “landscape pages displayed as portrait”, “printed PDF appears upside down”, “image truncated on PDF rotation”, “hyperlinks mixed orientation PDF.” Rotation alone is a family of failure modes.
  • Malformed PDFs that Adobe Acrobat opens anyway. This is the cruelest category. The file violates the spec — broken xref table, wrong stream lengths, objects that lie about their type — but Acrobat’s thirty years of accumulated forgiveness heals it silently. Your viewer either matches that forgiveness, bug for bug, or your customer says: “it works in Acrobat, so the file is fine and your product is broken.” They are not entirely wrong.
  • “Legacy PDF document not rendering” — PDFs produced by tools that died before some of your developers were born, using constructs deprecated four spec versions ago. The archive doesn’t care. The archive is forever.
  • PDF merge and split operations that must preserve bookmarks, annotations, form fields, and signatures — our corpus has “PDF merge output corruption” and “annotations wrongly duplicated on split” to show for it.
  • Duplicate bookmark entries. Broken internal hyperlinks. Hyperlink destinations that point to the right page but the wrong vertical position. Hyperlink borders drawn as ugly black frames (Acrobat hides them; will you?).
  • PDFs that render fine at 100% zoom and fall apart at 400% — “image quality zoom artifacts”, “rendering quality zoom degradation”, “hyperlink text misalignment at zoom.” Zoom is not a free operation.

One PDF library gets you maybe seventy percent of this. The last thirty percent is a decade of fieldwork.

3. Fonts: the eternal war

If document rendering is a war, fonts are the trenches. Nothing — nothing — produces more subtle, maddening, “it’s just slightly wrong” defects.

Did you know…

  • A missing font can crash a renderer outright? Not “substitute and warn” — crash. Real case: “missing fonts crash renderer.”
  • Fonts inside DOCX files are obfuscated? Embedded fonts in Word documents (ODTTF) are XOR-scrambled with a GUID-derived key. You have to de-obfuscate them before parsing. This is documented almost nowhere.
  • Fonts inside PDFs are usually subsetted — only the glyphs actually used are present, with scrambled glyph IDs and a name like BCDEFG+Arial. Text extraction from a subsetted font with a missing or lying ToUnicode table is archaeology, not parsing.
  • Font substitution changes the geometry of everything. Substitute Arial with a font 3% wider and a paragraph that fit on one line now wraps; the wrap pushes a heading to the next page; the heading drags a table with it; the table splits; page 7 becomes page 9. The complaint will not say “your font metrics are off by 3%.” It will say “the document is broken.”
  • Calibri’s line height is not what most people think it is. A font carries three different sets of vertical metrics (hhea, OS/2 typo, OS/2 win), a flag that says which to prefer, and applications that ignore the flag differently. We once traced a whole family of pagination drift to a single misread metric table: real Calibri advances 12pt text by 14.65pt per line, and if you believe the other table in the font, you get 14.0pt — and every fiftieth document paginates differently. One misread constant, buried in a binary table, drifting entire archives.
  • Wingdings is load-bearing. Word checkboxes are frequently the characters ☐/☒ rendered in Wingdings or Wingdings 2. No Wingdings glyph mapping → “the checked boxes in our contract all disappeared.” Two separate cases: “checkbox renders as wrong character”, “checkbox wingdings glyph.” In a signed contract, an invisible checkbox is not cosmetic. It is the deal.
  • Customers use barcode fonts. The invoice number is printed in Code 128 — as text, in a font that draws bars. No font → no barcode → the warehouse scanner has nothing to scan. Real case: “custom barcode font not rendering.”
  • The document that renders fine on your Windows dev machine and breaks on the RHEL 8 server — because the Windows box silently supplied Times New Roman from the OS and the Linux box has no fonts at all. Two cases: “windows system font loading”, “images not rendering on RHEL 8.”
  • Thai doesn’t put spaces between words — so line breaking requires a dictionary. Three separate Thai cases in our corpus: characters missing, characters not appearing in PDF output, and words broken at the wrong place.
  • CJK text needs its own font universe — gigabytes of glyphs, Han unification politics (the same Unicode codepoint should look different in Japanese vs Chinese context), vertical writing modes. Seen in the wild: “Chinese text not rendering”, “Korean character display error”, “CJK text missing in preview”, “email Korean character encoding.”
  • Arabic and Hebrew run right-to-left — but the numbers inside them run left-to-right, and a parenthesis must mirror, and the same letter takes four different shapes depending on its neighbors. Bidirectional layout is a Unicode algorithm with 61 rules. You implement all of them or you scramble someone’s contract.
  • Ligatures, kerning pairs, combining diacritics, zero-width joiners, emoji — yes, emoji, in professional documents: “emoji rendering in email messages” is a real case, because customer-service emails are documents too, and 😊 is evidence.

4. Word documents: pagination is an opinion

Here is the dirty secret of every “convert DOCX to PDF” feature: a Word document does not contain pages. It contains a stream of content and a set of rules, and the pages are computed — by an engine, with opinions. Word has opinions. LibreOffice has different opinions. Your renderer will have a third set of opinions. The customer has a printed copy from 2019 and would like all three of you to match it.

Have you thought about…

  • Fields{ PAGE }, { NUMPAGES }, { DATE }, { IF }, { MERGEFIELD }, { TOC } — a full macro language hiding in the text stream. A date field that re-evaluates at render time shows today’s date on an archived contract. Is that fidelity, or is that evidence-tampering? (Real case: “date field shows wrong date.” The customer had strong feelings.)
  • The Table of Contents — a field that renders page numbers, which depend on pagination, which you are computing yourself, which means your TOC is a fixed-point iteration: lay out the document, fill the TOC, which changes its own length, which shifts every page after it, which invalidates the numbers you just wrote…
  • Section breaks — continuous, next-page, even-page, odd-page — each carrying its own page size, orientation, margins, columns, and header/footer set. We recently dissected a real market-reform contract containing 60 sections in a single document. Sixty. Each a chance to break pagination.
  • Headers and footers — first-page variant, even/odd variants, inherited across sections unless overridden, containing page fields, images, tables, and — why not — floating text boxes anchored into the body.
  • Floating objects — images and text boxes anchored to a paragraph but positioned on the page, with seven wrapping modes, that can push text, be pushed, overlap, or float behind the text. The interaction between floats and pagination is where renderer engineers go quiet and stare into the distance.
  • Tables — nested tables, merged cells (both directions), cells that split across pages, header rows that repeat on every page, “keep with next” rows, floating tables that text wraps around, and tables sized by an algorithm so underdocumented that Word’s own behavior was reverse-engineered by the LibreOffice team over years. One of our own hardest bugs: a two-page quote letter whose second table exploded into chaos because of the interaction between conditional IF fields and table column widths.
  • Numbering — multilevel lists with inheritance, overrides, restarts, legal numbering, and the eternal “list numbering restarted at 1 in the middle of my contract” complaint (“word numbering inconsistency” — real).
  • Track changes — a document that is simultaneously two documents (with and without revisions), and the viewer must pick one, or show both, and one specimen in our corpus is simply: “track changes prevent rendering.”
  • Comments and their threads — which one customer discovered were not in the PDF export (“word comments not exported”) — a compliance problem, because the comments were part of the review record.
  • Content controls, form fields, legacy form fields, and ActiveX — three generations of “fill this in” technology, all still circulating: “word form content missing”, “word form fields and boxes.”
  • Macro-enabled documents (DOCM) where the text you must render was generated by the macro — “macro-generated text invisible.” Now your viewer has an opinion about executing VBA. (The correct opinion is “no.” The customer’s opinion is “but the text is missing.”)
  • Blank table pages — a Word document whose empty tables generated entire phantom blank pages in the rendition. Real case.
  • Margin collapsing between paragraphs — did you know Word and LibreOffice disagree about when spacing-before and spacing-after merge at heading transitions, and getting it wrong moves a page break, and moving a page break is always, always noticed?
  • The page-count arms race: “page count mismatch in DOCX”, “incomplete office pagination”, “word pagination and spacing”, “docx content removal and pagination” — four cases, one truth: your page 12 is not their page 12, and someone’s audit trail references page 12.

5. Excel: an infinite canvas cosplaying as paper

A spreadsheet is not a document. It is a surface — potentially 16,384 columns by 1,048,576 rows — and the moment a user clicks “view,” you must invent its pagination out of thin air, exactly the way Excel would have. Excel’s way is deranged. You must be identically deranged.

Did you know…

  • Formulas are not values. The file stores =VLOOKUP(...) and maybe a cached result. If the cache is stale or absent, you either implement a formula engine (there are ~500 functions) or you display wrong numbers. Real case: “excel formula display not evaluated.”
  • What you see depends on who’s asking: hidden columns, hidden sheets, filtered rows, conditional formatting that colors cells by value — one case was literally “excel conditional rendering by user.” And the search feature found text in hidden columns, which users experienced as the viewer hallucinating (“excel search hidden columns”).
  • Number formatting is a locale minefield: currency symbols, thousands separators, dates. #,##0.00 € vs $#,##0.00; 01/02/2026 meaning January 2nd or February 1st depending on which side of the Atlantic the viewer server thinks it’s on. In the wild: “excel cell currency formatting”, “date format in excel”, “spreadsheet number formatting incorrect.”
  • Dates are floating-point day counts since December 30, 1899 — except Excel deliberately believes 1900 was a leap year (a Lotus 1-2-3 compatibility bug, preserved for forty years), except the workbook might use the 1904 epoch because it was created on a Mac.
  • Column pagination is its own science: wide sheets must split across page columns, repeat frozen panes, respect manual page breaks and print areas and fit-to-width scaling. Our corpus: “excel column pagination”, “excel multipage column layout”, “excel spreadsheet column page scaling”, “excel wide columns zoom scaling”, “xlsx wide columns not rendering” — five cases, one feature.
  • Charts — a whole grammar of pies, bars, scatter plots, and pivot charts that must be re-rendered from data, in the right colors, with the right fonts. “Excel formatting and chart display” — real.
  • The multi-sheet problem — “excel multiple sheets not rendering”, “missing excel sheets”, “missing excel sheet content”: is a workbook one document or twelve? Users want it to be whichever they need at that moment.
  • XLS 97-2003 is a binary format (BIFF8) with formula bytecode and its own string table, and a “large Excel 97-2003 file” broke the viewer in a way XLSX never did. The past never dies. It keeps uploading.

6. PowerPoint: the format where nothing is where it says it is

Only two PPTX cases in our corpus, which sounds like good news until you learn why: presentations are so hard to render that the industry has quietly agreed to hold them to a lower standard. “PPTX layout display issues” and “PPTX rendition anomalies” — two cases, each a small anthology.

Have you thought about…

  • Inheritance five levels deep. A single text box’s font color can be defined on the run, the paragraph, the shape, the placeholder on the layout, the placeholder on the master, or fall through to the theme — and the correct answer is “the nearest one that exists, walking a chain that spans four XML files.” Every property. Every shape. Every time.
  • The theme is a lookup table for reality. Colors aren’t colors — they’re accent1 with an alpha modulation and a luminance shift applied at reference time. Fonts aren’t fonts — they’re +mj-lt (“major Latin”), resolved through the theme, per script. Render a slide without resolving the theme and you get a beautifully laid-out wireframe of the wrong everything.
  • Placeholders inherit geometry too. A title box with no position of its own sits exactly where the layout’s title sits, unless the layout is silent too, in which case the master decides. Move nothing, and everything is positioned.
  • SmartArt — the org chart is not shapes, it’s a data model plus a layout algorithm you must reimplement (or rasterize the fallback image and pray it was saved).
  • Charts on slides are full embedded spreadsheet-chart hybrids with their own theme resolution. OLE objects are entire foreign documents living inside a shape.
  • Slide dimensions are a suggestion: 4:3, 16:9, custom sizes, and content scaled by two different scaling modes when a deck was converted from one to the other in 2011 — and half the text boxes overflow ever since, in PowerPoint too, and the customer expects your overflow to match PowerPoint’s overflow exactly.
  • Text autofit — PowerPoint shrinks text to fit the shape, iteratively, with font-scale and line-space-reduction steps. Your renderer must converge to the same fixed point or the last bullet vanishes.
  • Animations and builds — a slide where four overlapping paragraphs appear one per click has all four stacked in the static render. What’s the “true” appearance of a slide mid-animation? (Whatever the customer’s printout shows, that’s what.)
  • Gradients, reflections, soft shadows, glow, 3D bevels — the full cosmetic arsenal of corporate slide design, each an hour of demo delight and a month of rendering mathematics. We’ve implemented alpha transforms and reflection effects for shapes; each one moves a fidelity score by a fraction of a percent and someone’s logo from “wrong” to “right.”
  • Speaker notes — part of the document or not? The compliance answer and the presenter’s answer differ, and your export dialog needs both.

Presentations are the one format where every single object is a small negotiation between six layers of inheritance. The miracle isn’t rendering them perfectly. The miracle is that anyone ever has.

7. Email: the format that contains all other formats

Here it is. The sleeper. The second-biggest troublemaker in our entire corpus — 101 cases, ahead of Word, ahead of Excel. Nobody scopes email into their viewer project, and email arrives anyway, because in banks, insurers, and public agencies, emails are records.

An email is not a document. An email is a container of arbitrary documents, wrapped in three decades of encoding history, with no defined visual appearance whatsoever. You are not rendering the email. You are inventing a document that never existed — and the customer will compare your invention to Outlook’s.

Have you thought about…

  • MSG vs EML — one is a binary OLE compound document (like DOC), the other is MIME text. Same email, two encodings, two parsers, two bug surfaces.
  • The body triple: an email can carry plain-text, HTML, and RTF bodies simultaneously — and Outlook’s RTF body can itself contain encapsulated HTML (search for “RTF-to-HTML de-encapsulation” and despair). Pick the wrong body and the customer sees a different email than Outlook shows.
  • winmail.dat — Outlook sometimes wraps ALL attachments inside a single proprietary TNEF blob. Users don’t see “TNEF.” They see “the attachments are gone.”
  • Inline images — referenced by cid: from the HTML, stored as MIME parts, except when they’re linked from a remote URL (load it? privacy leak. Don’t? “images from urls missing in output” — real case), except when the image is attached and inline and must not appear twice.
  • Header encoding=?UTF-8?B?...?= — RFC 2047 encoded-words, splittable mid-character across header folds. In the wild: “email subject special characters”, “email subject extra characters.”
  • Header localization — should “From/To/Subject” render as “De/À/Objet” for a French user? Our corpus contains seven distinct cases about the language of email headers, including the magnificent “msg headers always in French.” Somewhere, a Dutch compliance officer received a French email header block and was not amused. This is a rendering problem now.
  • The timezone of a sent date — displayed in whose timezone? The sender’s? The server’s? The viewer’s? “Email send date rendered wrong” and “email header timezone display” — both real, both someone’s legal deadline.
  • Encodings, plural — KOI8-R Cyrillic, Windows-1256 Arabic, ISO-2022-JP Japanese, all declared (or falsely declared, or undeclared) per MIME part. Corpus: “cyrillic email message rendering failure”, “email korean character encoding”, “email character encoding display” ×2, “multilingual text rendering email.”
  • Pagination of something that has no pages — an email is one infinite scroll; PDF is paper. Where do you cut? “Email truncation on page break”, “email header body pagination split”, “email pagination image sizing”, “email unexpected pagination layout” — four ways of slicing the infinite, all of them wrong for somebody.
  • Signed and encrypted email — S/MIME wraps the whole message in a cryptographic envelope: “signed emails display garbled.”
  • Nested emails — the .eml attached to the .msg attached to the .eml, forwarded four levels deep. “Nested email rendering crash” — of course it was a crash. Recursion always is.
  • Calendar invites, delivery receipts, voting buttons — message classes that aren’t quite emails, arriving through the same pipe.
  • The email whose entire body rendered as a single infinite line. (“Email content renders as single line.”) A missing white-space interpretation, and a claims file becomes a 40,000-character-wide page.

Email is where “just render the document” goes to die.

8. Text files and the encoding abyss

“At least plain text is trivial.” Reader, we have receipts.

  • There is no such thing as plain text. There is text in UTF-8, UTF-16LE, UTF-16BE, with BOM, without BOM, in Windows-1252, in ISO-8859-15 (they differ in exactly eight characters, one of which is €), in IBM EBCDIC export files from mainframes that very much still run your bank.
  • Encoding detection is statistical guessing — and every heuristic has a false positive. Corpus: “txt file character corruption”, “non-latin character display in text files”, “text file character encoding.”
  • Line endings: LF, CRLF, CR, and one glorious case — “line data CR/LF not respected” — where fixed-width mainframe report lines merged into soup.
  • A NUL character in the stream took down file handling entirely (already mentioned, still funny).
  • Apostrophes went missing. Just the apostrophes (“apostrophes missing in display”). A smart-quote codepoint outside the font’s coverage, and every French contraction in the document silently vanished. L’assuré became Lassuré. Lawyers noticed. Lawyers always notice.
  • Accented characters duplicated themselves (“accented character duplication”, “msg accents repeated duplication”) — é became éé through a double-decoding path. Even better: “uppercase bold character duplication in PDF” — only uppercase, only bold. Imagine root-causing that one.

9. Text extraction, search, and OCR: the invisible half of viewing

Users don’t just look at documents. They Ctrl+F them, copy-paste from them, and expect the claims number to be findable in a fax from 2009. The viewer’s invisible output — the text layer — has its own failure ecosystem, and it is nastier than the pixels.

Did you know…

  • A PDF can render its text perfectly and still contain garbage text. Rendering needs glyph shapes; extraction needs the meaning of each glyph, via a ToUnicode table the producing tool was free to omit, truncate, or fill with lies. The page looks pristine; the copy-paste says □□□□□. Corpus: “text extraction missing characters”, “illegible characters in pdf rendering.”
  • Reading order is not paint order. PDF content streams paint text in whatever sequence the producer fancied — right column first, footer in the middle, headline last. Extraction must reconstruct reading order geometrically. Multi-column layouts, tables, and marginalia all fight you.
  • Spaces are optional. Many PDFs never emit a space character — words are just glyphs positioned apart. You infer word breaks from gap widths, with thresholds, and thresholds have edge cases: “text extraction spacing”, “copy-paste loses spaces justified” (justified text stretches the gaps — now your threshold is wrong on exactly the prettiest paragraphs).
  • Text selection is geometry, not strings — the highlight box must wrap the glyphs, at every zoom, on rotated pages: “pdf text selection height error”, “text highlight offset”, “rotated text highlight missing”, “annotation text edge selection.” Four cases on the humble act of dragging a mouse across a sentence.
  • Search hit highlighting must map string offsets back to page coordinates through every quirk above — and when it misses (“ocr search missing results”), the user concludes the document doesn’t contain the thing they are staring at.
  • OCR is a probability field pretending to be text. Skewed scans, coffee stains, dot-matrix originals, handwriting in the margin, a fax of a photocopy of a fax. The OCR layer must be positioned under the image pixels (invisible, selectable), aligned glyph by glyph, or selection feels haunted.
  • OCR inherits every language problem from the fonts chapter — Thai segmentation, CJK, RTL, ligatures — plus its own: ‘l’ vs ‘1’ vs ‘I’, ‘O’ vs ‘0’, and the legal difference between €1,000,000 and €7,000,000 riding on a smudge.
  • Extraction feeds everything downstream — search indexes, data-capture pipelines, and now LLM ingestion. Garbage text layer in, garbage AI answers out — at enterprise scale, with confidence. (We’ve watched a poor text export make a language model hallucinate contract clauses. The fix wasn’t in the AI. It was in the viewer’s text layer.)
  • And extraction must respect governance: redacted content, permission masks, hidden Excel columns (“excel search hidden columns” — the search that found too much). The text layer is a second rendition of the document, with its own security review.

10. Annotations: the product hiding inside the product

Viewing is read-only, right? Wrong. The moment users can see documents, they want to mark them — highlights, sticky notes, stamps, arrows, redaction marks — and now you own a second product with its own data model, coordinate mathematics, versioning, and forty years of interoperability baggage.

Fifty-plus cases in our corpus — one in ten of all fidelity problems — were about annotations. A partial inventory of the ways annotations betray you:

  • They sit at the wrong place (“annotation positioning shifts after save”, “redaction annotation positioning”, “sticky notes misaligned in PDF export”).
  • They sit at the wrong place only on non-A4 pages (“annotation placement non-A4 export”) — because someone, somewhere, hardcoded 595×842.
  • They sit at the wrong place after the page was rotated (“page rotation annotation sync”) — PDF annotation coordinates live in unrotated page space, and everyone gets this wrong once.
  • They vanish. In print (“annotations missing from print” — three separate cases), in PDF export, in FDF export, on document load, after an upgrade, on email documents specifically. Each vanishing is its own code path.
  • They reappear (“annotation reappears after deletion”) — which is worse. A deleted redaction mark that resurrects is a document-governance incident.
  • They multiply (“annotations replicated across pages”, “annotations wrongly duplicated on split”).
  • They shrink (“annotations render microscopically”) or become “abnormally sized” PNGs.
  • They rotate themselves in FDF export (“annotations rotated in FDF export”).
  • Their text corrupts (“annotation comment text corruption”), their dates render wrong (three separate date cases: format, value, timestamp), their transparency flattens to opaque black boxes (“black boxes in PDF annotations”), their fonts are too small when printed but fine on screen (“annotation font sizing print”).
  • They contain non-Latin characters that the annotation layer can’t handle (“non-roman annotation characters unsupported”) — because of course a reviewer in Athens wrote a comment in Greek.
  • And the great silent killer: version compatibility. Annotations created in viewer version N must render in version N+3, and vice versa, forever. Our corpus holds six cases on annotation compatibility across versions. Annotations are data with a 20-year lifespan and an emotional owner.

Have you thought about the coordinate systems? PDF measures from the bottom-left in points, rotated pages rotate the origin, your screen measures from the top-left in CSS pixels at some zoom level and some devicePixelRatio, the scanned TIFF underneath has its own DPI, and an annotation dragged 3 pixels at 150% zoom on a rotated page must land on the same word forever, on every device, in every export. That is not a feature. That is a treaty between four coordinate systems, and treaties get violated.

11. Redaction and watermarking: where rendering bugs become legal incidents

Most rendering bugs cost fidelity. These cost lawsuits.

  • Redaction is not drawing a black rectangle. The text must be removed — from the content stream, from text extraction, from search — not covered. Our corpus: “partial redaction masking”, “redactions not applied to output”, “redaction flattentext not functional”, “pdf redaction output garbled”, “obfuscations missing in download.” Every one of those lines is a GDPR incident that almost happened.
  • Partial redaction on mixed page sizes — the redaction rectangle computed on an A4 assumption, applied to a Letter page, exposing a strip of the thing it was hiding. Real case.
  • Redacted text still selectable (“obfuscation text selection”) — the pixels were hidden; the characters were still there under Ctrl+C.
  • Redaction of video — a customer needed segments of a recording redacted from the downloadable copy (“video redactions not in download”).
  • Watermarks — dynamic (username, timestamp — “dynamic stamp values stale”), positioned (“watermark top_left placement wrong”), composited over arbitrary content (“dynamic watermark composite failure”), applied to whole ZIP archives of documents (“email zip watermarking failure”), and sometimes simply “watermarks not appearing,” which for a confidentiality-driven customer is the same severity as a redaction failure.

If your prototype’s redaction is a <div> with background: black, you do not have a redaction feature. You have a discovery-phase surprise.

12. The viewer itself: browsers, zoom, print, and the physics of scrolling

Everything so far was about the documents. Now remember: all of it must be displayed inside a browser you don’t control, at a zoom level you don’t control, on hardware you don’t control, printed through a pipeline you really don’t control.

  • “Document sharpness Chrome vs IE” — the same page, visibly crisper in one browser. (Also: you will support browsers that were end-of-lifed years ago, because a hospital’s radiology workstation runs what it runs.)
  • “PDF print orientation Firefox” — landscape documents printing portrait, but only in Firefox, only from the print dialog.
  • “Annotation display clipping edge browser” — annotations clipped at the viewport edge in exactly one browser’s compositing path.
  • Zoom breaks things you thought were solid: “document display offset zoom misalignment”, “hyperlink text misalignment at zoom”, “large page zoom scaling issue”, “excel wide columns zoom scaling.” Every fixed-point assumption in your rendering pipeline is a future zoom bug.
  • Scrolling a 10,000-page document means virtualization, tile caching, prefetch, and eviction — get any of them wrong and you produce our corpus’s poltergeists: “document reload ghost image”, “page order shuffling on refresh”, “intermittent blank page display”, “first load content display issue”, “pdf page display after inactivity.”
  • Sessions and caching produce the saddest category of all: the blank page. “Blank page after authentication.” “Session timeout blank display.” “Cached document timeout blank.” The user did nothing wrong. The document did nothing wrong. The clock did something wrong.
  • Thumbnails are a product too: “thumbnail generation failure”, “thumbnail image rendering quality poor”, “excel attachment thumbnail rendering”, and the wonderfully specific “last email attachment thumbnail missing.” (Just the last one. Off-by-one errors are eternal.)
  • Mobile — pinch zoom, touch selection, 3× devicePixelRatio, iOS Safari’s private opinions about canvas memory. Every desktop assumption, invalidated at 390 pixels wide.

13. Printing: the rendition of the rendition

You rendered the document faithfully on screen. Congratulations. Now the user presses Ctrl+P, and everything you fought for goes through a second rendering pipeline — one owned by the browser, the OS print spooler, and a driver written in 2011.

Have you thought about…

  • Print is not display. The screen rendition lives at 96 (or 192, or 288) DPI in RGB; paper wants 600 DPI in whatever the driver feels like. Do you re-render at print resolution, or ship the screen raster and accept the blur? (Users notice. “Annotation font sizing print” and “PDF annotation printing font small” — fine on screen, microscopic on paper.)
  • The orientation roulette: the landscape document that prints portrait, the portrait that prints landscape, and our old friend “printed PDF appears upside down” — each browser’s print path makes its own rotation decisions, and Firefox’s differ from Chrome’s. (Real case: “PDF print orientation Firefox.” Only Firefox.)
  • Annotations at print time are a policy decision and a rendering feature: burn them in? offer with/without? Our corpus holds three separate “annotations missing from print” cases plus “annotations fail to print/download” and “print annotations error.” Users consider a printout without their sticky notes a data loss.
  • Redactions at print time are not a policy decision. They are the law. The printout must carry the redaction, flattened, irreversible.
  • Watermarks must survive the trip — “CONFIDENTIAL — printed by X on date Y” exists precisely for the paper copy; a watermark that renders on screen and vanishes in print (“watermarks not appearing”) is a confidentiality feature working exactly backwards.
  • Scaling and margins: fit-to-page silently shrinking a form so its barcode no longer scans; “actual size” pushing content into the printer’s non-printable margin; A4 documents on Letter paper and vice versa, forever, across the Atlantic.
  • PDF/A flattening print regression — real case, five words, two weeks: archival-grade PDFs whose form flattening broke only in the print path.
  • The print dialog itself breaks — “print menu nonfunctional,” twice in our corpus. Not the document. The button. In one browser version. After one update.
  • And the existential one: the paper copy is the copy that gets signed, filed, and produced in court. Whatever your viewer prints becomes the document. No pressure.

14. Accessibility: viewing for people who don’t view

A growing share of “content viewing” has nothing to do with pixels. Screen readers, keyboard navigation, and accessibility law — the European Accessibility Act became enforceable in June 2025; Section 508 has been there all along — turn your viewer into an assistive-technology target, and documents into things that must be heard.

Did you know…

  • A PDF can be perfectly rendered and perfectly inaccessible. Visual fidelity needs glyphs and positions; a screen reader needs structure — tagged headings, reading order, table semantics, alt text. Most real-world PDFs are untagged: to assistive tech, they’re wallpaper.
  • A scanned document is an image of text. Without an OCR text layer, your viewer shows a page the sighted user reads fluently and the screen reader announces as… nothing. One archive, two completely different products.
  • Reading order strikes again — the same problem that haunts text extraction decides what a blind user hears, and in what order. Right column first? Footer mid-sentence? For a sighted user that’s a copy-paste annoyance; for a screen-reader user it’s the whole document, scrambled.
  • The viewer UI must be accessible too: every toolbar button reachable by keyboard, focus visibly managed inside an iframe inside someone else’s portal, zoom announcements, page-change announcements, ARIA landmarks over a canvas that is, natively, a bitmap with no semantics at all. Rendering to <canvas> is an accessibility decision, and it obliges you to rebuild, in parallel, everything the canvas erased.
  • High-contrast and forced-colors modes — the OS inverts the world; your carefully color-matched rendition must decide what to invert (the UI) and what to protect (the document — a contract whose colors changed is a different contract).
  • Text reflow — WCAG expects content usable at 400% zoom without two-dimensional scrolling. A paginated PDF is definitionally two-dimensional. Reconciling fixed layout with reflow is a rendering project of its own (and yes, it collides head-on with “fidelity”).
  • Public-sector customers don’t ask if, they ask how — accessibility conformance is now a procurement gate. “We’ll add accessibility later” is the new “we’ll add security later,” with the same survival rate for the deal.

15. Scale, performance, and the documents that fight back

A viewer that renders a 40-page contract beautifully has completed the demo. Production is where the other documents live:

  • The 10,000-page multi-page TIFF from the scanning bureau.
  • The 1.2-gigapixel engineering scan that must tile and stream, because decoding it whole would eat the server (“output image size too large”, “large image pdf rendering timeout”).
  • The 400 MB Excel file (“large excel file load error”) and the “excel 97-2003 large file display error” — same customer energy, different decade of format.
  • “Large document annotation failures” — everything works until page 4,000.
  • “Document conversion timeout failure”, “rendering timeout at resolution”, “email rendering timeout with links”, “video loading timeout” — four different timeouts, four different subsystems, one user experience: spinner, then nothing.
  • “PDF rendering fails randomly” — the phrase every engineer dreads, because “randomly” means concurrency, and concurrency means weeks. A rendering farm juggling hundreds of simultaneous conversions must isolate every crash (one malformed file must never take down a neighbor’s rendition), recycle poisoned workers, and keep P99 latency flat while someone uploads a 2 GB scan at 9:00 AM Monday.
  • The intermittents: “document rendering intermittent”, “image intermittent display”, “intermittent blank page” ×2. Heisenbugs, in a distributed pipeline, under load, with the reproduction case behind a customer’s firewall.
  • And the conversion bloat family: “TIFF PDF conversion bloat” (the 2 MB fax that became a 200 MB PDF), “JPEG image output size increase”, “PDF/A conversion file size.” Fidelity isn’t only visual — bytes are a fidelity dimension too, and storage teams notice.

16. Security: the chapter nobody puts in the demo

Your viewer parses hostile input by design. Every parser is attack surface; a document viewer is forty parsers in a trenchcoat, running server-side, behind your customer’s firewall, fed by anonymous uploads.

Our corpus is full of it, well beyond rendering: CVE assessments, Log4Shell (twice — remember December 2021? our customers do), XSS reports from customers’ own pentest campaigns (three), Docker image vulnerability scans (two), and the quiet, constant work of keeping forty embedded parsers patched against other people’s bugs.

Things your sprint-built viewer must survive:

  • The zip bomb DOCX (it’s a ZIP; 42 KB expanding to 4 PB is a classic).
  • The XML billion-laughs entity expansion inside OOXML.
  • The XXE — external entity resolution exfiltrating server files through a “document.”
  • The SSRF via remote image references in email HTML — your renderer, helpfully fetching http://169.254.169.254/ on behalf of an attacker.
  • The JBIG2/font/image codec exploits — the same bug classes that powered real-world zero-click exploit chains (FORCEDENTRY entered through a PDF codec pretending to be a GIF).
  • PDFs with JavaScript, macro documents, OLE objects with embedded executables — every “rich” format feature is also a delivery mechanism.
  • Password-protected files as a bypass — malware scanners can’t open them; your viewer, holding the user-supplied password, becomes the first thing that ever parses the payload.
  • And the sneaky governance one: text extraction and search must respect redaction and permissions — otherwise your search index happily serves the content someone carefully redacted from the pixels.

“Just use a library” is also a security decision: you now own the CVE feed of every library in the trenchcoat, forever, on your customer’s compliance timeline, with proof-of-patch obligations in regulated industries.

17. Integration: the viewer is never alone

A content viewer never ships as a standalone toy. It lands inside something — an ECM, a claims system, a case-management screen, an iframe in a 2009 portal — and the seams have their own failure ecosystem:

  • The repositories: every ECM and content platform on the market, cloud object stores, and at least one bespoke system whose “API” is a network share and a naming convention. Each with its own auth, its own streaming quirks, its own idea of what a “version” is.
  • “Wrong document shown in preview” — the scariest four words in content services. (It’s almost never the renderer. It’s an ID collision, a cache key, a race. It is always your problem anyway.)
  • “Document ID not recognized after upgrade” — identity is hard; persistent identity across a decade of migrations is harder.
  • “Annotation version compatibility” after the ECM migrated but the annotation store didn’t — data outliving three surrounding systems.
  • “Long file names prevent rendering” — a 300-character filename from a German compound-noun enthusiast, meeting a filesystem limit somewhere in the middle of the pipeline.
  • Token lifetimes, SSO handshakes, iframe cookie policies — “blank page after authentication” lives here, at the intersection of your viewer and five identity systems you’ve never heard of.
  • Environment drift: it renders on the Windows service but not the Linux one (“excel rendering windows service”); it renders everywhere except RHEL 8; it broke when the OpenJDK version changed; the Docker registry token expired and the nightly rebuild silently shipped nothing.

And above it all, the upgrade treadmill: our corpus’s most chilling theme isn’t any single format — it’s the word regression. “Annotations not visible after upgrade.” “Documents unreadable after upgrade.” “TIFF file rendering regression.” “Email pagination layout regression.” A viewer is a promise made to an archive: everything that opened yesterday opens tomorrow. Every improvement you ship is tested against that promise by thousands of documents you have never seen — and the ones that break will find you.

18. The meta-problem: what does “correct” even mean?

One last complexity, the philosophical one that swallows all the others.

When a customer says a document “renders wrong,” wrong compared to what?

  • Compared to Word? Which version? Word 2010, 2016, and 365 paginate the same file differently. Word on Mac differs from Word on Windows. Word with different printer drivers used to paginate differently (really — printer metrics leaked into layout for decades).
  • Compared to Acrobat? Acrobat heals malformed files silently; matching its output means matching its bugs, undocumented, version by version.
  • Compared to Outlook? Outlook renders HTML email with Word’s engine — a decision so consequential that an entire industry of email-template developers exists to work around it. Match Outlook, and you’re wrong compared to Gmail. Match Gmail, and the compliance officer’s printout from Outlook contradicts your rendition.
  • Compared to LibreOffice? We run automated fidelity metrics against reference renditions, and we routinely catch the reference being wrong — LibreOffice inflating a 2-page letter to 4 pages, reversing table columns on Google-Docs-exported files, hyphenating French text that the document never asked to hyphenate. When your measuring stick lies, even knowing you have a bug becomes a research project.
  • Compared to the paper copy in the file cabinet, printed in 2013 by a system that no longer exists? That one is unbeatable in court and unreproducible in software.

Every rendering fidelity decision is a negotiation between contradictory authorities. There is no spec for “what the user meant.” There is only judgment, measurement, regression suites, and years of accumulated cases — 2,382 of them and counting, in our corner of the world alone.

The litany

And because a liste à la Prévert deserves to actually be a list, here — without commentary, without mercy, each line a real document or a real scar — is what four years of “just viewing documents” looks like:

  • The PDF that renders completely black.
  • The PDF whose first page only renders black.
  • The PDF that opens in Acrobat and nowhere else.
  • The PDF that starts with a byte-order mark and gets displayed as text.
  • The PDF that is secretly a portfolio of other PDFs.
  • The PDF with an embedded Distiller joboptions file.
  • The PDF whose form fields hold data that never appears.
  • The PDF whose form text appears twice.
  • The XFA form that renders as a page telling you it cannot be rendered.
  • The signed PDF that must prove it hasn’t changed since signing.
  • The encrypted PDF with an empty password.
  • The landscape page that prints portrait.
  • The document that prints upside down, but only from Firefox.
  • The hyperlink that lands on the right page at the wrong height.
  • The hyperlink wearing an ugly black frame.
  • The bookmark that appears twice.
  • The bookmark panel that appears empty.
  • The checkbox that renders as the wrong character.
  • The checkbox that was a Wingdings glyph all along.
  • The apostrophes that vanished from an entire contract.
  • The accents that duplicated themselves.
  • The uppercase bold characters that duplicated themselves — only uppercase, only bold.
  • The Thai words broken in the wrong places.
  • The Polish characters missing from the PDF.
  • The Cyrillic email that arrived as mojibake.
  • The Korean characters that displayed as boxes.
  • The emoji in the customer-service email that had to be preserved as evidence.
  • The barcode font that turned an invoice into decoration.
  • The missing font that crashed the whole renderer.
  • The font that was 3% wider and moved a page break in a signed contract.
  • The line height of Calibri, about which entire weeks have been lost.
  • The Word document with sixty section breaks.
  • The Word document whose empty tables produced phantom blank pages.
  • The Word document whose text was generated by a macro your server refuses to run.
  • The date field that shows today’s date on a ten-year-old contract.
  • The table of contents whose page numbers change when you fill it in.
  • The tracked changes that prevented rendering entirely.
  • The comments that silently vanished from the export.
  • The numbering that restarted at 1 in the middle of a legal document.
  • The Excel formula whose cached value was wrong.
  • The Excel date born in 1904 because the workbook came from a Mac.
  • The leap year 1900, which never happened and must be honored anyway.
  • The hidden column that search kept finding.
  • The filter arrows that disappeared from the rendition.
  • The workbook whose other eleven sheets were simply not there.
  • The wide spreadsheet that would not paginate the way Excel paginates.
  • The 97-2003 file that broke what 2007+ never did.
  • The slide whose title is positioned by a file it isn’t in.
  • The theme color that is not a color but a formula.
  • The autofit text whose last bullet vanished at the fixed point.
  • The SmartArt that is a data model wearing a diagram costume.
  • The email with three bodies — text, HTML, and RTF — all slightly different.
  • The RTF body with HTML encapsulated inside it.
  • The winmail.dat that ate all the attachments.
  • The inline image that is also an attachment and must not appear twice.
  • The remote image that is a privacy leak if you load it and a bug if you don’t.
  • The email that rendered as one infinite line.
  • The email whose headers came out in French in Rotterdam.
  • The sent date rendered in the wrong timezone, missing a legal deadline.
  • The subject line with characters that broke the header decoder.
  • The signed S/MIME message that displayed as cryptographic soup.
  • The .eml inside the .msg inside the .eml, four levels deep, that crashed on level three.
  • The calendar invite that is not quite an email but arrived anyway.
  • The nested-email crash. (Recursion. It’s always recursion.)
  • The NUL character that took down file handling.
  • The mainframe export whose CR/LF was a matter of column alignment.
  • The text file misidentified as an email.
  • The email misidentified as XML.
  • The XML that was secretly a Word document.
  • The annotation that shifted after saving.
  • The annotation that shifted, but only on non-A4 paper.
  • The annotation that rotated itself in the FDF export.
  • The annotation that came back after being deleted.
  • The annotations that multiplied across every page.
  • The annotations that shrank to microscopic size.
  • The annotation dates in the wrong format, the wrong value, and the wrong timezone — three separate cases.
  • The Greek comment the annotation layer couldn’t hold.
  • The highlight that hid the words it was meant to emphasize.
  • The sticky note that flickered.
  • The redaction that didn’t redact the text underneath.
  • The redaction offset by the difference between A4 and Letter.
  • The redacted text that was still selectable.
  • The video segment that had to be redacted from the download.
  • The watermark that appeared in the wrong corner.
  • The watermark that didn’t appear at all.
  • The dynamic stamp showing a stale username.
  • The thumbnail that failed to generate.
  • The last email attachment’s thumbnail — only the last one — that went missing.
  • The ghost image that survived a document reload.
  • The pages that shuffled their order on refresh.
  • The blank page after authentication.
  • The blank page after session timeout.
  • The blank page that was intermittent, and therefore unreproducible, and therefore eternal.
  • The document that was sharp in Chrome and soft in Internet Explorer.
  • The zoom level at which the hyperlinks stopped lining up with the text.
  • The 10,000-page TIFF from the scanning bureau.
  • The TIFF shifted left by a few pixels, forever.
  • The 2 MB fax that converted into a 200 MB PDF.
  • The gigapixel scan that had to be tiled or it ate the server.
  • The large document where everything worked until page 4,000.
  • The rendering that failed randomly, which is to say: concurrency.
  • The conversion timeout, the resolution timeout, the link-crawl timeout, the video timeout.
  • The JBIG2 codec that once changed digits in photocopied numbers.
  • The JPEG 2000 that no browser will decode for you.
  • The CMYK JPEG that rendered as a photo negative.
  • The HEIC from an iPhone, three complaints running.
  • The WebP nobody scoped.
  • The EPS from 1994 that logistics still needs.
  • The Visio diagram the network team swears by.
  • The Factur-X invoice whose real content is the attachment inside it.
  • The zip bomb wearing a DOCX costume.
  • The billion-laughs entity expansion inside an innocent-looking office file.
  • The remote image reference that was actually an SSRF probe.
  • The password-protected file that no antivirus had ever opened — until your viewer did.
  • The Log4j December that support will never forget.
  • The long filename that broke the pipeline somewhere in the middle.
  • The document ID that stopped being recognized after the upgrade.
  • The annotations that outlived three ECM migrations.
  • The Windows service that rendered what the Linux service would not.
  • The RHEL 8 server with no fonts installed.
  • The Docker registry token that expired silently overnight.
  • The wrong document shown in the preview — four words, full escalation.
  • The renderer that had to match Word, which doesn’t match Word for Mac, which doesn’t match Word 2010, which doesn’t match the printout from 2013.
  • The reference PDF that was itself wrong, so the bug report was about the measuring stick.
  • The LibreOffice that hyphenated French no one asked it to hyphenate.
  • The LibreOffice that turned a two-page letter into four pages.
  • The table whose columns came back in reverse order, but only via Google Docs.
  • The page 12 that is someone’s page 14, referenced as page 12 in an audit that accepts no opinion on the matter.

Every line above is solved. Every line above lives in a regression suite. Every line above will be attempted again by a new document, somewhere, on a Monday.

So: can you build a content viewer in a sprint?

Absolutely. We did, once. Everyone does. It renders the demo PDF beautifully.

Then Monday happens, and the uploads begin: the 60-section contract, the HEIC from an iPhone, the S/MIME-signed email in KOI8-R with a winmail.dat, the XFA tax form, the 10,000-page TIFF, the Excel with the 1904 epoch, the PDF that starts with a BOM, the Wingdings checkbox, the Thai paragraph, the barcode font, the JBIG2 scan, the redaction that must actually redact, the annotation from 2016 that must land on the same word in 2030, on a rotated page, at 400% zoom, in a browser you’ve never tested, behind an SSO you’ve never heard of, faster than last Tuesday, and with yesterday’s CVE already patched.

None of these is impossible. That’s the trap. Each one is a solvable, two-week engineering problem — and there are several thousand of them, they interact, and they never stop coming. The difficulty of content viewing isn’t a wall; it’s weather. You don’t beat weather in a sprint. You survive it with infrastructure, telemetry, regression suites, and a decade of scar tissue.

That scar tissue has a name — ours is called ARender. Twenty-plus years of cases like the ones above, each one solved, each one added to the regression suite, each one a document that will never surprise anyone again.

If you’re a software vendor, this is the actual decision on the table — not “can we render a PDF?” but “do we want to own this list?” Every hour your team spends matching Word’s margin-collapsing rules is an hour not spent on the product your customers actually buy from you. Viewing is our product so that it doesn’t have to be yours: you integrate a component, and the litany above stays on our side of the API — along with the regression suite, the CVE feed, the format archaeology, and the next twenty years of documents nobody has met yet.

So the next time someone in a steering committee says “it’s basically done” — send them the list. Ask them about the apostrophes. Ask them about the timezone of a sent date, the leap year that never happened, the checkbox in Wingdings, the French email headers in Rotterdam, the last thumbnail (only the last one), and the PDF that opens fine in Acrobat.

Then ask them what their plan is for the second week.

Based on our classification of 2,382 real-world cases collected in the field between January 2022 and mid-2026: 518 document-fidelity problems across PDF, email, Word, Excel, PowerPoint, TIFF, images, text, and a long tail of formats we didn’t choose — the documents chose them for us. Details anonymized; pain preserved. And of course, everything is fixed…

Written by
UX
Uxopian Editorial
ARender Engineering
@Uxopian Software

Send them the list

If the steering committee says the viewer is basically done, this page is the reply. And if you would rather own your product than the litany, the ARender team is easy to reach.