Skip to main content
The video uses a specific AI coding tool to demonstrate the setup, but the configuration works 1:1 with Cursor, Claude Code, or any other tool. Despia is web framework and tooling agnostic, so the only thing that matters is passing the file’s HTTPS URL into the SDK call and serving the file with the right headers.
Pass an HTTPS URL into despia() and the runtime fetches the file, then opens the native share sheet with the bytes already attached. The user picks a destination (Messages, Mail, AirDrop, WhatsApp, Drive, Files, anything that registered a share extension) and the OS handles the rest. Works for any file type the OS recognizes, including PDFs, images, video, audio, archives, and Office formats.
The URL must be a publicly fetchable HTTPS endpoint that returns the file with the right Content-Type and Content-Disposition headers. Data URLs (data:application/pdf;base64,...), blob URLs (blob:...), and file:// paths are not accepted. The runtime needs to fetch the file from the network, so upload the bytes to a CDN, S3 bucket, or similar storage first and pass the resulting public URL into the call.

Installation

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

How it works

Pass the file URL directly into despia(). There is no scheme prefix, the runtime detects an HTTPS URL and routes it through the share-sheet handler.
import despia from 'despia-native'

const isDespia = navigator.userAgent.toLowerCase().includes('despia')

if (isDespia) {
    despia('https://cdn.example.com/documents/report.pdf')
}
The share sheet shows the file’s preview, name, and source app, then lets the user pick a destination. The user can also cancel, in which case nothing happens and your app keeps running normally.

Server requirements

The endpoint serving the file has to send two response headers correctly. The OS uses these to decide how to render the preview, what filename to suggest, and which apps to show as share targets.
HeaderRequired valueWhat it does
Content-TypeThe accurate MIME type for the file, e.g. application/pdf, image/jpeg, video/mp4, application/zipDetermines the file’s icon, preview behavior, and the apps the share sheet offers. Wrong type produces a generic icon and limited share targets
Content-Dispositionattachment; filename="report.pdf"Tells the OS what filename to use in the share sheet and in the receiving app
// Example endpoint serving a generated PDF
export default async function handler(req, res) {
    const buffer = await generatePdf(req.query.id)

    res.setHeader('Content-Type', 'application/pdf')
    res.setHeader('Content-Disposition', 'attachment; filename="report.pdf"')
    res.setHeader('Content-Length', buffer.length)
    res.send(buffer)
}
If you are serving from S3, Cloudflare R2, or another object store, set these headers on the object metadata when you upload. Most stores let you specify them per object, and they get returned automatically on every fetch.

Share a file from a button

The natural pattern is a “Share” button next to a file or piece of content. Tap, share sheet opens, user picks a destination, done.
import despia from 'despia-native'

const isDespia = navigator.userAgent.toLowerCase().includes('despia')

function ShareButton({ fileUrl, label = 'Share' }) {
    function share() {
        if (isDespia) {
            despia(fileUrl)
        }
    }

    return <button onClick={share}>{label}</button>
}
For files that do not yet exist as URLs (a generated invoice, an exported chart, a captured screen), upload first, then share the resulting URL.
async function generateAndShare() {
    if (!isDespia) return

    // 1. Generate or capture the file as a Blob
    const blob = await generateInvoice()

    // 2. Upload to your CDN or storage backend
    const formData = new FormData()
    formData.append('file', blob, 'invoice.pdf')

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

    // 3. Share the resulting public URL
    despia(data.url)
}
The upload step is your code, not Despia’s. Use whatever storage you already have (S3 with a presigned URL, Cloudflare R2, Bunny CDN, Supabase Storage, etc). The output must be a publicly fetchable HTTPS URL with the correct headers.

File types

Any file type the OS recognizes will share. The OS infers behavior from the Content-Type header, so as long as that is correct, the right share targets show up automatically.
CategoryCommon types
DocumentsPDF, DOC, DOCX, TXT, RTF, MD
ImagesJPG, PNG, GIF, WEBP, HEIC, SVG
VideoMP4, MOV, M4V, AVI, MKV
AudioMP3, M4A, WAV, FLAC, AAC
ArchivesZIP, RAR, 7Z, TAR.GZ
SpreadsheetsXLS, XLSX, CSV, NUMBERS
PresentationsPPT, PPTX, KEY
CodeJSON, XML, HTML, JS, TS
For unusual types, set Content-Type to application/octet-stream as a fallback. The share sheet still works, the user just gets a generic file icon and a smaller set of compatible destinations.

Resources

NPM Package

despia-native