web3icons

Naming conventions for large icon libraries

How to name files, keys and components for thousands of crypto logos, covering tickers versus ids, collisions, case, category prefixes and search aliases.

5 min read

With 50 icons, eth.svg and metamask.svg are all the naming scheme you need. With 2,000 icons across tokens, networks, wallets and exchanges, simple names start to collide, and every rename gets more expensive because names leak into URLs, import statements, cache keys and other people's bookmarks.

This guide describes a naming scheme that holds up at that scale: where simple names break, the separate names each icon needs, and rules for tickers, case, collisions, component names and search aliases.

Where simple names break

Most naming problems in crypto icon sets come from a handful of situations:

  • Tickers aren't unique. An ERC-20 token's symbol is a free-form string chosen by whoever deploys the contract, and EIP-20 even marks it as optional. Unrelated projects share tickers, and scam tokens copy popular ones on purpose.
  • Ids repeat across categories. Coinbase is both a wallet and an exchange, each with its own logo. Ethereum is a network, while its token is ETH.
  • Case differs, files don't. ETH.svg and eth.svg are two files on Linux and the same file on the default macOS and Windows file systems.
  • Characters cause trouble. Bridged tokens such as USDC.e contain a dot. 1INCH starts with a digit, which can't begin a JavaScript identifier. stETH and cbBTC use lowercase letters that carry meaning.
  • Names change. Projects rebrand and migrate tokens. After Polygon's token moved from MATIC to POL, both tickers became reasonable search terms for the same logo.

No single string handles all of that, which is why the next step is to stop asking one name to do every job.

Give each icon several names

Name Example Rules Used for
Key token/ETH, wallet/coinbase Unique across the library, never changes Data, caches, React key props
Slug ETH, coinbase Unique within a category, URL- and file-safe File paths, URLs
Display name Ethereum, Coinbase Wallet Spelled the way the brand spells it Labels, alt text, page titles
Component name TokenETH, WalletCoinbase Valid identifier, unique Generated code
Aliases Sepolia, MATIC Anything people might type Search only

The key is just category plus slug, which makes it unique without inventing anything new. Everything internal refers to icons by key. Slugs are allowed to repeat across categories, and that's fine, because a slug is never used without its category.

Scope everything by category

Put the category in the path: tokens/ETH.svg, networks/ethereum.svg, wallets/coinbase.svg, exchanges/coinbase.svg. URLs follow the same shape. On this site, the ETH token and the Ethereum network live at separate addresses, and Coinbase the exchange has its own page, apart from the wallet.

Category scoping also settles the format question. Each category can use the identifier its users actually know: tokens by ticker, everything else by a kebab-case id such as arbitrum-one.

Tickers, ids and collisions

For tokens, the ticker makes the best slug, because it's what people recognize and type. The question is who gets the bare ticker when two tokens share it. A workable rule: the most established token keeps the ticker, by whatever ranking you trust, such as market cap, and every other token falls back to its unique project id.

function assignSlugs(tokens) {
  const taken = new Set()
  const byRank = [...tokens].sort((a, b) => (a.rank ?? Infinity) - (b.rank ?? Infinity))

  return byRank.map((token) => {
    let slug = token.symbol.toUpperCase()
    if (taken.has(slug.toLowerCase())) slug = token.id // e.g. 'example-protocol'
    taken.add(slug.toLowerCase())
    return { ...token, slug }
  })
}

Two details matter here. The check compares lowercased slugs, so ETH and Eth can never both exist. And because the outcome depends on ranking order, a token that climbs the rankings could take over a ticker on the next build and move existing URLs. If URLs matter to you, store the assigned slugs and only compute slugs for new icons.

Keep slugs to a safe character set, such as letters, digits and hyphens. Transliterate everything else (USDC.e becomes USDC-E) and keep the original ticker in the data for display. A slug is an address; the label is for people. Ticker or name? covers what to show on screen.

Case rules

Pick one case per category and enforce it with a check that runs on every addition. Uppercase tickers for tokens and lowercase kebab-case for everything else is one workable combination, and the one this site's URLs use. It looks inconsistent in a file listing, but each half matches how people write those names.

Never let case be the only difference between two files. Make URL lookups case-insensitive and redirect to the canonical form, so /tokens/eth lands on /tokens/ETH rather than a 404.

Component names

If you generate a component or export per icon, its name has to be a valid identifier and unique across the whole library. Prefixing with the category handles both problems: Token1INCH is valid where 1INCH is not, and WalletCoinbase and ExchangeCoinbase no longer clash.

function componentName(category, slug) {
  const pascal = slug
    .split(/[^A-Za-z0-9]+/)
    .filter(Boolean)
    .map((part) => part[0].toUpperCase() + part.slice(1))
    .join('')
  return category[0].toUpperCase() + category.slice(1) + pascal
}

componentName('token', 'ETH') // 'TokenETH'
componentName('token', '1INCH') // 'Token1INCH'
componentName('network', 'arbitrum-one') // 'NetworkArbitrumOne'

Run a uniqueness check on the output as well. Stripping punctuation can collapse two different slugs into one identifier, as with USDC-E and a hypothetical USDCE.

Aliases are names an icon should be found by without being named after. They include testnets that reuse their mainnet's logo, former names and tickers after a rebrand, common short forms ("BSC" for BNB Smart Chain), and spellings without punctuation ("gateio" for Gate.io).

{
  "key": "network/ethereum",
  "slug": "ethereum",
  "name": "Ethereum",
  "aliases": ["Sepolia"]
}

Keep aliases out of URLs and file names; they're allowed to be vague and even to overlap between icons. Search on Web3 Icons, for example, matches names, tickers and alternative names such as testnet names. When a search matches only on an alias, it helps to say so in the result, as in "Ethereum, matches Sepolia", or the result can look like a mistake. Client-side search for icon libraries covers ranking these matches.

Rules that hold at 2,000 icons

  • Refer to icons internally by a key of category plus slug, never by slug alone.
  • Use tickers as token slugs, with a deterministic and stored rule for collisions.
  • Restrict slugs to letters, digits and hyphens; keep the original spelling in the data.
  • One case per category, checked automatically, with case-insensitive lookups.
  • Prefix generated identifiers with the category and check them for uniqueness.
  • Put old names, testnets and short forms in aliases, not in file names.

Run the naming checks as part of a wider review; auditing an icon set includes them alongside viewBox, padding and color checks.

More in Icon design

All guides