duxt draws from four Iconify collections. The question is never "which one looks
best here" — it is **what the thing being drawn is**, because that is the only
test that gives the same answer twice.

| Set                                                              | Draws                                            | Colour                              | Named in                     |
| :--------------------------------------------------------------- | :----------------------------------------------- | :---------------------------------- | :--------------------------- |
| [lucide](https://lucide.dev)                                      | the interface duxt draws itself                  | monochrome, inherits `currentColor` | anywhere; the default        |
| [vscode-icons](https://github.com/vscode-icons/vscode-icons)      | a file, a fence's language, a tool of the stack  | its own                             | `file-icons.ts`, and the package-manager tabs |
| [Simple Icons](https://simpleicons.org)                           | a platform, service or company named as itself    | monochrome                          | the component that names it  |
| [flag-icons](https://github.com/lipis/flag-icons)                 | a locale's region                                 | its own                             | `DuxtLocale`, derived        |

## The rule

**What is being drawn decides, and there are two kinds of mark:**

- **The stack** — a file, a fence's language, a tool you run — is **vscode-icons**.
  It carries the real colours in the file, which is what a file tree and a code
  header need.
- **A third party as itself** — a platform, a service, a company the site links
  to or hands something to — is **Simple Icons**.

Everything that is not a mark at all — a copy control, a chevron, a search
glass, an external-link arrow — is **lucide**, and needs no decision.

Stated by domain rather than by availability, the rule extends itself. Laravel,
GitHub, Discord and OpenAI are Simple Icons because they are parties this site
names, not parts of the stack it is built from. The package managers are
vscode-icons because a tab that runs `pnpm add` names a tool of the stack.

::callout{type="info" title="Where both collections carry the same brand"}
The domain decides, not the collection. vscode-icons has `file-type-claude` —
and it is, by its own namespace, the icon for a Claude **file**. The button that
sends this page to the Claude **platform** is `simple-icons:claude`, because the
platform is what it names. The same reading keeps `simple-icons:openai` beside
it rather than splitting a pair of buttons across two collections.
::

## Why not one set for everything

Because monochrome and self-coloured are different jobs, not different tastes.

An interface icon has to take the text colour, or it fights every state around
it: hover, active, muted, disabled. lucide inherits `currentColor`, so a control
is styled once and the icon follows.

A file-type icon has to keep its own colours, or a file tree becomes a column of
identical grey shapes. That is the whole reason vscode-icons exists, and why
`app/utils/file-icons.ts` maps every extension and language id into it.

## Colour is not ours to invent

The package-manager tabs used to be Simple Icons tinted by hand — eight hex
values, two per manager, because one cannot serve both themes: bun's cream
vanishes on white, npm's red goes muddy on black. Every one of those was a
number somebody read off a brand page and would have to read again when the
brand changed.

vscode-icons removed the table by carrying the colours in the file. Where a mark
still needs help, the collection usually says so itself: **pnpm** is orange
squares *and white ones*, so half the grid disappears on a white page — and
vscode-icons ships `file-type-light-pnpm` with `#4e4e4e` in place of the white,
for exactly that. It ships a light variant for no other manager here.

::callout{type="tip" title="Two elements, not a filter"}
A mark that needs both spellings is drawn twice and swapped by the theme class
(`dark:hidden` / `hidden dark:block`) — the same technique the landing page's
preview poster uses for its two screenshots. A CSS filter over a coloured mark
produces a colour nobody chose.
::

## Licences, and the thing a licence cannot give

All four collections are permissive and compatible with duxt's MIT: vscode-icons
and flag-icons are MIT, lucide is ISC, Simple Icons is CC0-1.0. Each is named
with its licence on the [credits page](/credits), because `icon.clientBundle`
inlines the SVGs into what ships — the package carries the works, so it carries
the notices.

**A licence on the file is not a licence on the mark.** Simple Icons says so in
its own LICENSE: CC0 releases the SVG, and cannot release a trademark it never
held. The same holds for vscode-icons' file types — MIT covers the drawing, not
the Python, Rust or Vue marks inside it.

What duxt does is **nominative use**: the bun logo sits on the tab that runs
`bun add`, the Python icon labels a Python fence, the Claude and OpenAI marks sit
on the buttons that send the page to those services. Naming a thing to identify
it is the use trademark law allows without permission. Using one of those marks
as duxt's own logo, favicon or endorsement would not be — and duxt does not.