October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
headless browser

Integrating Paged.js with Ruby on Rails: Browser Previews and Automated PDFs

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use Paged.js in Rails in one of two ways: load its browser polyfill when users need an interactive paginated preview and can print from the browser, or run the Paged.js CLI with a headless browser when your application must create PDFs unattended. Rails supplies the HTML, print CSS and JavaScript through the asset setup your application already uses. The official documentation describes Rails asset delivery and Paged.js workflows separately, so treat the wiring below as an integration to test against your Rails and Paged.js versions.

Choose the rendering architecture first

Decision Browser polyfill CLI/headless workflow
Best for Interactive preview and a user-triggered print-to-PDF flow Automated PDF creation from jobs, controllers or deployment scripts
Runs in A browser loading the Rails document, script and stylesheets A command-line process using a headless browser
Main integration work Serve paged.polyfill.js, HTML and print CSS from Rails Install the CLI dependencies and make the rendered page and assets reachable to the renderer
Important limitation The browser’s Save as PDF dialog controls paper, margins and other print settings Deployment, asset URLs and Rails orchestration are application-specific

Paged.js describes itself as an open-source library that transforms HTML and print CSS into paginated, print-ready output. Its overview and getting-started documentation explain both the browser preview and command-line approaches (project overview; getting started).

Prepare a Rails document for pagination

Keep print structure in the view

Render the report, invoice or book chapter as ordinary HTML. Use semantic elements for headings, tables and figures, then put page-oriented rules in a print stylesheet. A minimal Rails view might be:

<article class="report">
  <header class="report-cover">
    <h1><%= @report.title %></h1>
    <p>Prepared <%= l(@report.created_at.to_date) %></p>
  </header>

  <section class="chapter">
    <h2>Summary</h2>
    <%= sanitize @report.summary_html %>
  </section>
</article>

Use CSS for most layout decisions:

@page { size: A4; margin: 18mm 16mm 20mm; }

@media print {
  .report-cover { break-after: page; }
  h1, h2, h3 { break-after: avoid; }
  table, figure { break-inside: avoid; }
  .running-footer { position: running(footer); }
}

@page {
  @bottom-center { content: element(footer); }
}

Test the rules in the browser and in the CLI renderer. Browser support for advanced paged-media features can differ from the output path, so do not assume that a successful preview guarantees an identical automated PDF.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Expose a dedicated print endpoint

A dedicated action prevents navigation, authentication and interactive application chrome from becoming part of the document:

# config/routes.rb
get "/reports/:id/print", to: "reports#print", as: :print_report

# app/controllers/reports_controller.rb
def print
  @report = current_user.reports.find(params[:id])
  render layout: "print"
end

The print layout should include only the stylesheet and scripts needed by the document. If the endpoint requires authentication, the browser preview can use the user’s session; a background CLI process will need an intentionally designed access method such as a signed, short-lived URL or suitable request headers. Do not expose private reports through an unprotected URL.

Deliver Paged.js through Rails

Rails applications commonly use import maps or a JavaScript bundler, while the asset pipeline serves static assets and build output. Follow the stack already present in your application rather than introducing a second JavaScript delivery system. See the Rails JavaScript guide and Asset Pipeline guide.

Bundler-based application

Install the Paged.js package using the package manager and import it from the entry point produced by your existing bundler. The exact package and export shape can change, so verify the current Paged.js installation instructions before pinning it. Ensure the resulting build is written to the directory your Rails asset configuration serves (for example, app/assets/builds when using jsbundling-rails).

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
// app/javascript/application.js
// Keep this import aligned with the Paged.js distribution selected by your app.
import "./paged-print";

Then include the compiled entry in the print layout with your application’s normal Rails helper, commonly javascript_include_tag for an asset-pipeline file.

Import-map application

