# Lite Engine PinchTab includes a **Lite Engine** that performs DOM capture — navigate, snapshot, text extraction, click, and type — without requiring Chrome or Chromium. It is powered by [Gost-DOM](https://github.com/gost-dom/browser) (v0.11.0, MIT), a headless browser written in pure Go. **Issue:** [#201](https://github.com/pinchtab/pinchtab/issues/201) --- ## Why a Lite Engine? Chrome is the default execution backend for PinchTab. A real browser session handles JavaScript rendering, bot-detection bypass, screenshots, and PDF generation. For many workloads — static sites, wikis, news articles, APIs — none of these are needed. | Driver | Chrome | Lite | |--------|--------|------| | Memory per instance | ~200 MB | ~10 MB | | Cold-start latency | 1–6 seconds | <100 ms | | JavaScript rendering | yes | no | | Screenshots / PDF | yes | no | | No Chrome installation required | no | **yes** | Lite wins at DOM-only workloads (3–4× faster navigate, 3× faster snapshot) and is the right choice for containers, CI pipelines, and edge environments where Chrome is not available. --- ## Architecture ### Engine Interface All engines implement a common interface defined in `internal/engine/engine.go`: ```go type Engine interface { Name() string Navigate(ctx context.Context, url string) (*NavigateResult, error) Snapshot(ctx context.Context, filter string) ([]SnapshotNode, error) Text(ctx context.Context) (string, error) Click(ctx context.Context, ref string) error Type(ctx context.Context, ref, text string) error Capabilities() []Capability Close() error } ``` The Chrome engine wraps the existing CDP/chromedp pipeline. `LiteEngine` in `internal/engine/lite.go` implements the same interface using Gost-DOM. ### Router (Strategy Pattern) ``` Request → Router → [Rule 1] → [Rule 2] → … → [Fallback Rule] → Engine ``` `Router` in `internal/engine/router.go` evaluates an ordered chain of `RouteRule` implementations. The first rule that returns a non-`Undecided` verdict wins. Rules are registered at startup and are hot-swappable via `AddRule()` / `RemoveRule()`. No handler, bridge, or config change is needed when adding new routing logic — only a `RouteRule` implementation and a single `router.AddRule(myRule)` call. ### Built-in Rules | Rule | File | Behaviour | |------|------|-----------| | `CapabilityRule` | `rules.go` | Routes `screenshot`, `pdf`, `evaluate`, `cookies` → Chrome | | `ContentHintRule` | `rules.go` | Routes URLs ending in `.html/.htm/.xml/.txt/.md` → Lite | | `DefaultLiteRule` | `rules.go` | Catch-all: all remaining DOM ops → Lite (used in `lite` mode) | | `DefaultChromeRule` | `rules.go` | Final fallback → Chrome (used in `chrome` and `auto` modes) | ### Three Modes | Mode | Behaviour | |------|-----------| | `chrome` | All requests go through Chrome. Backward-compatible default. | | `lite` | DOM operations (navigate, snapshot, text, click, type) use Gost-DOM. Screenshot / PDF / evaluate / cookies fall through to Chrome (501 if Chrome is unavailable). | | `auto` | Per-request routing via rules: capability and content-hint rules are evaluated first; unknown URLs fall back to Chrome. | --- ## Request Flow (Lite Mode) ``` POST /navigate (server.engine=lite) │ ▼ handlers/navigation.go — HandleNavigate() │ ├─ useLite() == true │ │ │ ▼ │ LiteEngine.Navigate(ctx, url) │ ├─ HTTP GET url │ ├─ Strip