1- # Gosub: A new browser engine made from scratch
1+ # Gosub Browser Engine
22
3- This repository holds the Gosub browser engine. It will become a standalone library that can be used by other projects
4- but will ultimately be used by the Gosub browser user-agent. See the [ About] ( #about ) section for more information.
3+ An embeddable, async browser engine written in Rust.
54
65Join us at our development [ Zulip chat] ( https://chat.developer.gosub.io ) !
76
@@ -12,163 +11,213 @@ If you are interested in contributing to Gosub, please check out the [contributi
1211
1312## About
1413
15- This repository is part of the Gosub browser engine project. This is the main engine that holds the following components:
14+ Gosub is a modular, embeddable browser engine. The primary entry point is ` GosubEngine ` in the
15+ [ ` gosub_engine ` ] ( crates/gosub_engine ) crate. You provide a render backend and a compositor; the
16+ engine owns a multi-zone/tab model, an async networking stack, cookie and storage isolation per
17+ zone, and an event bus. Your user-agent (UA) drives everything via ` TabCommand ` and reacts to
18+ ` EngineEvent ` .
1619
17- - HTML5 tokenizer / parser
18- - CSS3 tokenizer / parser
19- - Document tree
20- - Several APIs for connecting to javascript
21- - Configuration store
22- - Networking stack
23- - Rendering engine
24- - JS bridge
20+ ** Core components:**
2521
26- More will follow as the engine grows. The idea is that this engine will receive some kind of stream of bytes (most likely
27- from a socket or file) and parse this into a valid HTML5 document tree and CSS stylesheets.
28- From that point, it can be fed to a renderer engine that will render the document tree into a window, or it can be fed
29- to a more simplistic engine that will render it in a terminal. JS can be executed on the document tree and the document
30- tree can be modified by JS.
22+ | Crate | Role |
23+ | ---| ---|
24+ | ` gosub_engine ` | ` GosubEngine ` — the unified entry point |
25+ | ` gosub_html5 ` | HTML5 tokenizer / parser |
26+ | ` gosub_css3 ` | CSS3 tokenizer / parser |
27+ | ` gosub_net ` | Networking stack (async, streaming, per-zone) |
28+ | ` gosub_taffy ` | Layout engine (Taffy/flexbox) |
29+ | ` gosub_cairo ` | Cairo / GTK4 render backend |
30+ | ` gosub_vello ` | Vello / wgpu render backend |
31+ | ` gosub_js ` | JS bridge |
32+ | ` gosub_config ` | Configuration store |
3133
3234
3335## Status
3436
35- > This project is in its infancy. There is no usable browser yet. However, you can look at simple html pages and parse
36- > them into a document tree and do some initial rendering.
37+ The engine is under active development. What works today:
3738
38- We can parse HTML5 and CSS3 files into a document tree or the respective css tree. This tree can be shown in the terminal
39- or be rendered in a very unfinished renderer. Our renderer cannot render everything yet, but it can render simple html
40- pages, sort of.
39+ - ** Multi-zone / multi-tab model** — zones isolate cookies and storage; tabs are controlled via ` TabCommand `
40+ - ** Async networking** — streaming HTTP fetcher with priority queues, inflight coalescing, redirect handling, and per-zone cookie isolation
41+ - ** Event-driven UA interface** — ` EngineEvent ` (navigation, resource, redraw) flows out; ` TabCommand ` / ` EngineCommand ` flow in
42+ - ** HTML5 and CSS3 parsing** — spec-compliant parsers for both
43+ - ** Pluggable render backends** — Null (headless), Cairo (GTK4), Vello (wgpu)
4144
42- We already implemented other parts of the engine, for a JS engine, networking stack, a configuration store and other
43- things however these aren't integrated yet. You can try these out by running the respective binary.
45+ What is still in progress:
4446
45- We can render a part for our own [ site] ( https://gosub.io ) :
47+ - Full page layout and rendering pipeline (the render backends receive geometry but pixel-perfect output is incomplete)
48+ - JavaScript execution integration
49+ - Accessibility tree
4650
47- ![ Gosub.io] ( resources/images/current_progress.png )
4851
52+ ## Quick start
4953
50- ## How to run
54+ Add ` gosub_engine ` to your ` Cargo.toml ` :
5155
52- <details >
53- <summary > Installing dependencies </summary >
56+ ``` toml
57+ [dependencies ]
58+ gosub_engine = { git = " https://github.com/gosub-io/gosub-engine" , package = " gosub_engine" }
59+ tokio = { version = " 1" , features = [" full" ] }
60+ ```
5461
55- This project uses [ cargo] ( https://doc.rust-lang.org/cargo/ ) and [ rustup] ( https://www.rust-lang.org/tools/install ) . First
56- you must install ` rustup ` at the link provided. After installing ` rustup ` , run:
62+ Then drive the engine from async code:
63+
64+ ``` rust
65+ use std :: sync :: {Arc , RwLock };
66+ use gosub_engine :: {EngineConfig , GosubEngine , EngineError };
67+ use gosub_engine :: render :: {DefaultCompositor , Viewport };
68+ use gosub_engine :: render :: backends :: null :: NullBackend ;
69+ use gosub_engine :: events :: {EngineEvent , TabCommand };
70+ use gosub_engine :: storage :: {StorageService , InMemoryLocalStore , InMemorySessionStore , PartitionPolicy };
71+ use gosub_engine :: cookies :: DefaultCookieJar ;
72+ use gosub_engine :: zone :: {ZoneConfig , ZoneServices };
73+ use gosub_engine :: tab :: TabDefaults ;
74+
75+ #[tokio:: main]
76+ async fn main () -> Result <(), EngineError > {
77+ let backend = NullBackend :: new (). expect (" backend" );
78+ let mut engine = GosubEngine :: new (
79+ Some (EngineConfig :: default ()),
80+ Arc :: new (backend ),
81+ Arc :: new (RwLock :: new (DefaultCompositor :: default ())),
82+ );
83+ engine . start (). expect (" start" );
84+
85+ let mut events = engine . subscribe_events ();
86+
87+ let services = ZoneServices {
88+ storage : Arc :: new (StorageService :: new (
89+ Arc :: new (InMemoryLocalStore :: new ()),
90+ Arc :: new (InMemorySessionStore :: new ()),
91+ )),
92+ cookie_store : None ,
93+ cookie_jar : Some (DefaultCookieJar :: new (). into ()),
94+ partition_policy : PartitionPolicy :: None ,
95+ };
96+ let mut zone = engine . create_zone (ZoneConfig :: default (), services , None )? ;
97+
98+ let tab = zone . create_tab (TabDefaults {
99+ viewport : Some (Viewport :: new (0 , 0 , 1280 , 800 )),
100+ .. Default :: default ()
101+ }, None ). await ? ;
102+
103+ tab . send (TabCommand :: Navigate { url : " https://example.com" . into () }). await ? ;
104+
105+ while let Ok (ev ) = events . recv (). await {
106+ match ev {
107+ EngineEvent :: Navigation { tab_id , event } => println! (" [{tab_id}] {event:?}" ),
108+ EngineEvent :: Redraw { tab_id , .. } => println! (" [{tab_id}] frame ready" ),
109+ _ => {}
110+ }
111+ }
112+
113+ engine . shutdown (). await ? ;
114+ Ok (())
115+ }
116+ ```
57117
58- If you want to use a specific version of rust:
118+ See [ ` examples/hello-world.rs ` ] ( examples/hello-world.rs ) for a fuller walkthrough, and
119+ [ ` examples/multi-tab.rs ` ] ( examples/multi-tab.rs ) for a 25-tab stress test with a live progress UI.
59120
60- ``` bash
61- $ rustup toolchain install 1.82
62- $ rustup default 1.82
63- $ rustc --version
64- rustc 1.82.0 (f6e511eec 2024-10-15)
65- ```
66121
67- or you can use the latest version:
122+ ## Running the examples
123+
124+ <details >
125+ <summary >Installing dependencies</summary >
126+
127+ This project uses [ cargo] ( https://doc.rust-lang.org/cargo/ ) and [ rustup] ( https://www.rust-lang.org/tools/install ) .
128+ Install ` rustup ` , then:
68129
69130``` bash
70- $ rustup default stable
71- $ rustc --version
72- rustc 1.92.0 (ded5c06cf 2025-12-08)
73- (or a higher version if available)
131+ rustup default stable
74132```
75133
76- You also should have following OS packages installed :
134+ For the GTK4-based examples you also need these OS packages (Ubuntu / Debian) :
77135
78136```
79- make
80- gcc
81- g++
82- libglib2.0-dev
83- libcairo2-dev
84- libpango1.0-dev
85- libgdk-pixbuf-2.0-dev
86- libgraphene-1.0-dev
87- libgtk-4-dev
137+ make gcc g++
138+ libglib2.0-dev libcairo2-dev libpango1.0-dev
139+ libgdk-pixbuf-2.0-dev libgraphene-1.0-dev libgtk-4-dev
88140libsqlite3-dev
89141```
90142
91- or equivalent for non-ubuntu based systems.
92-
93-
94- Once Rust is installed, run this command to pre-build the dependencies:
143+ Clone and build:
95144
96145``` bash
97- $ git clone https://github.com/gosub-io/gosub-engine.git
98- $ cd gosub-engine
99- $ cargo build --release
146+ git clone https://github.com/gosub-io/gosub-engine.git
147+ cd gosub-engine
148+ cargo build
100149```
101150</details >
102151
152+ ### Engine examples (no GUI required)
103153
104- You can run the following binaries (these will not output much useful information yet, as the engine is still in development):
154+ | Command | Description |
155+ | ---| ---|
156+ | ` cargo run --example hello-world ` | Single tab — navigate a URL, stream events to stdout |
157+ | ` cargo run --example multi-tab ` | 25 tabs navigating random sites; live progress bars via ` indicatif ` |
105158
106- | Command | Type | Description |
107- | ----------------------------------------| ------| -----------------------------------------------------------------------------------------------------------------------------------------------------------------|
108- | ` cargo run -r --bin config-store` | bin | A simple test application of the config store for testing purposes |
109- | ` cargo run -r --bin css3-parser` | bin | Show a parsed css tree from an url |
110- | ` cargo run -r --bin display-text-tree` | bin | A simple parser that will try and return a textual presentation of the website |
111- | ` cargo run -r --bin gosub-parser` | bin | The actual html5 parser/tokenizer that allows you to convert html5 into a document tree. |
112- | ` cargo run -r --bin html5-parser-test` | test | A test suite that tests all html5lib tests for the treebuilding |
113- | ` cargo run -r --bin parser-test` | test | A test suite for the parser that tests specific tests. This will be removed as soon as the parser is completely finished as this tool is for developement only. |
114- | ` cargo run -r --bin run-js` | bin | Run a JS file (Note: console and event loop are not yet implemented) |
159+ ### GUI examples
115160
116- For running the binaries, take a look at a quick introduction at [/docs/binaries.md](/docs/binaries.md)
161+ | Command | Description |
162+ | ---| ---|
163+ | ` cargo run --example gtk-cairo ` | GTK4 / Cairo window |
164+ | ` cargo run --example egui-vello ` | egui / Vello / wgpu window |
117165
118- There are also a bit more advanced examples that can be run that will try and display some graphics:
166+ ### Component tools (individual crate testing)
119167
120- | Command | Description |
121- | --------------------------------------------| --------------------------------------------------------------|
122- | ` cargo run --example gtk-renderer < url> ` | A GUI based on GTK4 / Cairo that displays a webpage |
123- | ` cargo run --example vello-renderer < url> ` | A GUI based on Winit / Vello that displays a webpage |
124- | ` cargo run --example html5-parser` | A simple example that displays a dom tree from a html source |
168+ | Command | Description |
169+ | ---| ---|
170+ | ` cargo run --bin gosub-parser ` | HTML5 parser / tokenizer — prints a document tree |
171+ | ` cargo run --bin css3-parser ` | CSS3 parser — prints a CSS tree from a URL |
172+ | ` cargo run --bin display-text-tree ` | Text-only render of a page |
173+ | ` cargo run --bin config-store ` | Config store smoke test |
174+ | ` cargo run --bin run-js ` | Run a JS file (event loop not yet implemented) |
175+ | ` cargo run --bin html5-parser-test ` | html5lib tree-builder test suite |
176+ | ` cargo run --bin parser-test ` | Parser development test runner |
125177
178+ For more detail on the component tools see [ /docs/binaries.md] ( /docs/binaries.md ) .
126179
127- # # Benchmark and test suites
128180
129- To run the tests and benchmark suite, do:
181+ ## Tests and benchmarks
130182
131183``` bash
132184make test
133185cargo bench
134- ls target/criterion/report
135- index.html
186+ # open target/criterion/report/index.html
136187```
137188
138- # # Wasm
139189
140- Our engine can also be compiled to WebAssembly. You need to use WasmPack for this. To build the Wasm version, run:
190+ ## WebAssembly
191+
192+ The engine can be compiled to WebAssembly via ` wasm-pack ` :
141193
142194``` bash
143195wasm-pack build --target web
144196```
145197
146- Afterwards you need to serve the small useragent around the wasm version in the ` wasm/` directory. You can do this by
198+ Then serve the thin UA wrapper in ` wasm/ ` :
147199
148200``` bash
149201cd wasm
150- npm run dev # you can also use `bun run dev`
151- ` ` `
202+ bun run dev # or: npm run dev
203+ ```
152204
153- To use this demo, you need to enable webgpu in chromium and disable the same origin policy.
205+ To run the demo you need a Chromium with WebGPU enabled:
154206
155207``` bash
156- chromium --disable-web-security --enable-features=Vulkan --enable-unsafe-webgpu --user-data-dir=/tmp/chromium-temp-profile
157- ` ` `
158-
159- This command works on Linux only, if someone uses Windows or macOS, please open an PR!
160-
161- And then you have it! A browser in a browser:
208+ # Linux only — PRs welcome for Windows / macOS
209+ chromium --disable-web-security --enable-features=Vulkan \
210+ --enable-unsafe-webgpu --user-data-dir=/tmp/chromium-temp-profile
211+ ```
162212
163213![ Browser in browser] ( resources/images/browser-wasm-hackernews.png )
164214
165215
166- # # Contributing to the project
167-
168- We welcome contributions to this project but the current status makes that we are spending a lot of time researching,
169- building small proof-of-concepts and figuring out what needs to be done next. Much time of a contributor at this stage
170- of the project will be non-coding.
216+ ## Contributing
171217
172- We do like to hear from you if you are interested in contributing to the project and you can join us currently at
218+ We welcome contributions. Because the engine is still taking shape, a lot of work is exploratory
219+ — building proofs-of-concept, reading specs, and making architectural decisions — rather than
220+ pure coding.
173221
174- our [Zulip chat](https://chat.developer.gosub.io)!
222+ Join us on [ Zulip] ( https://chat.developer.gosub.io ) or [ Discord] ( https://chat.gosub.io ) before
223+ diving in; it will save you time and help us keep things coordinated.
0 commit comments