How to Use the Playwright-Style Page Facade in ego-lite

The Playwright-style page facade in ego-lite provides a lightweight, familiar browser automation API through the createPageFacade() function in helpers.ts, exposing familiar methods like page.goto(), page.locator(), and page.screenshot() that delegate to an internal CDP driver layer.

ego-lite is a minimal browser automation runtime that eliminates the heavyweight dependency of full Playwright while preserving its ergonomic API. The page facade is the primary interface developers use to control browser sessions, enabling rapid migration of existing Playwright scripts with minimal code changes.

Architecture of the Page Facade

The facade implementation spans multiple source files, each with a distinct responsibility in the call chain.

Core Construction: createPageFacade()

The facade object is manufactured by createPageFacade() defined in src/helpers.ts at line 684. This factory function constructs an object where each method proxies to the underlying driver helpers:

  • nav – navigation operations (goto, goBack, reload)
  • pointer – mouse movements, clicks, scrolls
  • keyboard – key presses, typing shortcuts
  • element-ops – element queries, attribute extraction, visibility checks

View createPageFacade() implementation

Global Exposure via Helpers Export

Once constructed, the facade is attached to the runtime's global helper context at line 824 in the same file:

// helpers.ts line 824
page: createPageFacade()

This makes page directly available in agent scripts without manual instantiation.

View helpers export

Public API Signatures in format.ts

Method signatures and inline documentation for the facade reside in src/format.ts (lines 32–84). This file serves as the contract definition, specifying:

  • Parameter types and defaults
  • Return type annotations
  • Usage examples for IDE autocomplete

View format.ts signatures

Description and Capabilities

An in-code description at line 810 in helpers.ts documents the facade's strict, auto-waiting behavior:

The facade automatically retries locator operations until elements reach a stable state, eliminating explicit sleep() calls.

View facade description

Driver Layer: Where Facade Methods Execute

All facade methods ultimately delegate to the src/driver/ directory, which communicates with the browser via Chrome DevTools Protocol (CDP):

Driver Module Facade Methods Powered
nav.ts page.goto(), page.goBack(), page.reload(), page.waitForURL()
pointer.ts page.click(), page.hover(), page.scroll()
keyboard.ts page.keyboard.press(), page.keyboard.type()
element-ops.ts page.locator(), page.$(), page.$$()
screencast.ts page.screencast.start(), page.screencast.stop()
screenshot.ts page.screenshot()

The driver layer is orchestrated by browser-runtime.ts, which manages CDP transport, session lifecycle, and event buffering.

Runtime Entry Point: index.ts

The façade is re-exported through src/index.ts (lines 41–53), making it available to the CLI entry point and programmatic API consumers.

View index.ts exports

Practical Code Examples

// Navigate with timeout and wait for network idle
await page.goto('https://example.com', { timeout: 15000 });
await page.waitForLoadState('networkidle');

// Extract page metadata
console.log('Current URL:', await page.url());
console.log('Page title:', await page.title());

Locator-Based Interactions

// Fill forms using CSS selectors
await page.locator('input[name="search"]').fill('ego-lite');
await page.locator('button[type="submit"]').click();

// Text-based locators with exact matching
await page.getByText('Search Results', { exact: true }).waitFor();

// Chain locators for precision
await page.locator('nav').getByRole('link', { name: 'Documentation' }).click();

Keyboard Shortcuts and Special Keys

// Native keyboard shortcuts
await page.keyboard.type('Ctrl+L');  // Focus address bar
await page.keyboard.press('Enter');

// Sequential key presses
await page.keyboard.press('Tab');
await page.keyboard.type('hello world');

Visual Capture

// Static screenshot
await page.screenshot({ path: 'capture.png', fullPage: true });

// Video recording (screencast)
await page.screencast.start({
  path: 'session.webm',
  size: { width: 1280, height: 720 }
});
// ... perform actions ...
await page.screencast.stop();

Advanced Waiting Patterns

// Wait for URL pattern
await page.waitForURL(url => url.pathname.startsWith('/dashboard'), {
  timeout: 10000
});

// Wait for specific network response
await page.waitForResponse(resp =>
  resp.status() === 200 && resp.url().includes('/api/data')
);

// Wait for element state
await page.locator('.loading-spinner').waitFor({ state: 'hidden' });

Key Behavioral Guarantees

Guarantee Implementation Source
Auto-retry on locator actions helpers.ts line 812 description
Consistent async/await API All facade methods return Promises for browser-communicating operations
Playwright parity format.ts signatures match Playwright's public API
Zero Playwright dependency Direct CDP driver layer eliminates native module requirements

Migration from Full Playwright

Scripts written for standard Playwright require minimal adaptation:

  • Remove import statements: page is globally injected by ego-lite's runtime
  • Adjust launch configuration: Browser instances are managed by the runtime, not chromium.launch()
  • Preserve method calls: Core APIs like page.goto(), page.locator(), and page.screenshot() remain identical

Summary

  • The page facade is constructed by createPageFacade() in helpers.ts (line 684) and exposed globally at line 824
  • Public API contracts live in format.ts (lines 32–84), ensuring Playwright-compatible method signatures
  • Actual browser control delegates to src/driver/ modules (nav.ts, pointer.ts, keyboard.ts, element-ops.ts)
  • The facade provides auto-waiting, retry-based element interaction without explicit sleeps
  • Migration from Playwright is streamlined due to deliberate API parity

Frequently Asked Questions

What is the difference between ego-lite's page facade and full Playwright?

ego-lite's facade implements the most commonly used Playwright methods but executes them through a lightweight CDP driver rather than Playwright's native binary stack. This eliminates ~150MB of dependencies while preserving the ergonomic API. Methods like page.goto(), page.locator(), and page.screenshot() behave identically, though advanced features like browser contexts and multiple pages per context have simplified implementations.

How do I access the page object in my ego-lite scripts?

The page object is automatically injected into the global scope by the runtime. No import or instantiation is required. According to the source in helpers.ts line 824, the runtime calls createPageFacade() and assigns the result to page before your script executes.

Where are the actual browser commands implemented?

Facade methods proxy to the driver layer in src/driver/. Navigation maps to nav.ts, pointer actions to pointer.ts, keyboard input to keyboard.ts, and element queries to element-ops.ts. These modules serialize commands to CDP and deserialize responses, as coordinated by browser-runtime.ts.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →