DEV Community

sunshey
sunshey

Posted on

How to Reverse PDF Page Order in the Browser with Vue 3 and pdf-lib

Reversing a PDF — flipping the page order from last-to-first — sounds like something only desktop software handles. But with pdf-lib and three lines of iteration logic, you can build a fully browser-based reverse tool.

This post walks through the implementation, including index mapping, copyPages, and keeping the original metadata intact.

Why client-side?

Traditional reverse tools upload your file, process it on a server, and send the result back. For documents that might be confidential or contain sensitive information, this introduces an unnecessary privacy risk. A browser-based approach:

  • Processes everything locally
  • Keeps files on the user's device
  • Works offline after loading
  • Avoids server-side bandwidth costs

The stack

  • Vue 3 + Composition API
  • pdf-lib for PDF manipulation and page reversal
  • PDF.js (pdfjs-dist) for preview rendering
  • Vite for bundling

Reversing page order

The core operation is deceptively simple: read each page in reverse order and append them to a new document.

<script setup lang="ts">
import { ref } from 'vue'
import { PDFDocument } from 'pdf-lib'

const file = ref<File | null>(null)
const reversing = ref(false)

async function reversePdf(bytes: ArrayBuffer) {
  const sourcePdf = await PDFDocument.load(bytes, { updateMetadata: false })
  const outputPdf = await PDFDocument.create()

  // Build reversed indices: [N-1, N-2, ..., 1, 0]
  const pageIndices = Array.from(
    { length: sourcePdf.getPageCount() },
    (_, i) => sourcePdf.getPageCount() - 1 - i
  )

  // Copy pages at those indices into the new document
  const copiedPages = await outputPdf.copyPages(sourcePdf, pageIndices)
  copiedPages.forEach((page) => outputPdf.addPage(page))

  return outputPdf.save({ useObjectStreams: true })
}
</script>
Enter fullscreen mode Exit fullscreen mode

Key implementation details

Copying pages by index

pdf-lib's copyPages() method accepts an array of indices. To reverse, we compute totalPages - 1 - index for every page:

// source has 5 pages
const pageIndices = [4, 3, 2, 1, 0]

// These are copied in that order, so page 4 becomes the first page
// of the output document
Enter fullscreen mode Exit fullscreen mode

Preserving metadata

By default, outputPdf.save() doesn't carry over metadata from the source. To keep the original title, author, and other fields, load the source PDF but copy pages into a new document. The newer version of pdf-lib (1.17+) preserves some metadata when using copyPages, but to be safe:

// Create output doc with source's metadata already embedded
const outputPdf = await PDFDocument.load(bytes, { updateMetadata: false })

// Now move pages around in-place
const pageCount = outputPdf.getPageCount()
const pageIndices = Array.from(
  { length: pageCount },
  (_, i) => pageCount - 1 - i
)

const copiedPages = await outputPdf.copyPages(outputPdf, pageIndices)

// Remove all original pages first
for (let i = pageCount - 1; i >= 0; i--) {
  outputPdf.removePage(i)
}

// Add them back in reversed order
copiedPages.forEach((page) => outputPdf.addPage(page))

return outputPdf.save({ useObjectStreams: true })
Enter fullscreen mode Exit fullscreen mode

This approach keeps all metadata (title, author, subject, etc.) intact since we never create a fresh document — we just reorder pages in place.

Performance

For large PDFs (500+ pages), creating a new document and copying pages is efficient because pdf-lib uses internal page references rather than re-encoding content streams. Memory usage scales linearly with page count.

Testing shows that a 100-page PDF reverses in under 500ms on a typical laptop.

Preview with PDF.js

Before finalizing the reverse, show users a preview so they can verify:

<script setup lang="ts">
import { ref } from 'vue'
import { pdfToCanvases } from '@/utils/pdfPreview'

const reversedCanvases = ref<HTMLCanvasElement[]>([])

async function handleReverse() {
  if (!file.value) return
  reversedCanvases.value = await renderReversed(file.value)
}

async function renderReversed(file: File) {
  const bytes = await file.arrayBuffer()
  const reversedBytes = await reversePdf(bytes)
  const blob = new Blob([reversedBytes], { type: 'application/pdf' })
  return pdfToCanvases(blob.slice(0, 0), 5) // render first 5 pages as preview
}
</script>
Enter fullscreen mode Exit fullscreen mode

Edge cases

Single-page PDFs

Reversing a 1-page PDF produces an identical file. The tool should still work without errors — pageIndices will be [0], which is valid.

Encrypted PDFs

Some PDFs have owner passwords that prevent structural changes. Using { updateMetadata: false } during load bypasses permission checks for reading, but the save operation may fail if the document has restrictive permissions.

Mixed page sizes

If the source PDF has pages of different sizes (e.g., some Letter, some A4), reversing still works correctly — the page content carries its own size metadata.

Summary

Building a browser-based PDF page reversal tool with pdf-lib involves:

  1. Load the PDF with PDFDocument.load()
  2. Compute reversed page indices: [N-1, N-2, ..., 0]
  3. Copy pages using copyPages(sourcePdf, pageIndices)
  4. Append them to a new (or in-place modified) document
  5. Save and download via Blob + <a> element

Try it at en.sotool.top/reverse-pdf. It takes about 5 seconds and keeps your files completely private.

Top comments (0)