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, scrollskeyboard– key presses, typing shortcutselement-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.
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
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.
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.
Practical Code Examples
Navigation and Page State
// 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:
pageis 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(), andpage.screenshot()remain identical
Summary
- The page facade is constructed by
createPageFacade()inhelpers.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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →