Icons
Four icon sets, and the one question that decides which of them draws a given mark.
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 | the interface duxt draws itself | monochrome, inherits currentColor | anywhere; the default |
| 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 | a platform, service or company named as itself | monochrome | the component that names it |
| 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.
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.
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, 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.