Import maps deliver browser modules without a bundling step. Pin a distribution only after confirming that it is an ES module suitable for your browser targets; the reviewed Rails and Paged.js pages do not certify a particular import-map pin. If the distribution is not import-map compatible, serve a standalone script as a Rails asset instead.

Standalone script asset

Place the chosen Paged.js browser script where the asset pipeline can serve it, precompile it as required by your deployment, and include it only on the print page. The getting-started guide calls for loading paged.polyfill.js in a document served by a web server, because the polyfill must fetch the document’s CSS.

Browser preview with the polyfill

  1. Create the print endpoint and stylesheet.
  2. Make the page reachable over HTTP(S); opening a local file directly can prevent CSS and font requests from working.
  3. Load the Paged.js polyfill after the document’s stylesheets, using the delivery method selected for your Rails app.
  4. Open the endpoint in a browser and wait for pagination to finish. Inspect page breaks, missing assets and console errors.
  5. Use the browser’s Print or Save as PDF command. Select the intended paper size, margins, scale and background options in that dialog.

Paged.js performs its transformation in the page, so images, fonts and CSS must resolve from URLs the browser can access. Use absolute or correctly rooted asset URLs when the page may be rendered outside the normal Rails host.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Optional readiness indicator

Do not make a controller assume that the document is paginated merely because the initial HTML loaded. Add a small client-side indicator or disable the print button until the polyfill has completed, using the event or API exposed by the Paged.js version you installed. Confirm that API against the package documentation; event names are version-sensitive.

Automated PDFs with the Paged.js CLI

The CLI guide documents installing pagedjs-cli and pagedjs, then invoking a command such as:

pagedjs-cli index.html -o result.pdf

The CLI launches a headless browser and runs Paged.js automatically. The guide is dated 2019, so check current package installation, supported Node.js and browser-runtime requirements before using this command in production.

Make Rails content available to the renderer

There are three practical patterns:

  • Public or signed URL: point the CLI at the print endpoint. This is simplest, but protect private data with a short-lived signature and HTTPS.
  • Exported HTML: render the Rails view to a file and rewrite asset URLs so the headless browser can fetch CSS, fonts and images.
  • Application worker: enqueue a job that invokes the CLI, captures its exit status and stores the PDF outside the request cycle.

Whichever pattern you choose, test the exact runtime environment. A URL that works in your development browser may fail in a worker because of DNS, authentication, firewall rules, CSP, missing fonts or expiring credentials.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Run the CLI from a Rails job

# app/jobs/render_report_pdf_job.rb
class RenderReportPdfJob < ApplicationJob
  queue_as :default

  def perform(report_id)
    report = Report.find(report_id)
    input = Rails.root.join("tmp", "report-#{report.id}.html")
    output = Rails.root.join("tmp", "report-#{report.id}.pdf")

    File.write(input, ApplicationController.render(
      template: "reports/print",
      layout: "print",
      assigns: { report: report }
    ))

    success = system("pagedjs-cli", input.to_s, "-o", output.to_s)
    raise "Paged.js failed" unless success && File.exist?(output)

    report.pdf.attach(io: File.open(output), filename: "report-#{report.id}.pdf")
  ensure
    File.delete(input) if input && File.exist?(input)
    File.delete(output) if output && File.exist?(output)
  end
end

For production, prefer a process-spawning API that avoids shell interpolation, set a job timeout, capture stderr, and clean temporary files on failure. Large documents should run outside the web request with bounded concurrency.

CSS first, JavaScript hooks when necessary

Keep page size, breaks, counters and running content in CSS whenever possible. Paged.js also documents handlers and hooks for transformations that cannot reasonably be expressed in source markup or CSS, such as modifying content during parsing or layout. Read the handlers and hooks documentation and verify method names against your installed version; that page is dated 2020.

Use a hook for a specific, tested requirement—for example, adding a generated label to a page header—not as a replacement for basic print CSS. Keep custom code isolated from your Rails application JavaScript so it cannot alter ordinary interactive pages.

