feat: apply the 2026 brand to the Phoenix docs - #15458
Conversation
Ports the design system already applied to the Arize AX docs, keeping Phoenix's own cyan identity. The layout does not change; this is colour, type, surfaces and icons. Phoenix keeps its own palette. The brand token set carries a dedicated [data-mode="phoenix"] block — cyan accent, neutral near-black surfaces — with the same Geist type and 2/8px radii as AX, so the structure is shared and the hue is not. docs.json - Accents: primary #00769E (light-mode emphasis), light #39C7FF (dark-mode emphasis), dark #009DD2 (button fills). Note the docs.json JSON-schema describes this mapping incorrectly; these are what actually render. - Backgrounds #FFFFFF / #08090A, gradient decoration dropped. - Geist for heading and body; Geist Mono for code via CSS, as there is no docs.json slot for it. - icons.library switched to lucide; brand marks pinned to fontawesome. The token set defines Phoenix as dark-only, so light-mode values are derived. The brand cyan #009DD2 is only 3.1:1 on white, so light-mode emphasis uses a darkened #00769E — 5.1:1 on the page and 4.6:1 on the accent-soft pill. docs/style.css - Replaces the neutral ramp, which Mintlify otherwise derives from the primary colour and which therefore tinted every surface and hairline. - Mode-scoped --px-* tokens, then component styling for the navbar, sidebar, TOC, cards, code blocks, callouts, tables, the copy-page control and the changelog. Callout families are keyed off data-callout-type. - Changelog entries stack so the date heads a full-width section. - Phoenix's existing rules are carried over unchanged. Icons - 184 fontawesome-only names remapped to lucide across 72 mdx files, plus 19 in docs.json navigation. Non-brand fontawesome names have no fallback under lucide and would render blank. - Brand marks (github, python, java, docker, aws, npm, …) are untouched: Mintlify resolves those against fontawesome automatically. - Eleven mappings are judgement calls where lucide has no close equivalent; they are listed in the PR description. Also drops three hardcoded generic-blue callout colours so they inherit the theme. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
Five of the six tabs wrapped their landing page in a group named " " — Documentation, Integrations, Self-Hosting, Cookbooks and Release Notes. Mintlify renders a group's name as an eyebrow above the page H1, so that single space produced a blank line there plus an empty header in the sidebar. A tab's `pages` array accepts nested group objects, so each wrapper's contents are hoisted to tab level and the wrapper dropped. Tabs may carry either `pages` or `groups` but not both, so the remaining real groups move into `pages` alongside the hoisted items, preserving order. Verified no page was added, dropped or reordered: 708 pages, byte-identical flattened order per tab, no blank-named groups left, and no tab carrying both keys. Pages that were inside a wrapper (self-hosting/architecture, license, cookbook) now have no eyebrow rather than an empty one; grouped pages keep theirs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Four of the six AX fixes apply here; the other two have no Phoenix counterpart (there is no hero panel, and no coding-agent snippet). - Prose links: these render as `<a class="link">`, and the rule here was `a:not(.card):not(.link)` — so it excluded exactly the links it was meant to style, leaving them on Mintlify's link colour. Now scoped correctly and set to the brand accent. - Step number circles: shipped as a plain grey disc; now the design's accent-soft disc with a hairline accent ring and accent numeral. - Code inside callouts: sits on the page background rather than the code surface, so a tinted callout does not carry a second tint. - Table-of-contents active entry: marked by colour alone. Mintlify also bolds it, which the design does not. Also fixes two callouts that asked for a warning and did not get one. `type` is not a `<Callout>` prop, so `<Callout type="warning">` rendered as a neutral generic callout. Replaced with `<Warning>` in the Claude Code and OpenCode integration pages — same defect class as the AX callout fix, with the author's intent explicit in the markup. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…-system # Conflicts: # docs/phoenix/release-notes/08-2026/08-12-2026-session-filters-rest-api-and-endpoint-config.mdx
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Mc2tUw43f5K7tNEk6nU5Fk
|
|
||
| <CardGroup cols={2}> | ||
| <Card title="User Friction" icon="face-frown" href="/docs/phoenix/evaluation/pre-built-metrics/user-friction"> | ||
| <Card title="User Friction" icon="face-slightly-frowning" href="/docs/phoenix/evaluation/pre-built-metrics/user-friction"> |
There was a problem hiding this comment.
face-slightly-frowning isn't a valid name in either library, so this icon will render blank.
Lucide has no face-* namespace — its emotion set is angry / annoyed / frown / laugh / meh / smile / smile-plus, so the plain frown the description says is missing does exist (it's inherited from Feather). FontAwesome has face-frown and face-frown-open but not face-slightly-frowning; that string is the Unicode/CLDR emoji name for 🙁, not an icon id in either set.
It's the only face--prefixed name left in the docs — every other renamed icon in this PR maps to a real lucide id. Note the same "User Friction" card in pre-built-metrics.mdx was mapped to messages-square instead:
phoenix/docs/phoenix/evaluation/pre-built-metrics.mdx
Lines 42 to 44 in 4e3cc26
| <Card title="User Friction" icon="face-slightly-frowning" href="/docs/phoenix/evaluation/pre-built-metrics/user-friction"> | |
| <Card icon="frown" href="/docs/phoenix/evaluation/pre-built-metrics/user-friction"> |
(or messages-square for consistency with the other page)
| <Card title="Document Relevance" icon="file-search" href="/docs/phoenix/evaluation/pre-built-metrics/document-relevance"> | ||
| Assesses whether retrieved documents are relevant to the input query. Useful for RAG evaluation. | ||
| </Card> | ||
| <Card title="Tool Selection" icon="toolbox" href="/docs/phoenix/evaluation/pre-built-metrics/tool-selection"> |
There was a problem hiding this comment.
toolbox is a FontAwesome-only name that wasn't included in the rename sweep, so it's newly orphaned by the library flip and will render blank.
Lucide has no toolbox — the nearest equivalents are wrench, briefcase, or hammer. Per the PR description, non-brand FontAwesome names get no fallback under library: "lucide":
Lines 30 to 34 in 4e3cc26
It's one of only three non-brand FontAwesome-shaped names left in the docs (toolbox, user-shield, list-check) — the other icons on this page are all valid lucide ids.
| <Card title="Tool Selection" icon="toolbox" href="/docs/phoenix/evaluation/pre-built-metrics/tool-selection"> | |
| <Card icon="wrench" href="/docs/phoenix/evaluation/pre-built-metrics/tool-selection"> |
| <Card title="Query for Documents" href="/docs/phoenix/tracing/how-to-tracing/importing-and-exporting-traces/extract-data-from-spans#querying-for-retrieved-documents" icon="file-search" horizontal description="Document retrieval queries"/> | ||
| <Card title="Filter Expressions" href="/docs/phoenix/tracing/how-to-tracing/filter-expressions" icon="funnel" horizontal description="Filter spans and sessions with expressions"/> | ||
| <Card title="Extract Attributes" href="/docs/phoenix/tracing/how-to-tracing/importing-and-exporting-traces/extract-data-from-spans#how-to-extract-attributes" icon="tags" horizontal description="Attribute extraction tips"/> | ||
| <Card title="Use Pre-defined Queries" href="/docs/phoenix/tracing/how-to-tracing/importing-and-exporting-traces/extract-data-from-spans#pre-defined-queries" icon="list-check" horizontal description="Prebuilt query patterns"/> |
There was a problem hiding this comment.
list-check (singular) is a FontAwesome name — lucide's is list-checks (plural). It was missed by the rename sweep, so under library: "lucide" this card renders blank while the four neighbours in this same <Columns> block were all correctly remapped.
Lines 30 to 34 in 4e3cc26
| <Card title="Use Pre-defined Queries" href="/docs/phoenix/tracing/how-to-tracing/importing-and-exporting-traces/extract-data-from-spans#pre-defined-queries" icon="list-check" horizontal description="Prebuilt query patterns"/> | |
| <Card href="/docs/phoenix/tracing/how-to-tracing/importing-and-exporting-traces/extract-data-from-spans#pre-defined-queries" icon="list-checks" horizontal description="Prebuilt query patterns"/> |
| @@ -1245,12 +1250,14 @@ | |||
| }, | |||
There was a problem hiding this comment.
(anchored here — the affected line is just above, outside the diff hunk)
user-shield is a FontAwesome-only name that the rename sweep missed. Lucide's equivalent reverses the word order: shield-user. Under library: "lucide" both of these render blank:
- — the
Lines 1243 to 1245 in 4e3cc26
"Security"nav group - — the "Access Controls" card
phoenix/docs/phoenix/self-hosting.mdx
Lines 64 to 66 in 4e3cc26
Every other shield/user icon left in the docs (shield, shield-check, user-lock, user-plus, users) is a valid lucide id, and the sweep applied exactly this pattern nearby (shield-halved → shield, user-robot → bot, user-chef → chef-hat), so this looks like an oversight rather than a deliberate keep. Both sites need icon: "shield-user".
Mintlify serves lucide v1.16.0 from its CDN. user-shield and face-slightly-frowning are canonical ids in current lucide but postdate v1.16.0, so both 403 and render blank: user-shield -> shield-user (docs.json Security nav, self-hosting.mdx) face-slightly-frowning -> frown (07-22 release note) Addresses two of the four review comments. The other two (toolbox, list-check) were false positives — both return 200 from the v1.16.0 CDN and render correctly, so they are left alone. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Mc2tUw43f5K7tNEk6nU5Fk
| } | ||
| }, | ||
| "icons": { | ||
| "library": "lucide" |
There was a problem hiding this comment.
Switching the default icon library to lucide orphans the FontAwesome brand icon names that are still used unqualified across the docs. Lucide deliberately excludes brand/logo marks, so these names no longer resolve and will render as blank space (they rendered fine before, under the implicit FontAwesome default).
Still bare strings in this file:
Lines 627 to 629 in 25c3c16
plus "python" (L679, L938), "java" (L837), "js" (L948).
And in .mdx — including two files this PR does edit, where the generic icons on adjacent lines were migrated but the brand ones were skipped:
phoenix/docs/phoenix/integrations.mdx
Lines 83 to 85 in 25c3c16
phoenix/docs/phoenix/self-hosting.mdx
Lines 25 to 27 in 25c3c16
Repo-wide counts of unqualified names with no lucide equivalent: python ×211, js ×194, golang ×20, npm ×4, docker/aws/microsoft ×2 each, java/google ×1 each — ~437 .mdx usages plus the 5 in docs.json. (github ×130 does exist in lucide, so those render, just with a different mark.)
The footer socials were already handled correctly with the object form, which is the fix to apply here too:
Lines 1667 to 1673 in 25c3c16
For docs.json nav entries, use "icon": { "name": "python", "library": "fontawesome", "style": "brands" }. For .mdx <Card>/<Tab> props (which take a plain string), either swap to a lucide-native equivalent or use <Icon icon="python" library="fontawesome" iconType="brands" /> where the brand mark matters. A grep -rnE 'icon="(python|js|java|golang|npm|docker|aws|microsoft|google)"' docs --include=*.mdx sweep will catch the rest.
| <Card title="Document Relevance" icon="file-search" href="/docs/phoenix/evaluation/pre-built-metrics/document-relevance"> | ||
| Assesses whether retrieved documents are relevant to the input query. Useful for RAG evaluation. | ||
| </Card> | ||
| <Card title="Tool Selection" icon="toolbox" href="/docs/phoenix/evaluation/pre-built-metrics/tool-selection"> |
There was a problem hiding this comment.
toolbox is a FontAwesome-only name — lucide has no such icon, so with icons.library: "lucide" now set globally this card renders with a blank icon.
This looks like a missed rename rather than a deliberate keep: every other FontAwesome-only name in this CardGroup was migrated in this same hunk (check-double→check-check, compress→shrink, file-magnifying-glass→file-search, arrow-turn-down→corner-right-down, comments→messages-square), and the names left untouched (ghost, circle-check, wrench, hand) are all valid lucide icons.
Note wrench is already taken by the "Tool Invocation" card just below, so it needs a distinct name:
| <Card title="Tool Selection" icon="toolbox" href="/docs/phoenix/evaluation/pre-built-metrics/tool-selection"> | |
| <Card icon="briefcase" href="/docs/phoenix/evaluation/pre-built-metrics/tool-selection"> |
Mirrors the AX revert. FontAwesome's default style in Mintlify is already 'regular' — the lighter outline set — so removing icons.library restores light icons without touching a single iconType prop. Reverted at line level from the diff rather than by a global name map, and every original name was checked against Mintlify's FontAwesome build first. Three nav and card icons the line-level pass missed (their lines had other edits) were restored by hand: chef-hat -> user-chef, settings -> gear, layers -> layer-group. Verified: all 131 icon names now resolve — 121 via regular, 10 via brands, zero blank. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Mc2tUw43f5K7tNEk6nU5Fk
Card links checkNo broken Card links found. Checked external links in 20.2s |
| "group": "Upgrade", | ||
| "icon": "angles-up", | ||
| "pages": ["docs/phoenix/self-hosting/upgrade/migrations"] | ||
| "icon": "chevrons-up", |
There was a problem hiding this comment.
chevrons-up is a lucide-only name, but this PR never actually switches the icon library — there is no icons key anywhere in docs.json (jq '.icons' → null, and "lucide" appears nowhere in the diff). Mintlify therefore still resolves icons against its Font Awesome default.
Font Awesome names the double chevron angles-up and has no chevrons-* icons in Free or Pro. Because Mintlify renders these as CSS mask-image, the 404 paints nothing — the Self-Hosting → Upgrade group icon will render blank rather than showing a broken-image affordance.
The rest of the file confirms Font Awesome is still in force: gear-complex, user-robot, user-chef, rectangle-terminal, boxes-stacked, shield-halved, and wand-magic-sparkles are all FA-only names left untouched by this PR. The other renames here (rocket-launch, puzzle, gear, circle-check, wand-sparkles) all remain valid FA names — chevrons-up is the only outlier.
Lines 1232 to 1236 in 21c6b1e
| "icon": "chevrons-up", | |
| "icon": "angles-up", |
(Alternatively, land the "icons": { "library": "lucide" } switch and the full rename sweep the PR description describes — but as committed, the two halves disagree.)
Ports the 2026 design system already applied to the Arize AX docs (Arize-ai/docs#840), keeping Phoenix's own cyan identity. The layout does not change — this is colour, type, surfaces and icons.
Phoenix keeps its own palette
The brand token set carries a dedicated
[data-mode="phoenix"]block: cyan accent, neutral near-black surfaces, but the same Geist type and 2/8px radii as AX. So the structure is shared and the hue is not — Phoenix does not become magenta.colors.primary(light emphasis)#0384C3#00769Ecolors.light(dark emphasis)#0384C3#39C7FFaccent-5colors.dark(button fills)#0384C3#009DD2accent-1#FFFFFF/#08090A#151616Why
#00769Eand not the brand cyan. The token set defines Phoenix as dark-only, so light-mode values had to be derived. The brand cyan#009DD2is only 3.1:1 on white — below AA.#00769Eis the same hue darkened until it clears AA against both the white page (5.14:1) and the pale accent-soft pill it sits on in the active sidebar item (4.56:1). Solving for both was necessary; the first candidate passed on white but failed at 4.04:1 on the pill.Heads up on the accent mapping. The
docs.jsonJSON-schema sayscolors.darkis "used primary in light mode". That is wrong — measured from rendered output,primaryis light-mode emphasis,lightis dark-mode emphasis, anddarkis button/hover fills in both. Getting it the schema's way puts the light accent on white at ~3:1.docs/style.cssThe highest-leverage change is replacing the
--gray-*ramp: Mintlify derives it fromcolors.primary, so it was tinting every surface, hairline and muted text. The 400/900/950 stops are the token set's own Phoenix values (#A1A4AB,#151616,#08090A).Then component styling for the navbar, sidebar, TOC, cards, code blocks, callouts, tables, the copy-page control and the changelog. Callout families are keyed off
data-callout-type.Changelog entries now stack at every width, so the date heads a full-width section instead of sitting in a 160px sticky column beside narrowed content.
Phoenix's existing rules (
.sr-only, card-group image heights,table,.step-title,.invert-on-dark,.release-update-read-more) are carried over unchanged.Two implementation notes carried over from the AX work, both of which cost real debugging there:
.card.card). Mintlify styles these withdark:utilities that compile to.foo:is(.dark *)— specificity (0,2,0). A single class is (0,1,0) and silently loses in dark mode only.aria-haspopup, not:last-child. Opening its menu injects sibling elements into the container, so a positional selector stops matching mid-interaction and the button visibly shrinks.Icons
icons.libraryis a single global choice, and the two libraries behave differently:github,python,java,docker,aws,npm,google,golang,js,microsoftagainst fontawesome even under lucide. 572 references untouched.docs.jsonnavigation (easy to miss — they are not in MDX).Verified: all 1,175 icon references across 118 names resolve; zero blanks.
Judgement calls worth a look
Eleven mappings where lucide has no close equivalent — please sanity-check these:
dharmachakraship-wheeltraintrain-frontsignal-streamradio-towercompressshrinkfile-csvfile-spreadsheetchart-simplechart-columnface-frownface-slightly-frowningfrownsitemapnetworknetwork-wiredcommentsmessages-squaremessageswindow-maximizeapp-windowbrowserwarningtriangle-alerttriangle-exclamationAlso drops three hardcoded
#3b82f6callout colours so they inherit the theme accent.Verification
Audited with a scripted in-page check across 11 pages × light and dark, asserting every ramp stop, accent var, surface, border, radius, and the structural selectors (navbar rule width, tab underline, copy-button halves equal height, changelog columns equal width), plus a sweep for icons painted as solid blocks.
Zero failures. Worst contrast anywhere in scope: 4.56:1. Coverage was checked too — every assertion ran and passed on at least one real page, so nothing was silently skipped.
check-card-links.jspasses.mint broken-linksreports 11 in 9 files — verified by exact path comparison as pre-existing, none of them in this diff.Pre-existing issue found, not fixed here
docs/phoenix/settings/sandboxes.mdxcontains a hand-authored diagram with hardcoded light-theme colours (#334155,#4C1D95,#F4DDFF). In dark mode that text sits at 1.8–1.9:1. It is not caused by this change and the file is not in this diff, but it has never worked in dark mode and is worth a separate fix.Worth a reviewer's eye
appearance.default, so it follows the system preference. Light mode is therefore as load-bearing as dark here — more so than on AX, which defaults to dark.🤖 Generated with Claude Code