Skip to main content

Documentation Index

Fetch the complete documentation index at: https://setup.despia.com/llms.txt

Use this file to discover all available pages before exploring further.

fileviewer:// opens any remote file in a native previewer without forcing the user out of your app. iOS renders the file through QuickLook; Android renders it through Despia’s in-app file viewer, built to match QuickLook’s fidelity so output stays consistent regardless of what apps the user has installed. Useful for invoices, statements, contracts, exported reports, generated PDFs, and any other case where you would otherwise navigate the user to a hosted file URL and lose your app’s context.

Installation

npm install despia-native
import despia from 'despia-native';

How it works

Pass an absolute HTTPS URL as the src parameter. The native side downloads the file off the main thread, resolves its type from the URL extension (falling back to the response Content-Type), and hands it to the previewer. The call is fire-and-forget; there is no JS callback.
import despia from 'despia-native'

const isDespia = navigator.userAgent.toLowerCase().includes('despia')
const src = encodeURIComponent('https://example.com/report.pdf')

if (isDespia) {
    despia(`fileviewer://?src=${src}`)
}
Always pass src through encodeURIComponent so the scheme separator, slashes, and any query characters survive transit.
ParameterRequiredDescription
srcYesAbsolute HTTPS URL of the file. Must be percent-encoded.
themeNolight or dark. Overrides the system appearance for the previewer UI. Omit to follow the device’s system theme.
The previewer renders PDFs, images (PNG, JPG, HEIC), plain text, RTF, CSV, and Office documents (DOCX, XLSX, PPTX).

Matching the previewer to your app’s theme

Pass theme=light or theme=dark when your app overrides the OS appearance and you want the previewer to follow your app’s setting instead of the device default. Omit theme entirely to fall back to the system appearance.
const src = encodeURIComponent('https://example.com/report.pdf')

if (isDespia) {
    despia(`fileviewer://?src=${src}&theme=dark`)
}
theme is a plain string and does not need encoding; only src needs encodeURIComponent.

Authenticating the file URL

The native fetch is a plain HTTPS request made from outside your web session, so it does not carry the user’s cookies. Any file behind authentication has to be reachable through the URL itself. The standard pattern is a short-lived signed URL generated by your backend.
const res = await fetch('/api/invoices/123/signed-url')
const { url } = await res.json()

if (isDespia) {
    despia(`fileviewer://?src=${encodeURIComponent(url)}`)
}
Most object stores generate these natively: S3 presigned URLs, Cloudflare R2 signed URLs, Google Cloud Storage signed URLs, Azure Blob SAS tokens. Issue them with the shortest expiry that fits your flow, typically a few minutes, so a leaked URL stops working quickly.

Generated or canvas-exported files

src must be a publicly reachable HTTPS URL. data:, blob:, and file:// URLs are rejected, since the native side performs a real network fetch. Upload generated content to a CDN or signed endpoint first and pass the resulting URL.
If your app produces a file on the client, a canvas export, a generated PDF, a CSV built in memory, upload it first and then pass the returned URL to the scheme.
const form = new FormData()
form.append('file', blob, 'report.pdf')

const res = await fetch('/api/uploads', { method: 'POST', body: form })
const { url } = await res.json()

if (isDespia) {
    despia(`fileviewer://?src=${encodeURIComponent(url)}`)
}
If the upload endpoint returns a signed URL, the file is also protected after the upload — the same pattern from the previous section applies.

Resources

NPM Package

despia-native