|
| 1 | +# Contributing to Oxide |
| 2 | + |
| 3 | +Thank you for your interest in contributing to Oxide — the world's first decentralized, binary-first browser. Whether you're fixing a typo, adding a host function, building an example app, or proposing an entirely new subsystem, every contribution matters. |
| 4 | + |
| 5 | +## Table of Contents |
| 6 | + |
| 7 | +- [Getting Started](#getting-started) |
| 8 | +- [Project Structure](#project-structure) |
| 9 | +- [Development Workflow](#development-workflow) |
| 10 | +- [Coding Guidelines](#coding-guidelines) |
| 11 | +- [Adding a Host Function](#adding-a-host-function) |
| 12 | +- [Building a Guest App](#building-a-guest-app) |
| 13 | +- [Pull Request Process](#pull-request-process) |
| 14 | +- [Issue Labels & Bounties](#issue-labels--bounties) |
| 15 | +- [Contributor Tiers & Rewards](#contributor-tiers--rewards) |
| 16 | +- [Community](#community) |
| 17 | +- [Code of Conduct](#code-of-conduct) |
| 18 | + |
| 19 | +--- |
| 20 | + |
| 21 | +## Getting Started |
| 22 | + |
| 23 | +### Prerequisites |
| 24 | + |
| 25 | +- **Rust** (stable, latest) — [install via rustup](https://rustup.rs/) |
| 26 | +- **wasm32-unknown-unknown** target |
| 27 | + |
| 28 | +```bash |
| 29 | +rustup toolchain install stable |
| 30 | +rustup target add wasm32-unknown-unknown |
| 31 | +``` |
| 32 | + |
| 33 | +### Clone and Build |
| 34 | + |
| 35 | +```bash |
| 36 | +git clone https://github.com/niklabh/oxide.git |
| 37 | +cd oxide |
| 38 | + |
| 39 | +# Build the browser |
| 40 | +cargo build -p oxide-browser |
| 41 | + |
| 42 | +# Build an example guest app |
| 43 | +cargo build --target wasm32-unknown-unknown --release -p hello-oxide |
| 44 | + |
| 45 | +# Run the browser |
| 46 | +cargo run -p oxide-browser |
| 47 | +``` |
| 48 | + |
| 49 | +### Run Tests |
| 50 | + |
| 51 | +```bash |
| 52 | +cargo test --workspace |
| 53 | +``` |
| 54 | + |
| 55 | +### Verify Formatting & Lints |
| 56 | + |
| 57 | +```bash |
| 58 | +cargo fmt --all -- --check |
| 59 | +cargo clippy --workspace --all-targets -- -D warnings |
| 60 | +``` |
| 61 | + |
| 62 | +--- |
| 63 | + |
| 64 | +## Project Structure |
| 65 | + |
| 66 | +``` |
| 67 | +oxide/ |
| 68 | +├── oxide-browser/ # Host browser application (Rust, egui) |
| 69 | +│ └── src/ |
| 70 | +│ ├── main.rs # eframe bootstrap |
| 71 | +│ ├── engine.rs # WasmEngine, SandboxPolicy |
| 72 | +│ ├── runtime.rs # BrowserHost, fetch/load/instantiate |
| 73 | +│ ├── capabilities.rs # Host functions registered into wasmtime Linker |
| 74 | +│ ├── navigation.rs # History stack, back/forward |
| 75 | +│ ├── url.rs # WHATWG-style URL parser |
| 76 | +│ └── ui.rs # egui UI — toolbar, canvas, console, widgets |
| 77 | +├── oxide-sdk/ # Guest-side SDK (no_std compatible, pure FFI) |
| 78 | +│ └── src/ |
| 79 | +│ ├── lib.rs # Safe Rust wrappers over host imports |
| 80 | +│ └── proto.rs # Zero-dependency protobuf codec |
| 81 | +├── examples/ |
| 82 | +│ ├── hello-oxide/ # Minimal interactive guest app |
| 83 | +│ └── fullstack-notes/ # Full-stack example (Rust frontend + backend) |
| 84 | +├── oxide-landing/ # Landing page (static HTML/CSS/JS) |
| 85 | +├── ROADMAP.md # Phased development roadmap |
| 86 | +├── Security.md # Security policy and bug bounty scope |
| 87 | +└── Cargo.toml # Workspace root |
| 88 | +``` |
| 89 | + |
| 90 | +### Key Crates |
| 91 | + |
| 92 | +| Crate | What it does | When to touch it | |
| 93 | +|---|---|---| |
| 94 | +| `oxide-browser` | The host runtime — compiles WASM, registers host functions, renders UI | Adding capabilities, fixing sandbox bugs, improving the UI | |
| 95 | +| `oxide-sdk` | The guest SDK — safe wrappers around `oxide::*` imports | Exposing new host functions to guest apps | |
| 96 | +| `examples/*` | Example guest applications | Demonstrating features, onboarding new contributors | |
| 97 | + |
| 98 | +--- |
| 99 | + |
| 100 | +## Development Workflow |
| 101 | + |
| 102 | +1. **Fork** the repository and create a branch from `main`. |
| 103 | +2. **Name your branch** descriptively: `feat/audio-api`, `fix/memory-leak-canvas`, `docs/sdk-examples`. |
| 104 | +3. **Make small, focused commits.** Each commit should compile and pass tests. |
| 105 | +4. **Write tests** for new functionality when applicable. |
| 106 | +5. **Run the full check suite** before pushing: |
| 107 | + |
| 108 | +```bash |
| 109 | +cargo fmt --all |
| 110 | +cargo clippy --workspace --all-targets -- -D warnings |
| 111 | +cargo test --workspace |
| 112 | +``` |
| 113 | + |
| 114 | +6. **Open a pull request** against `main`. |
| 115 | + |
| 116 | +--- |
| 117 | + |
| 118 | +## Coding Guidelines |
| 119 | + |
| 120 | +### Rust Style |
| 121 | + |
| 122 | +- Follow standard Rust idioms and the [Rust API Guidelines](https://rust-lang.github.io/api-guidelines/). |
| 123 | +- Run `cargo fmt` before every commit. The CI will reject unformatted code. |
| 124 | +- Zero `clippy` warnings. If a lint is genuinely a false positive, suppress it with `#[allow(...)]` and a comment explaining why. |
| 125 | +- Prefer `&str` over `String` in function parameters. |
| 126 | +- Prefer returning `Result` or `Option` over panicking. |
| 127 | + |
| 128 | +### Naming Conventions |
| 129 | + |
| 130 | +| Entity | Convention | Example | |
| 131 | +|---|---|---| |
| 132 | +| Host function (in `capabilities.rs`) | `api_<category>_<action>` | `api_canvas_rect`, `api_audio_play` | |
| 133 | +| SDK wrapper (in `oxide-sdk/src/lib.rs`) | `<category>_<action>` | `canvas_rect`, `audio_play` | |
| 134 | +| FFI import (in SDK) | `_api_<name>` | `_api_canvas_rect` | |
| 135 | +| Constants | `UPPER_SNAKE_CASE` | `KEY_ENTER`, `MAX_MEMORY_PAGES` | |
| 136 | +| Types/Structs | `PascalCase` | `FetchResponse`, `UploadedFile` | |
| 137 | + |
| 138 | +### Documentation |
| 139 | + |
| 140 | +- Every public function in the SDK must have a doc comment (`///`). |
| 141 | +- Host functions in `capabilities.rs` should have a brief comment explaining the guest-visible behavior. |
| 142 | +- Non-obvious design decisions should be documented inline. |
| 143 | + |
| 144 | +### Security |
| 145 | + |
| 146 | +- **Never expose filesystem, environment, or raw socket access** to guest modules. |
| 147 | +- All data crosses the host–guest boundary through `(ptr, len)` pairs in linear memory. Validate lengths before reading. |
| 148 | +- New capabilities must be explicitly registered — the sandbox is additive by design. |
| 149 | +- When in doubt, open a discussion before implementing. |
| 150 | + |
| 151 | +--- |
| 152 | + |
| 153 | +## Adding a Host Function |
| 154 | + |
| 155 | +This is the most common type of contribution. Here's the end-to-end process: |
| 156 | + |
| 157 | +### 1. Register the host function in `capabilities.rs` |
| 158 | + |
| 159 | +```rust |
| 160 | +linker.func_wrap("oxide", "api_my_feature", |mut caller: Caller<'_, HostState>, arg: u32| -> u32 { |
| 161 | + // Read from guest memory if needed |
| 162 | + // Perform host-side logic |
| 163 | + // Write results back to guest memory if needed |
| 164 | + 0 // return value |
| 165 | +})?; |
| 166 | +``` |
| 167 | + |
| 168 | +### 2. Add the FFI import in `oxide-sdk/src/lib.rs` |
| 169 | + |
| 170 | +```rust |
| 171 | +#[link(wasm_import_module = "oxide")] |
| 172 | +extern "C" { |
| 173 | + #[link_name = "api_my_feature"] |
| 174 | + fn _api_my_feature(arg: u32) -> u32; |
| 175 | +} |
| 176 | +``` |
| 177 | + |
| 178 | +### 3. Add the safe wrapper in `oxide-sdk/src/lib.rs` |
| 179 | + |
| 180 | +```rust |
| 181 | +/// Brief description of what this does. |
| 182 | +pub fn my_feature(arg: u32) -> u32 { |
| 183 | + unsafe { _api_my_feature(arg) } |
| 184 | +} |
| 185 | +``` |
| 186 | + |
| 187 | +### 4. Add an example or update an existing one |
| 188 | + |
| 189 | +Show the new API in action in `examples/hello-oxide/src/lib.rs` or create a new example. |
| 190 | + |
| 191 | +### 5. Update documentation |
| 192 | + |
| 193 | +- Add the function to the capability table in `README.md`. |
| 194 | +- Update `DOCS.md` if it exists. |
| 195 | + |
| 196 | +--- |
| 197 | + |
| 198 | +## Building a Guest App |
| 199 | + |
| 200 | +Guest apps are regular Rust libraries compiled to `wasm32-unknown-unknown`. |
| 201 | + |
| 202 | +### Scaffold |
| 203 | + |
| 204 | +```bash |
| 205 | +cargo new --lib my-app |
| 206 | +cd my-app |
| 207 | +``` |
| 208 | + |
| 209 | +### `Cargo.toml` |
| 210 | + |
| 211 | +```toml |
| 212 | +[package] |
| 213 | +name = "my-app" |
| 214 | +version = "0.1.0" |
| 215 | +edition = "2021" |
| 216 | + |
| 217 | +[lib] |
| 218 | +crate-type = ["cdylib"] |
| 219 | + |
| 220 | +[dependencies] |
| 221 | +oxide-sdk = { path = "../oxide-sdk" } |
| 222 | +``` |
| 223 | + |
| 224 | +### `src/lib.rs` |
| 225 | + |
| 226 | +```rust |
| 227 | +use oxide_sdk::*; |
| 228 | + |
| 229 | +#[no_mangle] |
| 230 | +pub extern "C" fn start_app() { |
| 231 | + canvas_clear(30, 30, 46, 255); |
| 232 | + canvas_text(20.0, 40.0, 28.0, 255, 255, 255, "Hello, Oxide!"); |
| 233 | +} |
| 234 | +``` |
| 235 | + |
| 236 | +### Build and Run |
| 237 | + |
| 238 | +```bash |
| 239 | +cargo build --target wasm32-unknown-unknown --release |
| 240 | +# Open the .wasm file in the Oxide browser |
| 241 | +``` |
| 242 | + |
| 243 | +--- |
| 244 | + |
| 245 | +## Pull Request Process |
| 246 | + |
| 247 | +1. **Fill out the PR template** (if one exists) or include: |
| 248 | + - **What** — a concise summary of the change |
| 249 | + - **Why** — motivation, linked issue number |
| 250 | + - **How** — implementation approach, trade-offs |
| 251 | + - **Testing** — what you tested and how |
| 252 | + |
| 253 | +2. **Keep PRs focused.** One feature or fix per PR. Large PRs are harder to review and more likely to stall. |
| 254 | + |
| 255 | +3. **CI must pass.** The PR will be checked for: |
| 256 | + - `cargo fmt` — formatting |
| 257 | + - `cargo clippy` — lints |
| 258 | + - `cargo test` — unit and integration tests |
| 259 | + - `cargo build --target wasm32-unknown-unknown` — SDK compiles for WASM |
| 260 | + |
| 261 | +4. **Request a review.** Tag a maintainer or let the auto-assignment handle it. |
| 262 | + |
| 263 | +5. **Address feedback promptly.** If changes are requested, push follow-up commits (don't force-push during review). |
| 264 | + |
| 265 | +6. **Squash on merge.** We squash-merge to keep history clean. Your commit message will become the merge commit message. |
| 266 | + |
| 267 | +--- |
| 268 | + |
| 269 | +## Issue Labels & Bounties |
| 270 | + |
| 271 | +### Labels |
| 272 | + |
| 273 | +| Label | Meaning | |
| 274 | +|---|---| |
| 275 | +| `good first issue` | Great for newcomers — well-scoped, low complexity | |
| 276 | +| `help wanted` | Open for community contributions | |
| 277 | +| `phase:N` | Belongs to roadmap Phase N (see [ROADMAP.md](ROADMAP.md)) | |
| 278 | +| `bounty:small` | $OXIDE token reward — small scope | |
| 279 | +| `bounty:medium` | $OXIDE token reward — medium scope | |
| 280 | +| `bounty:large` | $OXIDE token reward — large scope | |
| 281 | +| `bug` | Something isn't working | |
| 282 | +| `enhancement` | New feature or improvement | |
| 283 | +| `security` | Security-related (see [Security.md](Security.md)) | |
| 284 | +| `docs` | Documentation improvements | |
| 285 | +| `sdk` | Changes to `oxide-sdk` | |
| 286 | +| `browser` | Changes to `oxide-browser` | |
| 287 | + |
| 288 | +### Claiming a Bounty |
| 289 | + |
| 290 | +1. Comment on the issue to claim it. First-come, first-served. |
| 291 | +2. A maintainer will assign you within 24 hours. |
| 292 | +3. Submit a PR within the agreed timeframe (usually 2 weeks for small, 4 weeks for large). |
| 293 | +4. Once merged, the bounty is distributed to your provided Solana wallet address. |
| 294 | + |
| 295 | +--- |
| 296 | + |
| 297 | +## Contributor Tiers & Rewards |
| 298 | + |
| 299 | +We recognize and reward contributors through a tiered system backed by the $OXIDE token. |
| 300 | + |
| 301 | +| Tier | Criteria | Perks | |
| 302 | +|---|---|---| |
| 303 | +| **Explorer** | First merged PR | Welcome NFT badge, listed on contributors page | |
| 304 | +| **Builder** | 5+ merged PRs | Monthly $OXIDE airdrop, Discord role, early access to features | |
| 305 | +| **Core** | Consistent contributor, deep domain expertise | Larger $OXIDE allocation, governance voting weight, roadmap input | |
| 306 | +| **Architect** | Major feature or subsystem owner | Grant funding, co-author credit, conference sponsorship | |
| 307 | + |
| 308 | +### Reward Types |
| 309 | + |
| 310 | +- **PR bounties** — one-time token payment for issues tagged `bounty:*` |
| 311 | +- **Code review rewards** — tokens for thorough, quality reviews |
| 312 | +- **Documentation rewards** — tokens for guides, tutorials, API docs |
| 313 | +- **Translation rewards** — tokens for i18n contributions |
| 314 | +- **Bug bounty** — tiered rewards for security vulnerabilities (see [Security.md](Security.md)) |
| 315 | + |
| 316 | +Rewards are distributed on Solana. Provide your wallet address in your GitHub profile or PR description. |
| 317 | + |
| 318 | +--- |
| 319 | + |
| 320 | +## Community |
| 321 | + |
| 322 | +- **Telegram** — [t.me/oxide_browser](https://t.me/oxide_browser) — general chat, questions, support |
| 323 | +- **X (Twitter)** — [@ForgeX_ai](https://x.com/ForgeX_ai) — announcements, updates |
| 324 | +- **GitHub Discussions** — feature proposals, architecture discussions, RFC-style threads |
| 325 | + |
| 326 | +### Getting Help |
| 327 | + |
| 328 | +If you're stuck: |
| 329 | + |
| 330 | +1. Search existing issues and discussions first. |
| 331 | +2. Ask in the Telegram group — the community is friendly and responsive. |
| 332 | +3. Open a GitHub Discussion for design questions or broad topics. |
| 333 | +4. Open an Issue for specific bugs or well-defined feature requests. |
| 334 | + |
| 335 | +--- |
| 336 | + |
| 337 | +## Code of Conduct |
| 338 | + |
| 339 | +We are committed to providing a welcoming and inclusive experience for everyone. All participants are expected to: |
| 340 | + |
| 341 | +- **Be respectful.** Disagreements are fine; personal attacks are not. |
| 342 | +- **Be constructive.** Provide actionable feedback, not just criticism. |
| 343 | +- **Be patient.** Not everyone has the same background or experience level. |
| 344 | +- **Be collaborative.** We're building something together. |
| 345 | + |
| 346 | +Harassment, discrimination, and toxic behavior will not be tolerated. Violations may result in removal from the project. |
| 347 | + |
| 348 | +For concerns, contact [nikhil@polkassembly.io](mailto:nikhil@polkassembly.io). |
| 349 | + |
| 350 | +--- |
| 351 | + |
| 352 | +## License |
| 353 | + |
| 354 | +By contributing to Oxide, you agree that your contributions will be licensed under the same license as the project. |
| 355 | + |
| 356 | +--- |
| 357 | + |
| 358 | +*Thank you for helping build the future of the decentralized web.* |
0 commit comments