From 16c72ca3d93ec48810bfa10864884d7c50195d84 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 29 Oct 2026 12:24:25 +0100 Subject: [PATCH] feat(docs): add sponsor page Add a /sponsor page to lucide.dev with sponsor tiers, an amount picker, a sponsor wall and a FAQ. - Fetch active Open Collective sponsors at build time into sponsorsData.json, falling back to an empty list when the API fails - Group sponsors by monthly amount so the wall keeps working while the Open Collective tiers are renamed - Add reusable SponsorLogoGrid and SponsorAvatars components - Add general Faq/FaqItem components fed by `faq` frontmatter, which also emits FAQPage structured data - Link the page from the nav, footer and the home page sponsor card Co-Authored-By: Claude Opus 5.5 --- .gitignore | 1 + docs/.vitepress/config.ts | 2 + docs/.vitepress/getStructuredData.ts | 20 + docs/.vitepress/theme/components/base/Faq.vue | 71 +++ .../theme/components/base/FaqItem.vue | 74 +++ .../theme/components/home/HomeSponsorCard.vue | 2 +- .../theme/components/overrides/VPFooter.vue | 4 + .../sponsor/SponsorAmountPicker.vue | 456 ++++++++++++++++++ .../components/sponsor/SponsorAvatars.vue | 123 +++++ .../theme/components/sponsor/SponsorCta.vue | 71 +++ .../components/sponsor/SponsorFundingUses.vue | 105 ++++ .../theme/components/sponsor/SponsorHero.vue | 152 ++++++ .../components/sponsor/SponsorLogoGrid.vue | 173 +++++++ .../components/sponsor/SponsorSection.vue | 51 ++ .../sponsor/SponsorSectionHeader.vue | 43 ++ .../components/sponsor/SponsorStats.data.ts | 28 ++ .../components/sponsor/SponsorTierCard.vue | 193 ++++++++ .../theme/components/sponsor/SponsorTiers.vue | 256 ++++++++++ .../theme/components/sponsor/SponsorWall.vue | 42 ++ .../theme/components/sponsor/sponsors.ts | 20 + .../theme/components/sponsor/tiers.ts | 92 ++++ docs/.vitepress/transformPageData.ts | 11 +- docs/package.json | 1 + docs/scripts/writeSponsorsData.mts | 161 +++++++ docs/sponsor.md | 45 ++ 25 files changed, 2195 insertions(+), 2 deletions(-) create mode 100644 docs/.vitepress/theme/components/base/Faq.vue create mode 100644 docs/.vitepress/theme/components/base/FaqItem.vue create mode 100644 docs/.vitepress/theme/components/sponsor/SponsorAmountPicker.vue create mode 100644 docs/.vitepress/theme/components/sponsor/SponsorAvatars.vue create mode 100644 docs/.vitepress/theme/components/sponsor/SponsorCta.vue create mode 100644 docs/.vitepress/theme/components/sponsor/SponsorFundingUses.vue create mode 100644 docs/.vitepress/theme/components/sponsor/SponsorHero.vue create mode 100644 docs/.vitepress/theme/components/sponsor/SponsorLogoGrid.vue create mode 100644 docs/.vitepress/theme/components/sponsor/SponsorSection.vue create mode 100644 docs/.vitepress/theme/components/sponsor/SponsorSectionHeader.vue create mode 100644 docs/.vitepress/theme/components/sponsor/SponsorStats.data.ts create mode 100644 docs/.vitepress/theme/components/sponsor/SponsorTierCard.vue create mode 100644 docs/.vitepress/theme/components/sponsor/SponsorTiers.vue create mode 100644 docs/.vitepress/theme/components/sponsor/SponsorWall.vue create mode 100644 docs/.vitepress/theme/components/sponsor/sponsors.ts create mode 100644 docs/.vitepress/theme/components/sponsor/tiers.ts create mode 100644 docs/scripts/writeSponsorsData.mts create mode 100644 docs/sponsor.md diff --git a/.gitignore b/.gitignore index 311a10f5f..d3412d6f7 100644 --- a/.gitignore +++ b/.gitignore @@ -66,6 +66,7 @@ docs/.vitepress/data/categoriesData.json docs/.vitepress/data/iconDetails docs/.vitepress/data/relatedIcons.json docs/.vitepress/data/brandStopwords.json +docs/.vitepress/data/sponsorsData.json docs/.vitepress/data/iconPopularity docs/.vitepress/data/lab/iconNodes docs/.vitepress/data/lab/iconMetaData.ts diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 251223308..fd61f358e 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -88,6 +88,7 @@ export default defineConfig({ 'index.md', 'packages.md', 'showcase.md', + 'sponsor.md', 'brand-logo-statement.md', 'icons/**', // Not working, need investigation ], @@ -117,6 +118,7 @@ export default defineConfig({ }, { text: 'Packages', link: '/packages' }, { text: 'Showcase', link: '/showcase' }, + { text: 'Sponsor', link: '/sponsor' }, { text: 'Merch', link: 'https://merch.lucide.dev/' }, ], sidebar, diff --git a/docs/.vitepress/getStructuredData.ts b/docs/.vitepress/getStructuredData.ts index 7fde3ff12..d66373378 100644 --- a/docs/.vitepress/getStructuredData.ts +++ b/docs/.vitepress/getStructuredData.ts @@ -79,3 +79,23 @@ export default async function getStructuredData(iconName: string, pageData: Page }, }; } + +export interface FaqEntry { + question: string; + answer: string; +} + +export function getFaqStructuredData(faq: FaqEntry[]) { + return { + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: faq.map(({ question, answer }) => ({ + '@type': 'Question', + name: question, + acceptedAnswer: { + '@type': 'Answer', + text: answer, + }, + })), + }; +} diff --git a/docs/.vitepress/theme/components/base/Faq.vue b/docs/.vitepress/theme/components/base/Faq.vue new file mode 100644 index 000000000..8d8ec9682 --- /dev/null +++ b/docs/.vitepress/theme/components/base/Faq.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/docs/.vitepress/theme/components/base/FaqItem.vue b/docs/.vitepress/theme/components/base/FaqItem.vue new file mode 100644 index 000000000..8ebed3fb4 --- /dev/null +++ b/docs/.vitepress/theme/components/base/FaqItem.vue @@ -0,0 +1,74 @@ + + + + + diff --git a/docs/.vitepress/theme/components/home/HomeSponsorCard.vue b/docs/.vitepress/theme/components/home/HomeSponsorCard.vue index 9a680b411..c358552a9 100644 --- a/docs/.vitepress/theme/components/home/HomeSponsorCard.vue +++ b/docs/.vitepress/theme/components/home/HomeSponsorCard.vue @@ -22,7 +22,7 @@ import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vu height="42" />