# How to Use Topcoat’s Iconify Integration for Vendoring Icons

> Learn to use Topcoat's Iconify integration to vendor icons. Enable the icon-iconify feature, stage icon sets, and embed thousands of SVG icons as compile-time constants with iconify::include! or iconify_icon!.

- Repository: [Tokio/topcoat](https://github.com/tokio-rs/topcoat)
- Tags: how-to-guide
- Published: 2026-07-31

---

**Enable the `icon-iconify` feature in both runtime and build dependencies, stage your desired icon sets via `BuildConfig` in [`build.rs`](https://github.com/tokio-rs/topcoat/blob/main/build.rs), then import them using `iconify::include!` or `iconify_icon!` to embed thousands of SVG icons as compile-time constants.**

The tokio-rs/topcoat framework provides first-class support for the Iconify ecosystem, allowing you to vendor any open-source icon set directly into your Rust binary. By leveraging the **Iconify integration for vendoring icons**, you eliminate runtime network requests and ship offline-capable, style-aware SVG components. The workflow downloads JSON definitions during compilation and exposes them as type-safe `IconData` constants ready for the `icon` component.

## Enable the Feature in Cargo.toml

To access the Iconify tooling, you must activate the `icon-iconify` feature for both the runtime crate (to render icons) and the build crate (to stage icon sets).

Add the following to your [`Cargo.toml`](https://github.com/tokio-rs/topcoat/blob/main/Cargo.toml):

```toml
[dependencies]
topcoat = { version = "0.5", features = ["icon-iconify"] }

[build-dependencies]
topcoat = { version = "0.5", default-features = false, features = ["icon-iconify"] }

```

The runtime dependency enables the `iconify` module re-exported in [[`crates/topcoat/src/icon.rs`](https://github.com/tokio-rs/topcoat/blob/main/crates/topcoat/src/icon.rs)](https://github.com/tokio-rs/topcoat/blob/main/crates/topcoat/src/icon.rs), while the build dependency compiles the staging logic defined in [[`crates/topcoat-icon/src/iconify/config.rs`](https://github.com/tokio-rs/topcoat/blob/main/crates/topcoat-icon/src/iconify/config.rs)](https://github.com/tokio-rs/topcoat/blob/main/crates/topcoat-icon/src/iconify/config.rs).

## Stage Icon Sets with build.rs

Create a [`build.rs`](https://github.com/tokio-rs/topcoat/blob/main/build.rs) file in your project root to download and cache the icon JSON files. The `BuildConfig` API lets you specify which sets to stage, where to cache them, and which versions to pin.

```rust
// build.rs
#[cfg(feature = "icon-iconify")]
fn main() {
    topcoat::icon::iconify::BuildConfig::new()
        .icon_set("feather")          // Stage the Feather icon set
        .stage()
        .expect("Failed to stage Iconify set");
}

#[cfg(not(feature = "icon-iconify"))]
fn main() {}

```

The first build downloads [`feather.json`](https://github.com/tokio-rs/topcoat/blob/main/feather.json) from the Iconify CDN and stores it in the default cache directory (or your configured path). Subsequent builds reuse the cached copy, supporting fully offline builds once the files are vendored. For version pinning or custom cache locations, see the configuration options below.

## Import Icons into Your Application

Once staged, you can expose icons in your source code using one of two macros. Both resolve at compile time to `IconData` structs defined in the framework's icon system.

### Using `iconify::include!` for Full Sets

The `include!` macro generates a Rust module containing one constant per icon in the set. This is ideal when you reference many icons from the same set.

```rust
use topcoat::icon::{icon, iconify};

// Creates a `feather` module with constants like `TRASH_2`, `ARROW_LEFT`, etc.
iconify::include!("feather");

async fn render(cx: &Cx) -> Result {
    view! {
        // Access via generated constant
        icon(data: feather::TRASH_2, label: "Delete")
    }
}

```

### Using `iconify_icon!` for Single Icons

For one-off usage, the `iconify_icon!` macro expands a `"set:name"` string directly into an `IconData` constant without generating a module.

```rust
use topcoat::icon::{icon, iconify};

const TRASH: IconData = iconify::iconify_icon!("feather:trash-2");

view! {
    icon(data: TRASH, label: "Delete")
}

```

This approach is documented in [[`crates/topcoat-icon/macro/docs/iconify_icon.md`](https://github.com/tokio-rs/topcoat/blob/main/crates/topcoat-icon/macro/docs/iconify_icon.md)](https://github.com/tokio-rs/topcoat/blob/main/crates/topcoat-icon/macro/docs/iconify_icon.md) and produces identical bytecode to the module-based approach.

## Configure Caching and Version Pinning

The `BuildConfig` struct in [[`crates/topcoat-icon/src/iconify/config.rs`](https://github.com/tokio-rs/topcoat/blob/main/crates/topcoat-icon/src/iconify/config.rs)](https://github.com/tokio-rs/topcoat/blob/main/crates/topcoat-icon/src/iconify/config.rs) exposes additional methods to control vendoring behavior.

**Custom cache directory:**

```rust
topcoat::icon::iconify::BuildConfig::new()
    .cache_dir("assets/icons")    // Store JSON files in your project tree
    .icon_set("feather")
    .stage()
    .unwrap();

```

**Pin a specific version:**

```rust
topcoat::icon::iconify::BuildConfig::new()
    .icon_set_version("feather", "1.0.0")  // Pin to npm-style version tag
    .icon_set("feather")
    .stage()
    .unwrap();

```

These options allow you to commit vendored icon files to version control, ensuring reproducible builds even if the upstream Iconify CDN is unavailable.

## Summary

- **Enable** the `icon-iconify` feature in both `[dependencies]` and `[build-dependencies]` in [`Cargo.toml`](https://github.com/tokio-rs/topcoat/blob/main/Cargo.toml).
- **Stage** icon sets by calling `BuildConfig::new().icon_set("name").stage()` inside [`build.rs`](https://github.com/tokio-rs/topcoat/blob/main/build.rs).
- **Import** staged icons via `iconify::include!("<set>")` to generate a module of constants, or use `iconify_icon!("<set>:<name>")` for single icons.
- **Render** the resulting `IconData` constants with the `icon` component in your views.
- **Cache** downloaded JSON files locally or vendor them into your repository for offline builds.

## Frequently Asked Questions

### Do I need internet access for every build?

No. The `BuildConfig::stage()` method downloads icons only when the cache is missing or the requested version changes. Once cached, builds proceed offline. You can also check the cached JSON files into your repository using the `cache_dir` configuration to eliminate network dependencies entirely.

### How do I pin a specific icon set version?

Call `icon_set_version("<set>", "<tag>")` on your `BuildConfig` instance before invoking `stage()`. This records the version in the cache key and ensures reproducible builds across environments, as implemented in [[`crates/topcoat-icon/src/iconify/config.rs`](https://github.com/tokio-rs/topcoat/blob/main/crates/topcoat-icon/src/iconify/config.rs)](https://github.com/tokio-rs/topcoat/blob/main/crates/topcoat-icon/src/iconify/config.rs).

### What is the difference between `iconify::include!` and `iconify_icon!`?

`iconify::include!("<set>")` generates a Rust module containing every icon in the set as a named constant (e.g., `feather::TRASH_2`), suitable for heavy usage of a specific set. `iconify_icon!("<set>:<name>")` expands a single string literal into an `IconData` constant inline, which is preferable for occasional usage or when minimizing binary size by avoiding unused icon definitions.

### Where can I see a working example?

The repository provides two canonical examples: [[`examples/icon/src/main.rs`](https://github.com/tokio-rs/topcoat/blob/main/examples/icon/src/main.rs)](https://github.com/tokio-rs/topcoat/blob/main/examples/icon/src/main.rs) demonstrates basic `include!` usage, while [[`examples/ui/src/main.rs`](https://github.com/tokio-rs/topcoat/blob/main/examples/ui/src/main.rs)](https://github.com/tokio-rs/topcoat/blob/main/examples/ui/src/main.rs) and its accompanying [[`build.rs`](https://github.com/tokio-rs/topcoat/blob/main/build.rs)](https://github.com/tokio-rs/topcoat/blob/main/examples/ui/build.rs) show a full application staging multiple sets and rendering them within styled components.