Rails and Paged.js troubleshooting

The polyfill does not paginate

  • Confirm the page is served over HTTP(S), not opened as a file:// URL.
  • Check that the script actually loaded in the browser network panel and that its asset URL was precompiled.
  • Look for JavaScript exceptions caused by loading a module as a classic script, or vice versa.
  • Verify that the stylesheet is reachable and contains print rules. A blocked CSS request leaves Paged.js without the layout information it needs.

Images, fonts or styles are missing in a PDF

  • Use URLs resolvable from the headless browser, not paths that exist only on the Rails server’s filesystem.
  • Check authentication, CSP, CORS and mixed-content errors.
  • Wait for the assets to load before invoking the CLI or capture process; lazy-loaded images may require an explicit trigger in your page.
  • Install the fonts in the renderer’s operating-system image and use deterministic font stacks.

The CLI works locally but fails in a worker

  • Install the same Node.js, CLI and headless-browser dependencies in the worker image.
  • Log the command’s stderr and exit status, and use an absolute executable path if PATH differs.
  • Check sandbox permissions, shared-memory limits and outbound network access.
  • Make temporary input/output directories writable and clean them after both success and failure.

Page breaks differ between preview and automation

Use the same Paged.js version, stylesheet, viewport assumptions and font files in both paths. Browser print settings affect the interactive Save as PDF flow, while CLI flags and runtime defaults affect automation. Compare generated HTML and computed styles before changing break rules.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Performance, reliability and security checklist

  • Cache stable CSS, fonts and images, but invalidate cached assets when their content changes.
  • Generate large PDFs asynchronously and report job progress instead of holding an HTTP request open.
  • Bound concurrent headless-browser processes; each consumes CPU and memory.
  • Record the Paged.js, CLI, Node.js and browser versions used for a PDF so a later regeneration is explainable.
  • Sanitize user-authored HTML and constrain outbound requests to prevent server-side request forgery when rendering URLs.
  • Set explicit timeouts and fail closed when required assets or pages do not load.

Or skip the browser setup

If your requirement is simply to obtain a clean screenshot or PDF of a URL, ScreenshotNeo provides a website screenshot API and MCP server. It removes cookie-consent banners, newsletter popups and chat widgets before capture; bot checks, blank pages, failed loads and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP tools—take_screenshot, get_page_info and capture_pdf—work with Claude, Cursor and other MCP clients.

For a one-call image request, see the ScreenshotNeo documentation:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo supports full-page and element captures, 12 device presets plus custom viewports, retina scale, PDF paper and page-range controls, custom CSS and JavaScript, click and wait conditions, request blocking, headers and cookies, timezone and geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage reporting and an OpenAPI specification. Its parameter names are compatible with those used by other screenshot APIs, which can simplify migration.

The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Every feature is available on every plan, and yearly billing provides two months free. Create a free ScreenshotNeo account.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

FAQ

Does Rails have an official Paged.js integration?

No. Rails documents asset delivery and Paged.js documents its browser and CLI workflows separately, so your application must connect those pieces.

Should a user-facing report use the CLI?

Usually not. The browser polyfill gives an immediate preview and lets the user control the browser’s print dialog; reserve the CLI for repeatable, unattended generation.

Can I use Paged.js hooks for every layout rule?

Hooks are intended for document-specific transformations. Prefer print CSS for ordinary page sizing, breaks, counters and running content.

Frequently Asked Questions

Does Rails have an official Paged.js integration?

No. Rails documents asset delivery and Paged.js documents its browser and CLI workflows separately, so your application must connect those pieces.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Should a user-facing report use the CLI?

Usually not. The browser polyfill gives an immediate preview and lets the user control the browser’s print dialog; reserve the CLI for repeatable, unattended generation.

Can I use Paged.js hooks for every layout rule?

Hooks are intended for document-specific transformations. Prefer print CSS for ordinary page sizing, breaks, counters and running content.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.