CtrlK
BlogDocsLog inGet started
Tessl Logo

add-icon-mapping

Add or modify icon keyword mappings for providers, models, or agents in lobe-icons. Use this whenever a task involves mapping a provider/model id to an icon, adding a new entry to ModelProvider enum or providerMappings/modelMappings/agentMappings, or fixing a provider/model that renders the fallback (default) icon in LobeHub. Trigger even if the request only says "add icon for X provider" or references a Linear issue about icon keyword mapping — the actual icon component usually already exists; only the mapping is missing.

80

Quality

100%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

SKILL.md
Quality
Evals
Security

Add icon keyword mapping

lobe-icons ships icon components (e.g. src/Grok/) and, separately, mapping tables that resolve a provider/model/agent id string to one of those components. A provider showing the fallback icon in LobeHub almost always means the mapping entry is missing, not the icon itself. Always check src/<Name>/ first — if the brand icon already exists, the task is only wiring it up.

Where mappings live (edit ALL that apply)

The react-native package duplicates the main package's config files. Forgetting the RN package is the most common mistake — the main package edits compile and pass review on their own.

WhatMain packagereact-native package
Provider enumsrc/features/providerEnum.tspackages/react-native/src/features/providerEnum.ts
Provider mappingssrc/features/providerConfig.tsxpackages/react-native/src/features/providerConfig.tsx
Model mappingssrc/features/modelConfig.tspackages/react-native/src/features/modelConfig.ts
Agent mappingssrc/features/agentConfig.ts— (main package only)

The static-* workspace packages (static-svg, static-png, static-webp, static-avatar) are generated from icon components and contain no mapping logic — never edit them for a mapping change.

Matching semantics (they differ!)

  • ProviderIcon: exact match — keyword.toLowerCase() === provider. A keyword like xai will NOT match supergrok; every provider id needs its own keyword.
  • ModelIcon / AgentIcon: each keyword is a case-insensitive RegExp tested against the model id, and the first matching entry in the array wins. Consequences:
    • Substrings match: keyword gpt-4 matches chatgpt-4o-latest.
    • Order matters: put more specific entries before general ones (see how gpt-oss sits before the broad OpenAI entry).
    • Regex syntax is live: ^o1, /o1, o1- are anchored patterns, and characters like . or + in a keyword are regex metacharacters — escape or anchor deliberately.

Provider mapping workflow

  1. Enum — add to ModelProvider in providerEnum.ts, alphabetically sorted, value lowercase:
    SuperGrok = 'supergrok',
  2. Import — in providerConfig.tsx, import the icon (alphabetical order). Main package uses the @/ alias, RN uses relative paths:
    import Grok from '@/Grok';          // main package
    import Grok from '../icons/Grok';   // react-native package
  3. Mapping entry — add to providerMappings, near related entries:
    { Icon: Grok, keywords: [ModelProvider.SuperGrok] },
  4. Repeat 1–3 in the react-native package. The RN enum is RNModelProvider inside its own providerEnum.ts; entry shape is identical.

New entry vs appending a keyword

Two established patterns for derived/subscription providers:

  • Append to an existing entry when the new provider should look identical to its parent — precedent: keywords: [ModelProvider.Moonshot, ModelProvider.KimiCodingPlan], [ModelProvider.ZhiPu, ModelProvider.GLMCodingPlan].
  • New entry with a different brand icon when a more recognizable brand exists and visual distinction from the parent provider helps — precedent: supergrokGrok icon instead of appending to the XAI entry.

Prefer whichever the issue/requester specifies; otherwise pick based on whether users would benefit from telling the two providers apart in a list.

Verification

bun run type-check                             # repo root
cd packages/react-native && bun run type-check # RN package has its own tsconfig

If dependencies aren't installed, the RN type-check reports pre-existing Cannot find module 'react-native' / 'react-native-svg' errors — those are environmental, not caused by your change. Only errors mentioning your new enum member or the config files matter; don't install dependencies just to silence them (pnpm install creates lockfile noise, see below).

Type-check catches typos but not a missed mapping — grep is the completeness check:

grep -rn "supergrok" src packages/react-native/src

Expect hits in both enum files and both config files (2×2). For a model/agent keyword, quickly sanity-check the regex in isolation: new RegExp(keyword, 'i').test(modelId).

There are no committed tests and the repo's vitest.config.ts alias ('@': './src', relative) does not resolve transitive @/ imports — a render test needs a throwaway config with an absolute-path alias and server.deps.inline: [/@lobehub/]. Usually type-check + grep is sufficient.

Commit pitfalls

  • .npmrc sets lockfile=false — the repo commits no lockfile. Running pnpm install generates pnpm-lock.yaml and may inject a placeholder allowBuilds: block into pnpm-workspace.yaml. Delete the lockfile and git checkout -- pnpm-workspace.yaml before committing.
  • The pre-commit hook runs lint-staged and can sweep unintended files into the commit. After committing, check git show --stat HEAD — a mapping change should touch only the 2–4 config files.
  • Commit style is gitmoji + conventional: ✨ feat: add Grok icon mapping for supergrok provider.
Repository
lobehub/lobe-icons
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.