Contributing to servo-fetch
August 2, 2026 · View on GitHub
Thank you for considering contributing to servo-fetch.
If your contribution is not straightforward, please open an issue first to discuss the change before submitting a PR.
Development setup
Requires Rust 1.88.0+ (see rust-version in Cargo.toml).
git clone https://github.com/konippi/servo-fetch
cd servo-fetch
cargo build
First build takes several minutes due to Servo compilation.
Useful commands
cargo run -- "https://example.com" # Markdown output
cargo run -- "https://example.com" --format json # JSON output
cargo run -- "https://example.com" --format png -o page.png # Screenshot
cargo run -- "https://example.com" --js "document.title" # JS execution
cargo test # Run tests
cargo test -- --ignored # Run Servo+network tests (slow)
cargo clippy # Lint (pedantic)
cargo +nightly fmt # Format
cargo deny check # License & advisory check
taplo fmt # Format TOML files (install: cargo install taplo-cli --locked)
typos # Spell check
For exact CI parity (with --locked, CI profile, etc.), use these cargo aliases:
cargo lint # CI cargo-clippy
cargo test-ci # CI cargo-test (unit/integration)
cargo test-doc # CI cargo-test (doc)
cargo test-e2e # CI e2e (Servo-backed)
Build/test run on stable. Format requires nightly rustfmt for unstable
imports_granularity/group_imports; one-time:rustup toolchain install nightly --component rustfmt --profile minimal.
Profiling
cargo build --profile profiling produces a release-optimized binary with debug symbols and thin LTO for use with cargo flamegraph or perf record.
Coverage
cargo install cargo-llvm-cov
cargo llvm-cov --lib --tests
Benchmark harness (Python)
The benchmark harness in benchmarks/ is a separate Python package managed with uv. Requires Python 3.11+.
cd benchmarks
uv sync --group dev # Install deps
uv run pytest # Run tests
uv run ruff check src tests tools # Lint
./benchmarks/bench all # Full benchmark suite (~25 min)
See benchmarks/README.md for the full guide.
Language bindings
The bindings live outside the cargo workspace and each has its own dev loop and README. The single source of truth for versions is [workspace.package].version in Cargo.toml (bumped by release-plz); the Node package.json versions are 0.0.0-development placeholders that the release workflow fills from the release tag, so they never need hand-editing.
Python (bindings/python/) — uv, Python 3.11+:
cd bindings/python
uv sync --group all --no-install-project # venv + dev deps
uv run --no-sync maturin develop # build the extension
uv run --no-sync pytest # tests
uv run --no-sync ruff check python tests && uv run --no-sync ty check python # lint + types
Node (bindings/node/) — pnpm, Node 22+:
cd bindings/node
pnpm install
pnpm run build # tsdown → dist (ESM + CJS + d.ts)
pnpm test # vitest
pnpm run typecheck && pnpm run lint # tsc + biome
Commit conventions
This project uses Conventional Commits. The CHANGELOG.md is generated from these by release-plz.
feat: add PDF output support
fix: handle empty body in extract
refactor: simplify bridge error handling
Breaking changes
Mark breaking changes with ! in the subject — for example, feat(api)!: split sync and async or refactor(error)!: rename Error::Timeout. The subject marker keeps the breaking nature visible in commit logs, PR titles, and the auto-generated changelog.
Pull request guidelines
- Keep PRs focused on a single change
- Ensure
cargo clippy,cargo +nightly fmt --check, andcargo testpass with zero warnings - Run
cargo test -- --ignoredif your change affects Servo integration or network behavior - Update documentation if behavior changes
Use of AI
AI tools (e.g. Claude Code, Kiro) can be useful for generating code. However, you remain responsible for any code you publish, and we are responsible for any code we merge and release. A few expectations:
- Human in the loop. Do not submit pull requests created autonomously by AI agents. We will close any PR we believe was created without a human author who understands the change.
- Write PR descriptions and replies yourself. Describe the change and reply to review comments in your own words. Do not paste AI output as a reply to maintainers. We may hide comments we believe are AI-generated.
- Disclose AI context when you quote it. If you paste output from an AI tool into an issue or PR, put it in a
>quote block and add your own commentary explaining why it is relevant.
Issue labels
We use four label categories:
type: *— what kind of work, aligned with Conventional Commits:type: bug,type: feature,type: docs,type: refactor,type: perf,type: test,type: deps,type: ci,type: build,type: security- component — area of the codebase:
cli,mcp,skill,benchmark - status — workflow state:
good first issue,help wanted,needs triage,needs info - resolution — closing reason:
duplicate,wontfix
Start with good first issue if you are new to the project.
Labels are declared in .github/labels.yml and synced by the Sync Labels workflow. To propose a new label, open a PR editing that file.
Reporting bugs
Please use the bug report template and include:
- Steps to reproduce
- Expected vs actual behavior
- Output of
servo-fetch --version - OS info
License
By contributing, you agree that your contributions will be licensed under the MIT License.