browse_servo

Hex.pmHex DocsCILicense: MIT

BrowseServo is a Rustler-backed Elixir browser runtime for Elixir applications that want an idiomatic browser API with a native process boundary and a Servo-backed execution engine.

It follows the same shared-interface pattern used by Chrona: BrowseServo implements the shared Browse browser contract over a Servo-backed native runtime.

The architectural boundary is:

📦 Installation

def deps do
  [
    {:browse_servo, "~> 0.1.0-dev"}
  ]
end

For development in this repository:

mise install
mix setup

🧭 Usage

Start a browser runtime directly

{:ok, browser} = BrowseServo.start_link()

Use the browser contract directly

:ok = BrowseServo.Browser.navigate(browser, "https://example.com/docs")
{:ok, url} = BrowseServo.Browser.current_url(browser)
{:ok, html} = BrowseServo.Browser.content(browser)
{:ok, value} = BrowseServo.Browser.evaluate(browser, "document.title")
{:ok, image} = BrowseServo.Browser.capture_screenshot(browser, format: "png")

Use Browse-backed pools

Configure pools through BrowseServo:

config :browse_servo,
  default_pool: MyApp.BrowseServoPool,
  pools: [
    MyApp.BrowseServoPool: [pool_size: 2]
  ]

Add the configured pools to your supervision tree:

children = BrowseServo.children()

Or start one pool directly:

children = [
  {BrowseServo.BrowserPool, name: MyApp.BrowseServoPool, pool_size: 2}
]

Check out a warm browser from the pool:

BrowseServo.checkout(fn browser ->
  :ok = BrowseServo.Browser.navigate(browser, "https://example.com")
  BrowseServo.Browser.capture_screenshot(browser, format: "png")
end)

🧩 Native Layer

BrowseServo.Native uses RustlerPrecompiled, so published releases ship precompiled NIFs and downstream users do not need Rust or Cargo installed.

During local development the 0.1.0-dev version force-builds the NIF from source.

The native crate links directly against Servo from the upstream Servo repository, pinned to a specific commit in native/browse_servo_native/Cargo.toml.

For repository development, mise.toml also pins Python 3.12 because current Servo code generation requires Python 3.11+.

📡 Telemetry

BrowseServo emits telemetry events aligned with browse_chrome:

BrowseServo also emits operation-specific browser events under the [:browse_servo, :browser, ...] prefix for:

Operation-level events are emitted as spans, so consumers get :start, :stop, and :exception events with timing metadata.

📄 License

MIT