# Rust Workspace

> Design Rust project topology — single-crate packages, project-sized multi-crate workspaces (small root-flat, hybrid/domain-grouped, contained crates/, nested, or root-package layouts), workspace-level configuration, dependency DAGs, and crate-boundary decisions. Use when users ask how to split a project into crates, choose paths from the resulting project scale instead of copying a source-language module tree, configure a workspace, avoid dependency cycles, refactor a mixed root-package workspace, or decide between modules and crates. For in-crate src/ layout, see rust-module-layout.

- Skill: `full-stack-skills/rust-workspace` (Agent Skill, multi-file: 22 files)
- Install (CLI): `npx skillmds@latest add full-stack-skills/rust-workspace`
- Raw SKILL.md: https://api.skillmd.com/api/skills/full-stack-skills/rust-workspace/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: full-stack-skills (https://skillmd.com/u/full-stack-skills)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/full-stack-skills/rust-workspace

---


# Rust Workspace and Project Topology

> Authority: [Cargo Book — Workspaces](https://doc.rust-lang.org/cargo/reference/workspaces.html), [The Book ch7](https://doc.rust-lang.org/book/ch07-00-managing-growing-projects-with-packages-crates-and-modules.html) and [ch14-03](https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html), [Rust Reference ch7](https://doc.rust-lang.org/reference/items/modules.html), [RFC 1525](https://rust-lang.github.io/rfcs/1525-cargo-workspace.html), [matklad — Large Rust Workspaces](https://matklad.github.io/2021/08/22/large-rust-workspaces.html).

This skill decides **how many crates a project should have and how they relate**. Its companion `rust-module-layout` decides **what lives inside one crate's `src/`**.

## Capability Boundaries

### ✅ Strengths
1. Single-crate vs multi-crate workspace decision (decision tree with five concrete triggers)
2. Project-driven workspace layouts: small root-flat, hybrid/domain-grouped, contained `crates/`, nested, and root-package
3. Virtual manifest vs root package — trade-offs and migration
4. Workspace-level shared configuration: `[workspace.package]`, `[workspace.dependencies]`, `[workspace.lints]`
5. Dependency direction DAGs — types → core → sdk → server → binary
6. Diagnosing and refactoring the "mixed root package" anti-pattern
7. Crate naming, publishing, and version coordination across members

### ⚠️ Prerequisites
1. Rust ownership and basic module syntax — see `rust-stable`
2. In-crate module layout (lib.rs facade, mod declarations, visibility) — see `rust-module-layout`

### ❌ Out of Scope
1. Cargo.toml `[dependencies]` syntax and feature resolution → use `rust-cargo-build`
2. In-crate src/ directory layout → use `rust-module-layout`
3. Rust syntax fundamentals → use `rust-stable`
4. Testing organization → use `rust-testing`

## When to Use

- "Should I split this into a workspace or keep it one crate?"
- "How do I configure a Cargo workspace?"
- "Refactor my rbatis-style mixed root package"
- "Why does cargo only build one crate at the root?"
- "How do I share dependencies across workspace members?"
- "Is my dependency direction correct?"

## Data Privacy

This skill does not collect, store, or transmit any user data.

---

# Foundations — Packages, Crates, Modules

> In-crate module layout depth (mod files, visibility, re-exports) is covered by the companion `rust-module-layout` skill. This section covers only the parts that affect project-level decisions.

### Package vs crate vs workspace

| Term | Meaning |
|------|---------|
| **Package** | One `Cargo.toml` and the source it points at; what you publish to crates.io |
| **Crate** | A compilation unit — either a library (`src/lib.rs`) or a binary (`src/main.rs`, `src/bin/*.rs`). A package can contain multiple crates (1 lib + N binaries). |
| **Workspace** | A collection of packages sharing one `Cargo.lock` and `target/`. |
| **Module** | A nameable scope inside a crate — declared with `mod foo;`, resolved to `src/foo.rs` or `src/foo/mod.rs`. |

### Single-package layouts

```text
# Library only                      # Binary only                  # Library + binary
my-lib/                             my-app/                        my-crate/
├── Cargo.toml                      ├── Cargo.toml                 ├── Cargo.toml
└── src/                            └── src/                       └── src/
    └── lib.rs                          └── main.rs                 ├── lib.rs
                                                                      └── main.rs

# Multi-binary (one package, multiple binaries)
my-app/
├── Cargo.toml
└── src/
    ├── lib.rs
    ├── main.rs                      # binary named after the package
    └── bin/
        ├── tool_a.rs                # binary `tool_a`
        └── tool_b.rs                # binary `tool_b`
```

### Module declaration (the rule that surprises Java/Python devs)

```rust
// src/lib.rs — declare modules explicitly; directories are NOT auto-discovered
pub mod front_of_house;      // loads src/front_of_house.rs OR src/front_of_house/mod.rs
mod back_of_house;           // private
pub(crate) mod utils;        // crate-visible
```

Everything is **private by default**; `pub` exposes. See `rust-module-layout` for the full visibility model, the parent-bound reachability rule, and the modern `foo.rs + foo/` layout.

### `use` paths (quick reference)

```rust
use crate::front_of_house::hosting;       // absolute (current crate)
use std::collections::HashMap;            // absolute (external)
use self::back_of_house::Cook;            // relative (current module)
use super::parent_module::helper;         // relative (parent)
use std::{cmp::Ordering, io};             // nested
use std::fmt::Result as FmtResult;        // alias
pub use crate::front_of_house::hosting;   // re-export (facade pattern)
```

### Conditional compilation

```rust
#[cfg(target_os = "linux")]
fn only_linux() {}

#[cfg(feature = "serde")]
fn with_serde() {}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
struct Config;

if cfg!(target_os = "linux") { /* runtime check */ }
```

# Project Scaffolding

```bash
cargo new my-app              # Binary project
cargo new my-lib --lib        # Library project
cargo init                    # Initialize current directory
```

For multi-crate workspaces, create the root virtual manifest by hand (there is no `cargo workspace new`), choose the member topology from the decision model below, then run `cargo new --lib <selected-member-path>`. For a small root-flat workspace that may be `cargo new --lib my-core`; for a contained large workspace it may be `cargo new --lib crates/my-core`. For templates, use [`cargo-generate`](https://github.com/cargo-generate/cargo-generate).

---

# Workspace Patterns (single-crate vs multi-crate)

> Authority: [Cargo Book — Workspaces](https://doc.rust-lang.org/cargo/reference/workspaces.html), [The Book ch14-03](https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html), [matklad — Large Rust Workspaces](https://matklad.github.io/2021/08/22/large-rust-workspaces.html), [RFC 1525](https://rust-lang.github.io/rfcs/1525-cargo-workspace.html).

A **workspace** is a collection of one or more packages that share a single `Cargo.lock` and `target/` directory. Workspaces exist for four reasons: **faster builds** (shared dependency compilation), **coordinated versions** (one lockfile, one `cargo publish` flow), **cleaner boundaries** (each crate is an independent compilation unit with its own public API), and **independent reuse** (users can depend on one crate without pulling in the others).

## Decision tree — how many crates?

```
Is this project one cohesive library or one binary?
├── Yes → Single-crate layout (Section 8.1)
└── No, it has multiple subdomains
    ├── Do the subdomains share types and call each other heavily?
    │   └── Single-crate with module directories (use rust-module-layout skill)
    └── At least one subdomain is independently useful / independently versioned / has different deps?
        └── Multi-crate workspace (Section 8.2)
```

**Rule of thumb**: split into crates only when at least one of these is true (from `references/production-workspace-boundaries.md`):
1. The subdomain requires independent publishing or third-party reuse
2. The subdomain needs distinct `feature` / target / `no_std` / WASM boundaries
3. You need to **prohibit** a reverse dependency at compile time (e.g., `core` must not depend on `tokio`)
4. The subdomain has an independently versioned public API
5. Test/build lifecycles are significantly different

If none of these apply, **prefer modules over crates**. Modules are cheaper (no publish, no version coordination, no separate `Cargo.toml`). See the `rust-module-layout` skill for in-crate organization.

## Single-crate layout

The default for small-to-medium projects. One `Cargo.toml`, one `src/`. Four variants: library only, binary only, library + binary (same package), or multi-binary (`src/bin/<name>.rs`). See `examples/single-crate.md` for all four skeletons.

**When to graduate to a workspace**: when a binary or library needs an independent dependency/feature/target boundary, release trajectory, or build/test lifecycle. A second binary alone can remain under `src/bin/` in the same package.

## Multi-crate workspace — two flavors of root

Cargo supports two kinds of root `Cargo.toml`:

| Flavor | What's in root | When to use |
|--------|---------------|-------------|
| **Virtual manifest** | `[workspace]` only — **no `[package]`** | **Default for new workspaces.** Clean root, no top-level `src/`; members may be root-flat, hybrid, or contained. |
| **Root package** | `[workspace]` **+** `[package]` + `src/` at root | Small (2-3 package) workspaces where one package is unambiguously primary; you accept the trade-offs below. |

The Cargo team and community (notably matklad's [Large Rust Workspaces](https://matklad.github.io/2021/08/22/large-rust-workspaces.html)) recommend **virtual manifests** for any non-trivial workspace:

1. **Root pollution** — a `[package]` at the root forces `src/`, `tests/`, `benches/` into the top level alongside every other crate's directory.
2. **Command ergonomics** — with a root package, `cargo build` at the root builds *only* the root package; `--workspace` is needed for everything. Virtual manifests build all members by default.
3. **Publishing friction** — root package + members leads to confusing `cargo publish` ordering.

## Project-driven layout patterns

| Pattern | Layout | When | Used by |
|---------|--------|------|---------|
| **A. Root-flat virtual** | `<member>/` beside root `Cargo.toml` | **Default for small cohesive workspaces**, usually 2-8 packages/members | [Tokio](https://github.com/tokio-rs/tokio), [Serde](https://github.com/serde-rs/serde), [Clap](https://github.com/clap-rs/clap) |
| **B. Hybrid/domain-grouped** | core members at root plus `support/*`, `examples/*`, or another real family | Growing workspaces with stable families or noisy adapters/examples | framework and migration workspaces |
| **C. Contained/grouped** | `crates/<member>/` or `crates/<category>/*` | Large workspaces, multi-language repositories, or roots that need a Rust container | [Bevy](https://github.com/bevyengine/bevy)-style large repositories |
| **D. Nested sub-workspaces** | `vendor/<sub>/` with own `[workspace]` | Git submodule or vendored-workspace isolation (rare) | vendored upstream workspaces |
| **E. Root package** | `[package]` at root plus sibling/contained members | 2-3 packages with one genuinely primary crate | library plus companion CLI |

Workspace member count is a **signal, not a law**. Decide package/crate boundaries first, then consider repository root noise, independent publishing, adapter/plugin families, targets, examples/tests, other languages, and established paths. As a review trigger: 2-8 cohesive packages normally stay root-flat; around 8-20 compare root-flat with a hybrid; 20+ commonly benefits from grouping or `crates/`. Never create one Cargo package per Maven/Gradle module without a Rust boundary reason.

Full skeletons and the decision matrix: `references/workspace-layouts.md`.

### Pattern A skeleton — small workspace default

```text
my-project/
├── Cargo.toml                      # virtual: [workspace]
├── my-core/                        # library
│   ├── Cargo.toml
│   └── src/lib.rs
├── my-net/                         # library
│   └── ...
└── my-cli/                         # binary
    └── src/main.rs
```

```toml
# root Cargo.toml — virtual manifest
[workspace]
resolver = "3"
members = ["my-core", "my-net", "my-cli"]

[workspace.package]
edition = "2024"
version = "0.1.0"
license = "Apache-2.0"

[workspace.dependencies]
serde = { version = "1", features = ["derive"] }   # pin once
my-core = { path = "my-core" }                      # internal deps here
```

```toml
# my-net/Cargo.toml
[package]
name = "my-net"
version.workspace = true               # inherits from [workspace.package]
edition.workspace = true

[dependencies]
serde.workspace = true                 # inherits from [workspace.dependencies]
my-core.workspace = true               # internal workspace dep
```

## The "mixed root package" anti-pattern

A common mistake from developers coming from Java/Maven or Python: putting a real `[package]` with substantial code at the workspace root **while also** having member crates.

```toml
# Cargo.toml — DON'T (anonymized from a real public crate)
[workspace]
members = ["codegen", "macro-driver", "example"]

[package]                            # ❌ root package + workspace together
name = "my_framework"
version = "4.9.6"

[dependencies]
my-codegen = { path = "codegen" }
my-macro-driver = { path = "macro-driver" }
```

```text
my-framework/
├── Cargo.toml                       # 163 lines mixing workspace + package config
├── src/                             # ❌ the root package's source pollutes the root
│   ├── lib.rs                       # 30 lines of `pub use *::*`
│   ├── crud.rs                      # 591 lines (monster file — see rust-module-layout)
│   ├── executor.rs                  # 642 lines
│   └── plugin/
├── codegen/                         # member crate
├── macro-driver/                    # member crate
└── tests/
```

**Five problems**: root pollution, asymmetric commands (`cargo build` builds only the root), coupled versioning, no clear facade (lib.rs becomes a glob re-export hub), and migration is a breaking change once published.

**Refactor target** — virtual manifest with all crates under `crates/`:

```text
my-framework/
├── Cargo.toml                       # virtual manifest — workspace config only
└── crates/
    ├── my-framework/                # was: src/ at root
    │   ├── Cargo.toml
    │   └── src/
    ├── codegen/
    ├── macro-driver/
    └── example/
```

Migration is **mechanical and preserves the published crate name** — full six-step procedure in `references/mixed-root-package-antipattern.md` and a worked example in `examples/migration-mixed-to-virtual.md`.

## Workspace-level shared configuration

Three workspace-level tables eliminate drift across members. See `references/workspace-dependencies.md` for the full syntax.

```toml
# root Cargo.toml
[workspace.package]                  # shared package metadata
version = "0.1.0"
edition = "2024"
rust-version = "1.85"
license = "Apache-2.0"

[workspace.dependencies]             # shared external + internal deps
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
my-core = { path = "crates/core" }

[workspace.lints.rust]               # shared lint config
unsafe_code = "forbid"
missing_docs = "warn"
```

Members opt in with `.workspace = true`:

```toml
# crates/net/Cargo.toml
[package]
name = "my-net"
version.workspace = true             # inherits 0.1.0
edition.workspace = true

[dependencies]
serde.workspace = true               # inherits pinned version + features
my-core.workspace = true

[lints]
workspace = true                     # inherits shared lints
```

## Dependency direction (DAG)

Crate dependencies form a **directed acyclic graph**. Cycles are forbidden (`cargo` will error). Plan direction deliberately.

```text
low-level types ──► domain logic ──► application ──► binary
   (my-types)         (my-core)         (my-server)     (my-cli)
```

**Anti-pattern — leaky direction**:

```toml
# crates/core/Cargo.toml — ❌ core depending on CLI concerns
[dependencies]
clap = "4"                           # CLI lib has no business in core
my-cli = { path = "../cli" }         # core cannot depend on the binary
```

**Verification**:

```bash
cargo tree                                    # visualize the dep graph
cargo tree --invert --package my-core         # what depends on my-core?
```

If `my-types` shows up as depending on anything non-`std`, the direction is wrong. Layering rules in `references/dependency-direction.md`.

## Reference example — `sa-token-rs` (11-crate virtual workspace)

[`sa-token-rs`](https://github.com/dromara/sa-token-rs) is a real-world Rust port of the Java Sa-Token permission framework — an exemplar of every pattern this skill teaches. Virtual manifest, 11 crates, clean 5-layer DAG, `crates/<category>/` grouping, full `[workspace.*]` inheritance.

### Layout (contained + domain-grouped hybrid)

```text
sa-token-rs/
├── Cargo.toml                          # virtual manifest
└── crates/
    ├── sa-token/                       # Layer 3: facade (public API)
    ├── sa-token-core/                  # Layer 1: core types & traits (no internal deps)
    ├── sa-token-derive/                # Layer 2: proc-macro (core only)
    ├── sa-token-context-mock/          # Layer 2: mock context (core only)
    ├── sa-token-dao-memory/            # Layer 2: memory DAO (core only)
    ├── sa-token-dao-redis/             # Layer 4: redis DAO (facade + core)
    ├── sa-token-axum/                  # Layer 4: axum adapter (facade + core)
    ├── sa-token-plugin/                # domain grouping inside container
    │   ├── sa-token-jwt/               # Layer 4: JWT plugin
    │   └── sa-token-sign/              # Layer 4: signature plugin
    ├── sa-token-demo/                  # domain grouping inside container
    │   └── sa-token-demo-axum/         # Layer 5: binary example
    └── sa-token-test/                  # Layer 5: integration tests
```

### DAG — 5 layers, every arrow points up

```text
L1  sa-token-core
      ▲
L2  sa-token-derive   sa-token-context-mock   sa-token-dao-memory
      ▲                      ▲                       ▲
L3  sa-token  (facade — aggregates L2 leaves into one public API)
      ▲
L4  sa-token-dao-redis   sa-token-axum   sa-token-jwt   sa-token-sign
      ▲
L5  sa-token-demo-axum   sa-token-test   (binaries + tests)
```

### Why it's exemplary

1. **Virtual manifest** — no root `[package]`; `cargo build` builds all 11 by default.
2. **Contained + domain-grouped hybrid** — `crates/sa-token-*` for leaves, with plugin and demo families grouped beneath `crates/`.
3. **Full `[workspace.*]` inheritance** — `version`, `edition = "2024"`, `rust-version = "1.85"`, `license`, `repository`, `[workspace.lints]` (`unsafe_code = "forbid"`, `missing_docs = "warn"`, `clippy::pedantic = "warn"`), and `[workspace.dependencies]` for internal + external deps.
4. **Feature-gated optional dep** — `sa-token` exposes `redis = ["dep:sa-token-dao-redis"]`.
5. **Clean DAG** — core has zero internal deps; facade aggregates; adapters/plugins/DAOs sit on top; demos/tests consume everything.

See `references/sa-token-rs-case-study.md` for the full member-by-member Cargo.toml breakdown, DAG verification commands, and how the layout supports independent publishing.

## Workspace commands cheat sheet

```bash
cargo build --workspace               # build every member (default in virtual manifest)
cargo build -p my-core                # build one member
cargo test --workspace                # test every member
cargo check --workspace               # fast type-check everything
cargo doc --workspace --no-deps       # docs for every member
cargo publish -p my-core              # publish one member
cargo run -p my-cli                   # run a specific binary

cargo workspaces version minor       # bump all members in lockstep (needs cargo-workspaces)
cargo workspaces publish              # publish all members in topological order
```

For batch version bumps and publishes across all members, install [`cargo-workspaces`](https://crates.io/crates/cargo-workspaces).

---


## Workflow

1. **Decide project type and crate boundaries** — start single-crate; split only for independent reuse/versioning, dependency or target isolation, or a distinct lifecycle. Otherwise use modules.
2. **Inventory topology signals** — resulting package count, publish units, adapter/plugin families, examples/tests, repository root noise, languages, and compatibility-sensitive existing paths.
3. **Choose a layout** — small cohesive workspace: root-flat; growing workspace with real families: hybrid/domain-grouped; large or multi-language workspace: contained/grouped. Treat counts as review triggers, not hard thresholds.
4. **Pin shared metadata and deps at workspace level** — `[workspace.package]`, `[workspace.dependencies]`, `[workspace.lints]`. Members opt in with `.workspace = true`.
5. **Verify dependency direction** — `cargo tree --invert --package my-core` must show only higher-level crates depending on lower-level ones. No reverse edges, no cycles.
6. **Select naming conventions** — snake_case crate names, kebab-case in `Cargo.toml` `name`. Use full words; avoid 2-letter abbreviations (see `rust-module-layout`'s naming reference).
7. **Validate** — `cargo check --workspace`, `cargo tree`, `cargo doc --workspace --no-deps`. Inspect the generated docs sidebar — it should reflect your intended public API surface.

## Gotchas

1. Distinguish between `crate::` (references the current crate root) and `::other_crate_name::` (absolute path reference to an external crate).
2. Restricted visibility such as `pub(crate)` is not an Edition boundary; verify the project's Rust version rather than assuming Edition 2015 forbids it.
3. Both `module.rs` and `module/mod.rs` are supported; new code typically prefers the former, but do not misinterpret a deprecated warning as an error for using `mod.rs`.
4. Workspace resolver settings apply globally; Edition 2021 defaults to resolver 2, while Edition 2024 defaults to resolver 3.
5. The path argument in `pub(in path)` must point to ancestor modules of the current item and cannot be used to expose visibility across arbitrary sibling modules.
6. Use of the `#[path]` attribute bypasses filesystem conventions — module paths no longer follow default file tree structures after application.
7. **A virtual manifest cannot contain `[dependencies]` or `[package]`.** If you see `failed to parse manifest at ... missing field package`, you've mixed virtual and root-package syntax. Either remove `[package]` (virtual) or add it (root package) — don't half-do both.
8. **`cargo build` at a root-package workspace only builds the root.** Use `--workspace` to build everything. With a virtual manifest, `cargo build` already builds all members — fewer surprises.
9. **Workspace globs match one level only.** `members = ["crates/*"]` does not match `crates/libs/core/`; use `crates/libs/*` or explicit paths. Root-flat members can use explicit names or a carefully scoped glob, but never `members = ["*"]` because it captures non-package directories.
10. **Workspace-internal `path` deps still need versions for publish.** `my-core = { path = "../core", version = "0.1.0" }` — without `version`, `cargo publish` rejects it. Use `[workspace.dependencies]` to keep the version in one place.
11. **Bumping a workspace-shared dep requires editing only the root `Cargo.toml`.** Don't re-pin it in member crates — that defeats the purpose and creates drift.
12. **Renaming a published crate is a breaking change.** Add a deprecated alias crate (`pub use my_new_name::*;`) under the old name for one release cycle before removing it.

## On-Demand Resources

- [Layout Examples](examples/examples.md) — basic module layouts
- [Concept Quick Reference](references/references.md)
- [Workspace Layouts](references/workspace-layouts.md) — project-sized root-flat, hybrid, contained, nested, and root-package skeletons
- [Virtual vs Root Manifest](references/virtual-vs-root-manifest.md) — the decision in depth, with command-ergonomics comparison
- [Mixed Root Package Anti-Pattern](references/mixed-root-package-antipattern.md) — full diagnosis + migration path for rbatis-style layouts
- [Workspace Dependencies](references/workspace-dependencies.md) — `[workspace.package]` / `[workspace.dependencies]` / `[workspace.lints]` in depth
- [Dependency Direction](references/dependency-direction.md) — DAG rules, layering, leaky direction anti-patterns
- [`sa-token-rs` Case Study](references/sa-token-rs-case-study.md) — real-world 11-crate virtual workspace with 5-layer DAG, full member-by-member breakdown, DAG verification, and publishing implications
- [Production-grade workspace boundaries](references/production-workspace-boundaries.md): When splitting protocols, domains, platforms, transports, SDKs, adapters, and binaries, read the relevant sections.
- `examples/golden-layout/`: single-crate CI compilation example
- `examples/golden-workspace/`: small root-flat virtual workspace example with three crates

## Official References

- [The Book ch 7 — Managing Growing Projects](https://doc.rust-lang.org/book/ch07-00-managing-growing-projects-with-packages-crates-and-modules.html)
- [The Book ch14-03 — Cargo Workspaces](https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html)
- [Rust Reference ch 7 (Items)](https://doc.rust-lang.org/reference/items.html)
- [Rust Reference ch 7.2 (Modules)](https://doc.rust-lang.org/reference/items/modules.html)
- [Cargo Book — Workspaces](https://doc.rust-lang.org/cargo/reference/workspaces.html)
- [Cargo Book — `workspace.package`](https://doc.rust-lang.org/cargo/reference/workspaces.html#the-package-table)
- [Cargo Book — Workspace dependencies](https://doc.rust-lang.org/cargo/reference/workspaces.html#the-dependencies-table)
- [RFC 1525 — Cargo Workspaces](https://rust-lang.github.io/rfcs/1525-cargo-workspace.html)
- [matklad — Large Rust Workspaces](https://matklad.github.io/2021/08/22/large-rust-workspaces.html) (community best-practice reference)
- [Rust API Guidelines — Organization (C-HIERARCHY, C-REEXPORT)](https://rust-lang.github.io/api-guidelines/about.html)

