From f67a7e44bf8f3b06a9083a274b779b6e20c09bbd Mon Sep 17 00:00:00 2001 From: Abeuty Date: Thu, 2 Jul 2026 16:52:37 -0600 Subject: [PATCH 1/2] =?UTF-8?q?feat(ds):=20design=20system,=20rebrand=20st?= =?UTF-8?q?yles,=20and=20lucide=E2=86=92Phosphor=20icon=20migration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Build out the /ds design system as the source of truth for the site and apply its tokens, type, and icons across the app. Design system (/ds): - Rendered style book with tree nav: Styles (Colors, Typography, Iconography, Icon Migration, Shadows, Effects), Figma Tokens (Palette, Semantic Tokens), and Components (Buttons, Badges, Inputs, Dropdown, Avatar, Spinner, Collapsible, Breadcrumbs, Cards). - Figma token layer in app.css (@theme static): primitives (--color-ds-*), library (--color-lib-*), and semantic tokens (text/background/border/icon/ action/status/accent) with html.dark overrides. - New-system component kit (src/components/ds/ui) on the semantic tokens. Site-wide rebrand application: - Global type: h1..h6 → Bricolage Grotesque, mono → IBM Plex Mono, fonts loaded globally from __root.tsx. Editing --font-ds-* propagates everywhere. - Navbar swapped to the new rebrand landscape logo (light/dark variants) with centered nav; mega menu centered. - Palm-tree pixel-art spinner (PalmSpinner) that sways at the trunk base. Icon migration (lucide-react → @phosphor-icons/react), 155 files: - 218 distinct icons (85 kept name, 133 renamed) at regular weight. - Props translated: dropped strokeWidth/absoluteStrokeWidth, fill→weight="fill", LucideIcon type → Phosphor Icon type; aliases and same-target collisions handled. - /ds/icon-migration review page renders old→new glyphs side by side so maintainers can flag any swap that doesn't fit its context. lucide-react is kept installed (the review page renders the "before" glyphs); it can be removed once that page is retired. Co-Authored-By: Claude Fable 5 --- .agents/index.md | 27 + package.json | 1 + pnpm-lock.yaml | 15 + .../images/brand/tanstack-landscape-black.svg | 23 + .../brand/tanstack-landscape-charcoal.svg | 23 + .../images/brand/tanstack-landscape-white.svg | 23 + .../images/brand/tanstack-stacked-black.svg | 19 + .../brand/tanstack-stacked-charcoal.svg | 19 + .../images/brand/tanstack-stacked-cream.svg | 19 + .../images/brand/tanstack-stacked-white.svg | 19 + src/builder/templates.ts | 18 +- src/components/ApplicationStarter.tsx | 30 +- src/components/AuthenticatedUserMenu.tsx | 18 +- src/components/Avatar.tsx | 2 +- src/components/AvatarCropModal.tsx | 2 +- src/components/BlogAuthorFilter.tsx | 7 +- src/components/Breadcrumbs.tsx | 4 +- src/components/CodeExplorerTopBar.tsx | 22 +- src/components/CopyPageDropdown.tsx | 4 +- src/components/Doc.tsx | 9 +- src/components/DocFeedbackFloatingButton.tsx | 4 +- src/components/DocFeedbackNote.tsx | 18 +- src/components/DocFeedbackProvider.tsx | 4 +- src/components/ExampleDeployDialog.tsx | 20 +- src/components/FeedbackLeaderboard.tsx | 4 +- src/components/FeedbackModerationList.tsx | 8 +- src/components/FilterComponents.tsx | 20 +- src/components/FrameworkCard.tsx | 2 +- src/components/ImageUpload.client.tsx | 4 +- src/components/LibraryLayout.tsx | 10 +- src/components/LibraryStatsSection.tsx | 2 +- src/components/LibraryTestimonials.tsx | 2 +- src/components/LoginModal.tsx | 2 +- src/components/Navbar.tsx | 119 ++-- src/components/NavbarAuthControls.tsx | 2 +- src/components/NavbarCartButton.tsx | 2 +- src/components/NewsletterSignup.tsx | 8 +- src/components/NotFound.tsx | 30 +- src/components/NotesModerationList.tsx | 6 +- src/components/OpenSourceStats.tsx | 4 +- src/components/PaginationControls.tsx | 6 +- src/components/PartnershipCallout.tsx | 4 +- src/components/SearchButton.tsx | 4 +- src/components/SearchModal.tsx | 64 +-- src/components/Select.tsx | 7 +- src/components/ShowcaseCard.tsx | 13 +- src/components/ShowcaseDetail.tsx | 14 +- src/components/ShowcaseGallery.tsx | 2 +- src/components/ShowcaseModerationList.tsx | 10 +- src/components/ShowcaseSection.tsx | 2 +- src/components/ShowcaseSubmitForm.tsx | 4 +- src/components/Spinner.tsx | 4 +- src/components/SponsorSection.tsx | 2 +- src/components/TableComponents.tsx | 8 +- src/components/ThemeToggle.tsx | 4 +- src/components/TocMobile.tsx | 4 +- src/components/UserFeedbackSection.tsx | 13 +- src/components/VersionSelect.tsx | 2 +- .../AccountProfilePictureSection.client.tsx | 6 +- src/components/admin/AdminAccessDenied.tsx | 2 +- src/components/admin/DocsCacheTab.tsx | 14 +- src/components/admin/UserAvatar.tsx | 2 +- src/components/application-builder/parts.tsx | 6 +- src/components/builder/BuilderSummary.tsx | 6 +- src/components/builder/BuilderWorkspace.tsx | 4 +- src/components/builder/CustomAddonDialog.tsx | 22 +- .../builder/CustomTemplateDialog.tsx | 20 +- src/components/builder/DeployDialog.tsx | 20 +- src/components/builder/FeaturePicker.tsx | 16 +- src/components/charts/ChartControls.tsx | 6 +- src/components/ds/DsKit.tsx | 232 ++++++++ src/components/ds/ds-nav.ts | 52 ++ src/components/ds/ui/PalmSpinner.tsx | 117 ++++ src/components/ds/ui/index.tsx | 523 ++++++++++++++++++ src/components/game/ui/CompleteOverlay.tsx | 6 +- src/components/game/ui/GameHUD.tsx | 11 +- src/components/game/ui/StatsHUD.tsx | 4 +- .../home/HomeSocialProofSection.tsx | 2 +- src/components/landing/AiLanding.tsx | 30 +- src/components/landing/CliLanding.tsx | 28 +- src/components/landing/ConfigLanding.tsx | 30 +- src/components/landing/DbLanding.tsx | 33 +- src/components/landing/DevtoolsLanding.tsx | 30 +- src/components/landing/FormLanding.tsx | 22 +- src/components/landing/HotkeysLanding.tsx | 14 +- src/components/landing/IntentLanding.tsx | 31 +- .../landing/LandingCopyPromptButton.tsx | 4 +- src/components/landing/PacerLanding.tsx | 25 +- src/components/landing/QueryLanding.tsx | 26 +- src/components/landing/RangerLanding.tsx | 13 +- src/components/landing/RouterLanding.tsx | 34 +- src/components/landing/StartLanding.tsx | 24 +- src/components/landing/StoreLanding.tsx | 26 +- src/components/landing/TableLanding.tsx | 57 +- src/components/landing/VirtualLanding.tsx | 45 +- src/components/landing/WorkflowLanding.tsx | 18 +- src/components/markdown/CodeBlockView.tsx | 2 +- src/components/markdown/MarkdownContent.tsx | 6 +- src/components/npm-stats/BaselineSection.tsx | 20 +- src/components/npm-stats/ChartControls.tsx | 14 +- src/components/npm-stats/PackagePills.tsx | 16 +- src/components/npm-stats/PackageSearch.tsx | 4 +- src/components/npm-stats/StatsTable.tsx | 4 +- src/components/shop/CartDrawer.tsx | 4 +- src/components/shop/ui/Qty.tsx | 2 +- src/components/stack/CategoryArticle.tsx | 44 +- src/libraries/ai.tsx | 4 +- src/libraries/cli.tsx | 14 +- src/libraries/config.tsx | 6 +- src/libraries/db.tsx | 6 +- src/libraries/devtools.tsx | 6 +- src/libraries/form.tsx | 6 +- src/libraries/hotkeys.tsx | 6 +- src/libraries/intent.tsx | 4 +- src/libraries/pacer.tsx | 8 +- src/libraries/query.tsx | 6 +- src/libraries/ranger.tsx | 8 +- src/libraries/router.tsx | 8 +- src/libraries/start.tsx | 4 +- src/libraries/store.tsx | 8 +- src/libraries/table.tsx | 6 +- src/libraries/virtual.tsx | 6 +- src/libraries/workflow.tsx | 8 +- src/routeTree.gen.ts | 405 ++++++++++++++ src/routes/__root.tsx | 12 + .../$libraryId/$version.docs.blog.tsx | 2 +- .../$libraryId/$version.docs.contributors.tsx | 8 +- ...n.docs.framework.$framework.examples.$.tsx | 8 +- .../$libraryId/$version.docs.npm-stats.tsx | 2 +- src/routes/account/feedback.tsx | 8 +- src/routes/account/index.tsx | 4 +- src/routes/account/integrations.tsx | 22 +- src/routes/account/notes.tsx | 4 +- src/routes/account/submissions.tsx | 10 +- src/routes/admin/audit.tsx | 6 +- src/routes/admin/feedback_.$id.tsx | 12 +- src/routes/admin/github-stats.tsx | 8 +- src/routes/admin/index.tsx | 20 +- src/routes/admin/intent.tsx | 38 +- src/routes/admin/logins.tsx | 6 +- src/routes/admin/npm-stats.tsx | 6 +- src/routes/admin/roles.$roleId.tsx | 2 +- src/routes/admin/roles.index.tsx | 16 +- src/routes/admin/route.tsx | 30 +- src/routes/admin/showcases_.$id.tsx | 26 +- src/routes/admin/users.$userId.tsx | 13 +- src/routes/admin/users.tsx | 6 +- src/routes/blog.index.tsx | 2 +- src/routes/brand-guide.tsx | 2 +- src/routes/dashboard.tsx | 2 +- src/routes/ds.avatar.tsx | 72 +++ src/routes/ds.badges.tsx | 76 +++ src/routes/ds.breadcrumbs.tsx | 60 ++ src/routes/ds.buttons.tsx | 198 +++++++ src/routes/ds.cards.tsx | 82 +++ src/routes/ds.collapsible.tsx | 71 +++ src/routes/ds.colors.tsx | 142 +++++ src/routes/ds.dropdown.tsx | 70 +++ src/routes/ds.effects.tsx | 64 +++ src/routes/ds.icon-migration.tsx | 376 +++++++++++++ src/routes/ds.iconography.tsx | 246 ++++++++ src/routes/ds.index.tsx | 98 ++++ src/routes/ds.inputs.tsx | 73 +++ src/routes/ds.palette.tsx | 63 +++ src/routes/ds.semantic.tsx | 119 ++++ src/routes/ds.shadows.tsx | 51 ++ src/routes/ds.spinner.tsx | 52 ++ src/routes/ds.tsx | 72 +++ src/routes/ds.typography.tsx | 206 +++++++ src/routes/ethos.tsx | 12 +- src/routes/index.tsx | 22 +- src/routes/intent/registry/$packageName.tsx | 2 +- src/routes/learn.tsx | 2 +- src/routes/maintainers.tsx | 15 +- src/routes/merch.tsx | 12 +- src/routes/paid-support.tsx | 10 +- src/routes/partners.$partner.tsx | 4 +- src/routes/partners.index.tsx | 4 +- src/routes/partners.railway.tsx | 16 +- src/routes/shop.cart.tsx | 4 +- src/routes/shop.search.tsx | 2 +- src/routes/stats/npm/index.tsx | 2 +- src/routes/tenets.tsx | 10 +- src/routes/workshops.tsx | 22 +- src/styles/app.css | 352 +++++++++++- 185 files changed, 4991 insertions(+), 904 deletions(-) create mode 100644 public/images/brand/tanstack-landscape-black.svg create mode 100644 public/images/brand/tanstack-landscape-charcoal.svg create mode 100644 public/images/brand/tanstack-landscape-white.svg create mode 100644 public/images/brand/tanstack-stacked-black.svg create mode 100644 public/images/brand/tanstack-stacked-charcoal.svg create mode 100644 public/images/brand/tanstack-stacked-cream.svg create mode 100644 public/images/brand/tanstack-stacked-white.svg create mode 100644 src/components/ds/DsKit.tsx create mode 100644 src/components/ds/ds-nav.ts create mode 100644 src/components/ds/ui/PalmSpinner.tsx create mode 100644 src/components/ds/ui/index.tsx create mode 100644 src/routes/ds.avatar.tsx create mode 100644 src/routes/ds.badges.tsx create mode 100644 src/routes/ds.breadcrumbs.tsx create mode 100644 src/routes/ds.buttons.tsx create mode 100644 src/routes/ds.cards.tsx create mode 100644 src/routes/ds.collapsible.tsx create mode 100644 src/routes/ds.colors.tsx create mode 100644 src/routes/ds.dropdown.tsx create mode 100644 src/routes/ds.effects.tsx create mode 100644 src/routes/ds.icon-migration.tsx create mode 100644 src/routes/ds.iconography.tsx create mode 100644 src/routes/ds.index.tsx create mode 100644 src/routes/ds.inputs.tsx create mode 100644 src/routes/ds.palette.tsx create mode 100644 src/routes/ds.semantic.tsx create mode 100644 src/routes/ds.shadows.tsx create mode 100644 src/routes/ds.spinner.tsx create mode 100644 src/routes/ds.tsx create mode 100644 src/routes/ds.typography.tsx diff --git a/.agents/index.md b/.agents/index.md index 01316aeb9..ea6eee1cb 100644 --- a/.agents/index.md +++ b/.agents/index.md @@ -2,6 +2,33 @@ TanStack.com marketing site built with TanStack Start. +## Core principles for every task + +Before writing code, walk this ladder. Stop at the first answer that works. + +1. **Does this need to exist?** → no: skip it (YAGNI) +2. **Already in this codebase?** → reuse it, don't rewrite +3. **Stdlib does it?** → use it +4. **Native platform feature?** → use it +5. **Installed dependency?** → use it +6. **One line?** → one line +7. **Only then:** the minimum that works + +Inspired by https://github.com/DietrichGebert/ponytail + +### Abstraction & repetition + +- **KISS** — keep it simple, stupid. Boring code beats clever code. +- **WET > DRY** — write everything twice (or more) before abstracting. Three similar usages with diverging needs is the cue to extract; two is not. +- Premature DRY couples unrelated code through a shared abstraction that ends up fighting both callers. Duplication is cheaper than the wrong abstraction. + +### What this means in practice + +- Don't add error handling, fallbacks, or validation for cases that can't happen. +- Don't introduce helpers, wrappers, or config knobs "for later." +- Don't refactor surrounding code while fixing a bug. +- When tempted to abstract: count the call sites and check they actually want the same behavior. If not, leave the duplication. + ## Essentials - Package manager: `pnpm` diff --git a/package.json b/package.json index 7c4299f90..bd8c8bc1e 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "@modelcontextprotocol/sdk": "^1.29.0", "@observablehq/plot": "^0.6.17", "@octokit/graphql": "^9.0.3", + "@phosphor-icons/react": "^2.1.10", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-toast": "^1.2.15", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 29e1ab7e9..5e86314a1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -39,6 +39,9 @@ importers: '@octokit/graphql': specifier: ^9.0.3 version: 9.0.3 + '@phosphor-icons/react': + specifier: ^2.1.10 + version: 2.1.10(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@radix-ui/react-dialog': specifier: ^1.1.15 version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -2308,6 +2311,13 @@ packages: cpu: [x64] os: [win32] + '@phosphor-icons/react@2.1.10': + resolution: {integrity: sha512-vt8Tvq8GLjheAZZYa+YG/pW7HDbov8El/MANW8pOAz4eGxrwhnbfrQZq0Cp4q8zBEu8NIhHdnr+r8thnfRSNYA==} + engines: {node: '>=10'} + peerDependencies: + react: '>= 16.8' + react-dom: '>= 16.8' + '@poppinss/colors@4.1.6': resolution: {integrity: sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==} @@ -8652,6 +8662,11 @@ snapshots: '@oxlint/binding-win32-x64-msvc@1.58.0': optional: true + '@phosphor-icons/react@2.1.10(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + '@poppinss/colors@4.1.6': dependencies: kleur: 4.1.5 diff --git a/public/images/brand/tanstack-landscape-black.svg b/public/images/brand/tanstack-landscape-black.svg new file mode 100644 index 000000000..a048f79ee --- /dev/null +++ b/public/images/brand/tanstack-landscape-black.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + diff --git a/public/images/brand/tanstack-landscape-charcoal.svg b/public/images/brand/tanstack-landscape-charcoal.svg new file mode 100644 index 000000000..04682e958 --- /dev/null +++ b/public/images/brand/tanstack-landscape-charcoal.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + diff --git a/public/images/brand/tanstack-landscape-white.svg b/public/images/brand/tanstack-landscape-white.svg new file mode 100644 index 000000000..50ad4162f --- /dev/null +++ b/public/images/brand/tanstack-landscape-white.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + diff --git a/public/images/brand/tanstack-stacked-black.svg b/public/images/brand/tanstack-stacked-black.svg new file mode 100644 index 000000000..816042af2 --- /dev/null +++ b/public/images/brand/tanstack-stacked-black.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + diff --git a/public/images/brand/tanstack-stacked-charcoal.svg b/public/images/brand/tanstack-stacked-charcoal.svg new file mode 100644 index 000000000..d3fcd4eef --- /dev/null +++ b/public/images/brand/tanstack-stacked-charcoal.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + diff --git a/public/images/brand/tanstack-stacked-cream.svg b/public/images/brand/tanstack-stacked-cream.svg new file mode 100644 index 000000000..b3ed7ec4c --- /dev/null +++ b/public/images/brand/tanstack-stacked-cream.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + diff --git a/public/images/brand/tanstack-stacked-white.svg b/public/images/brand/tanstack-stacked-white.svg new file mode 100644 index 000000000..46fc6bbba --- /dev/null +++ b/public/images/brand/tanstack-stacked-white.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + diff --git a/src/builder/templates.ts b/src/builder/templates.ts index 28809a598..b5eafb79a 100644 --- a/src/builder/templates.ts +++ b/src/builder/templates.ts @@ -5,25 +5,25 @@ * Users can select a template to pre-populate features, then modify freely. */ -import type { LucideIcon } from 'lucide-react' +import type { Icon } from '@phosphor-icons/react' import { Rocket, - Bot, - LayoutDashboard, + Robot, + SquaresFour, FileText, - Server, + HardDrives, Radio, Globe, HardDrive, Plus, ShoppingBag, -} from 'lucide-react' +} from '@phosphor-icons/react' export interface Template { id: string name: string description: string - icon: LucideIcon + icon: Icon color: string features: Array /** @@ -63,7 +63,7 @@ export const TEMPLATES: Array