Contributions to OxideSEO are welcome. This document describes the contribution process and expectations.
For local development setup, see DEVELOPMENT.md. For architecture details, see ARCHITECTURE.md.
- Check existing issues and PRs to avoid duplicate work
- For non-trivial changes, open an issue first to discuss the approach
- For bug fixes, include steps to reproduce in the issue or PR description
See DEVELOPMENT.md for prerequisites, installation, and common workflows.
Create branches from main following this pattern:
| Prefix | Use |
|---|---|
feat/ |
New features |
fix/ |
Bug fixes |
refactor/ |
Code restructuring |
docs/ |
Documentation changes |
test/ |
Test additions or changes |
chore/ |
Tooling, dependencies, CI |
perf/ |
Performance improvements |
This project follows Conventional Commits:
<type>(<scope>): <short summary>
Types: feat, fix, refactor, test, docs, chore, perf, ci
Scopes: crawler, rules, storage, frontend, ipc, ci, export, ai, plugin
Examples:
feat(crawler): add streaming body read with blake3 hashing
fix(rules): handle missing viewport meta on frameset pages
refactor(storage): extract query builder for paginated results
test(frontier): add property-based tests for dedup consistency
The changelog is generated from these messages via git-cliff. Maintainers generate the changelog; contributors do not need git-cliff installed.
- Create a feature branch from
main - Make your changes following the code style guidelines below
- Add or update tests for behavioral changes
- Ensure all checks pass locally:
# Frontend
npm run lint
npm run format:check
npm run typecheck
npm run test
# Rust (from src-tauri/)
cd src-tauri
cargo fmt --all -- --check
cargo clippy --all-targets -- -D warnings
cargo test- Open a PR against
mainwith:- A clear description of what changed and why
- Link to the related issue (if any)
- Screenshots for UI changes
Every PR must pass before merge:
| Check | Command | Runs On |
|---|---|---|
| Rust format | cargo fmt --all -- --check |
Ubuntu, macOS, Windows |
| Rust lint | cargo clippy --all-targets --all-features -- -D warnings |
Ubuntu, macOS, Windows |
| Rust tests | cargo test --lib --all-features |
Ubuntu, macOS, Windows |
| Frontend lint | npm run lint |
Ubuntu |
| Frontend format | npm run format:check |
Ubuntu |
| Frontend typecheck | npm run typecheck |
Ubuntu |
| Frontend tests | npm run test |
Ubuntu |
- All code must pass
cargo fmtandcargo clippywith zero warnings - Use
anyhow::Result<T>with.context()for error propagation in internal code - Return
Result<T, String>at the Tauri command boundary (map with.map_err(|e| format!("{e:#}"))) - No
unwrap(),expect(), orpanic!()outside of tests - Use
///doc comments on public items - Import order:
std-> external crates ->crate::internal imports, separated by blank lines
- All code must pass ESLint (zero warnings) and Prettier
- No
anytype. Useunknownand narrow with type guards. - Use function declarations for components:
export function MyComponent(), not arrow assignments - Use
cn()fromlib/utils.tsfor conditional Tailwind class merging
Types that cross the Tauri IPC boundary must be updated in both languages simultaneously:
- Rust: struct with
#[serde(rename_all = "camelCase")] - TypeScript: interface in
src/types/index.ts
- Use Tailwind utility classes exclusively
- Use CSS custom properties (
var(--color-*)) for theme-aware colors - Use shadcn/ui primitives for standard UI patterns
- Bug fixes should include a regression test
- New rules should include tests with HTML fixture
ParsedPagestructs - New commands should include tests for the Rust handler
- Aim for behavioral coverage, not line coverage
Open an issue with:
- Steps to reproduce
- Expected vs. actual behavior
- OS and app version
- Relevant error messages or screenshots
Open an issue describing:
- The problem you are trying to solve
- Your proposed solution
- Alternatives you considered
By contributing, you agree that your contributions will be licensed under the project's dual MIT / Apache 2.0 license.