Building better document previews with a Custom Doc Viewer for Retool

Vaggelis Kapetanakis

Rich document preview

Client-side rendering

Open Source

tl;dr here's the repository

Building internal tools often means dealing with contracts, specs, and reports that still live in Word. For those flows, we needed a way to preview .docx files directly inside Retool without downloads, external viewers, or public URLs.

Why we built it

Retool lets you upload and store files, but there is still no native way to preview Word documents inline inside an app. For teams working with specs, contracts, or internal reports, that usually means downloading the file locally or sending it through an external viewer before you can read it.

Most existing workarounds either break internal‑only requirements or add a lot of infrastructure overhead. Google Docs or Office Online embeds require a publicly accessible URL, server‑side PDF conversion adds latency and maintenance, and popular React viewers like react-doc-viewer ultimately rely on Microsoft’s Office Online iframe behind the scenes. In other words, you either expose documents to the public internet or ship them off to third‑party services, not great for sensitive internal tools.

We wanted a simple, React‑friendly component we could drop into Retool that would render .docx files directly in the browser, stay responsive, and never send data outside the client.

What we built

The Custom Doc Viewer is a Retool custom component that previews .docx files entirely client‑side using the docx-preview library. It accepts base64‑encoded document data from file inputs or queries, validates file size, and renders a responsive, scrollable document viewer with built‑in loading and error states.

Because everything runs in the browser, no public URLs are required and no document content is sent to external services. The component exposes Retool events so you can trigger workflows when a document loads successfully or when something goes wrong, and it supports accessible markup with ARIA attributes and keyboard navigation.

You can use it anywhere you need inline Word previews in Retool, reviewing contract drafts, checking specification docs, or letting operators confirm an uploaded file before they save it.

Features

Client‑side .docx rendering – Uses docx-preview to parse Office Open XML and render Word documents directly to HTML/CSS in the browser, with no server‑side processing.

  • Responsive scaling – Automatically scales pages to fit the component width and keeps the document centered for a clean reading experience.

  • Base64 input – Accepts raw base64 or data‑URL‑style strings from file inputs or queries (for example {{ fileInput1.value[0] }} or {{ query1.data.fileContent }}).

  • Configurable file size limitmaxFileSizeMB lets you cap document sizes (50MB by default) to avoid browser crashes or memory issues.

  • Loading, error, and empty states – Built‑in loading indicator, clear error messages, and an empty state when no document is provided.

  • Accessible by design – ARIA attributes, screen reader support, and keyboard navigation for users who rely on assistive technology.

  • Retool eventsonDocumentLoaded and onLoadError events so you can trigger queries, show notifications, or update app state when documents render or fail.

  • Simple styling hooks – Configure background color and drop it into your existing Retool layout without custom CSS.

Note on formats: the component supports .docx files only and will show a friendly error if a legacy .doc file is uploaded, reflecting a limitation of the underlying library.

Installation & Usage

The Custom Doc Viewer ships as an open‑source Retool Custom Component Library.

Clone the repository

git clone https://github.com/StackdropCO/custom-doc-viewer.git
cd custom-doc-viewer
git clone https://github.com/StackdropCO/custom-doc-viewer.git
cd custom-doc-viewer
git clone https://github.com/StackdropCO/custom-doc-viewer.git
cd custom-doc-viewer

Install dependencies

npm install
npm install
npm install

Login to Retool

npx retool-ccl login
npx retool-ccl login
npx retool-ccl login

You’ll need an API access token with read and write scopes for Custom Component Libraries.

Start development mode
This runs live‑refresh mode so changes sync straight into your Retool custom components.

npm run dev
npm run dev
npm run dev

Deploy for production
Once deployed, pin your app to the published version in the Custom Component settings.

npm run deploy
npm run deploy
npm run deploy

Using it in your Retool app

  • Once the library is deployed, you’ll see Custom Doc Viewer in the Custom Components section of the Retool component picker.

    • Drop the component onto your canvas.

    • Set the base64Data property to your document source:

      • From a File Input: {{ fileInput1.value[0] }}

      • From a query returning base64: {{ getDocument.data.base64Content }}

    • Optionally tweak:

      • maxFileSizeMB – for example 10 for 10MB or 100 for 100MB.

      • backgroundColor – to match your app’s design.

      • showLoadingState – toggle the loading indicator.

    You can reference the component’s state anywhere in your app:

    • {{ customDocViewer1.isLoading }} to show spinners or disable actions while a document renders.

    • {{ customDocViewer1.errorMessage }} to surface errors or drive alerts.

    Hook into onDocumentLoaded and onLoadError events to trigger follow‑up queries, write audit logs, or show success/error banners.

Retool limitations & roadmap

Because this is a Retool custom component, the usual constraints apply: it can’t be part of a form, Appearance/Interaction/Spacing panels are disabled, and it renders inside an iframe without access to the parent DOM.

There’s a clear roadmap for future improvements:

  • Zoom controls for manual in/out.

  • Page navigation for long documents.

  • Text search and highlighting.

  • Additional formats like .rtf, .odt, or legacy .doc via complementary libraries.

  • One‑click print support that opens the browser’s print dialog.

If you want to dig into the implementation or contribute, the code is available on GitHub at StackdropCO/custom-doc-viewer.

Get involved

We build this component to make internal tools feel as polished as the products they power, and to keep expanding the open toolbox for the Retool community to build on and improve together.

We're always open to ideas, whether it's a feature idea, a bug fix or a completely new use-case. Jump in, share feedback or open a PR ~ we'd love to see what you build and how you make it better. 

Give it a try - happy building.