draft_forge
Rails engine for exporting HTML or Editor.js JSON to PDF. Can be paired with any front-end or used standalone.
Requires Ruby 3.1 or higher. See CHANGELOG for release notes.
Installation
Copy an initializer and migration into your application:
bin/rails generate draft_forge:install
Attempting to use DraftForge's services before running the generator and migrating will log an error directing you to install and migrate.
Mounting
Expose DraftForge's endpoints by mounting the engine in your application's routes:
# config/routes.rb
Rails.application.routes.draw do
mount DraftForge::Engine => "/draft_forge"
end
This provides POST /draft_forge to queue a PDF export and
GET /draft_forge/:id to check status or download the finished file.
Services
If you prefer not to expose HTTP endpoints, you can queue and fetch exports directly with service objects:
export = DraftForge::CreateExport.call(
content_json: { blocks: [{ type: 'paragraph', data: { text: 'Hello world' } }] },
filename: "hello.pdf"
)
DraftForge::FetchExport.call(export.id)
# => { id: 1, status: "queued" }
# Render HTML directly to a PDF without queuing
file = DraftForge::PdfRenderer.call("<p>Hello</p>")
file.close!
Configuration
DraftForge exposes simple configuration hooks for PDF rendering and HTML
sanitization. The sanitizer controls which HTML elements (blocks) are allowed,
letting you distinguish between editable and non-editable content. By default
the sanitizer permits the contenteditable attribute so sanitized markup can
be used in live editors.
# config/initializers/draft_forge.rb
DraftForge.configure do |config|
# Change page size/margins for Grover
config. = { format: 'Letter' }
# Permit additional HTML elements
config.sanitizer_config[:elements] += %w[hr]
end
Performance
ExportPdfJob streams generated PDFs to a temporary file before attaching, keeping memory usage low even for very large, 100+ page exports.
Testing
Run the RSpec suite from this directory to verify changes:
bundle exec rspec