From 33dcf64967206921cd022f944f2bb8d3cdf098e8 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Mon, 21 Jul 2025 22:07:44 +0000 Subject: [PATCH 01/21] chore: add partner section on homepage --- .../Partners/PartnerIcon/index.module.css | 13 ++ .../Common/Partners/PartnerIcon/index.tsx | 26 ++++ .../PartnersIconList/index.module.css | 9 ++ .../Partners/PartnersIconList/index.tsx | 62 +++++++++ apps/site/components/Common/Partners/utils.ts | 48 +++++++ apps/site/navigation.json | 4 + apps/site/next.mdx.use.mjs | 3 + apps/site/next.partners.constants.tsx | 7 + apps/site/pages/en/index.mdx | 5 + apps/site/types/index.ts | 1 + apps/site/types/partners.ts | 20 +++ apps/site/util/partners/constants.json | 58 ++++++++ apps/site/util/partners/index.tsx | 27 ++++ apps/site/util/partners/original.json | 129 ++++++++++++++++++ packages/i18n/src/locales/en.json | 3 +- .../src/Icons/PartnerLogos/Cloudflare.tsx | 23 ++++ .../src/Icons/PartnerLogos/Crowdin.tsx | 49 +++++++ .../src/Icons/PartnerLogos/DataDog.tsx | 56 ++++++++ .../src/Icons/PartnerLogos/HeroDevs.tsx | 56 ++++++++ .../src/Icons/PartnerLogos/NodeSource.tsx | 13 ++ .../src/Icons/PartnerLogos/Rackspace.tsx | 19 +++ .../src/Icons/PartnerLogos/Sentry.tsx | 20 +++ .../src/Icons/PartnerLogos/Vercel.tsx | 18 +++ .../src/Icons/PartnerLogos/index.ts | 19 +++ 24 files changed, 687 insertions(+), 1 deletion(-) create mode 100644 apps/site/components/Common/Partners/PartnerIcon/index.module.css create mode 100644 apps/site/components/Common/Partners/PartnerIcon/index.tsx create mode 100644 apps/site/components/Common/Partners/PartnersIconList/index.module.css create mode 100644 apps/site/components/Common/Partners/PartnersIconList/index.tsx create mode 100644 apps/site/components/Common/Partners/utils.ts create mode 100644 apps/site/next.partners.constants.tsx create mode 100644 apps/site/types/partners.ts create mode 100644 apps/site/util/partners/constants.json create mode 100644 apps/site/util/partners/index.tsx create mode 100644 apps/site/util/partners/original.json create mode 100644 packages/ui-components/src/Icons/PartnerLogos/Cloudflare.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/Crowdin.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/DataDog.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/HeroDevs.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/NodeSource.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/Rackspace.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/Sentry.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/Vercel.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/index.ts diff --git a/apps/site/components/Common/Partners/PartnerIcon/index.module.css b/apps/site/components/Common/Partners/PartnerIcon/index.module.css new file mode 100644 index 0000000000000..5ca11edb40806 --- /dev/null +++ b/apps/site/components/Common/Partners/PartnerIcon/index.module.css @@ -0,0 +1,13 @@ +@reference "../../../../styles/index.css"; + +.partnerIcon { + @apply h-9! + w-auto! + min-w-9! + !p-2; + + svg { + @apply !h-4 + !w-auto; + } +} diff --git a/apps/site/components/Common/Partners/PartnerIcon/index.tsx b/apps/site/components/Common/Partners/PartnerIcon/index.tsx new file mode 100644 index 0000000000000..c2c713816d73a --- /dev/null +++ b/apps/site/components/Common/Partners/PartnerIcon/index.tsx @@ -0,0 +1,26 @@ +import Skeleton from '@node-core/ui-components/Common/Skeleton'; +import type { ComponentProps, FC } from 'react'; +import { cloneElement } from 'react'; + +import type { Partners } from '#site/types'; + +import style from './index.module.css'; +import Button from '../../Button'; + +type ParnetsIconProps = Partners & ComponentProps; + +const PartnersIcon: FC = ({ href, logo, loading }) => { + return ( + + + + ); +}; + +export default PartnersIcon; diff --git a/apps/site/components/Common/Partners/PartnersIconList/index.module.css b/apps/site/components/Common/Partners/PartnersIconList/index.module.css new file mode 100644 index 0000000000000..ebba90ad3787b --- /dev/null +++ b/apps/site/components/Common/Partners/PartnersIconList/index.module.css @@ -0,0 +1,9 @@ +@reference "../../../../styles/index.css"; + +.partnersIconList { + @apply flex + flex-row + flex-wrap + items-center + gap-2; +} diff --git a/apps/site/components/Common/Partners/PartnersIconList/index.tsx b/apps/site/components/Common/Partners/PartnersIconList/index.tsx new file mode 100644 index 0000000000000..2425a3da0331f --- /dev/null +++ b/apps/site/components/Common/Partners/PartnersIconList/index.tsx @@ -0,0 +1,62 @@ +'use client'; + +import { useEffect, useRef, useState, type FC } from 'react'; + +import PARTNERS from '#site/next.partners.constants'; +import type { PartnerCategory, Partners } from '#site/types'; + +import PartnerIcon from '../PartnerIcon'; +import style from './index.module.css'; +import { randomPartnerList } from '../utils'; + +type PartnersIconListProps = { + maxLength?: number; + categories?: PartnerCategory; +}; + +const PartnersIconList: FC = ({ + maxLength = 6, + categories, +}) => { + const initialRenderer = useRef(true); + + const [seedList, setSeedList] = useState>( + PARTNERS.slice(0, maxLength) + ); + + useEffect(() => { + // We intentionally render the initial default "mock" list of sponsors + // to have the Skeletons loading, and then we render the actual list + // after an enough amount of time has passed to give a proper sense of Animation + // We do this client-side effect, to ensure that a random-amount of sponsors is renderered + // on every page load. Since our page is natively static, we need to ensure that + // on the client-side we have a random amount of sponsors rendered. + // Although whilst we are deployed on Vercel or other environment that supports ISR + // (Incremental Static Generation) whose would invalidate the cache every 5 minutes + // We want to ensure that this feature is compatible on a full-static environment + const renderSponsorsAnimation = setTimeout(() => { + initialRenderer.current = false; + + setSeedList(randomPartnerList(PARTNERS, maxLength, 1, categories)); + }, 0); + + return () => clearTimeout(renderSponsorsAnimation); + // We only want this to run once on initial render + // We don't really care if the props change as realistically they shouldn't ever + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return ( +
+ {seedList.map((partner, index) => ( + + ))} +
+ ); +}; + +export default PartnersIconList; diff --git a/apps/site/components/Common/Partners/utils.ts b/apps/site/components/Common/Partners/utils.ts new file mode 100644 index 0000000000000..79683e6492368 --- /dev/null +++ b/apps/site/components/Common/Partners/utils.ts @@ -0,0 +1,48 @@ +import type { PartnerCategory, Partners } from '#site/types/partners.js'; + +function randomPartnerList( + partners: Array, + pick = 4, + dateSeed = 5, + category?: PartnerCategory +) { + const now = new Date(); + const minutes = Math.floor(now.getUTCMinutes() / dateSeed) * dateSeed; + + const fixedTime = new Date( + Date.UTC( + now.getUTCFullYear(), + now.getUTCMonth(), + now.getUTCDate(), + now.getUTCHours(), + minutes, + 0, + 0 + ) + ); + + // We create a seed from the rounded date (timestamp in ms) + const seed = fixedTime.getTime(); + const rng = mulberry32(seed); + + // Create a copy of the array to avoid modifying the original + const shuffled = partners + .filter(partner => !category || partner.categories.includes(category)) + .slice() + .sort(() => rng() - 0.5); + + return shuffled.slice(0, pick); +} + +// This function returns a random list of partners based on a fixed time seed + +function mulberry32(seed: number) { + return function () { + let t = (seed += 0x6d2b79f5); + t = Math.imul(t ^ (t >>> 15), t | 1); + t ^= t + Math.imul(t ^ (t >>> 7), t | 61); + return ((t ^ (t >>> 14)) >>> 0) / 4294967296; + }; +} + +export { randomPartnerList }; diff --git a/apps/site/navigation.json b/apps/site/navigation.json index cfc6114362475..e2a26b00bcd1b 100644 --- a/apps/site/navigation.json +++ b/apps/site/navigation.json @@ -117,6 +117,10 @@ "branding": { "link": "/about/branding", "label": "components.navigation.about.links.branding" + }, + "partners": { + "link": "/about/partners", + "label": "components.navigation.about.links.partners" } } }, diff --git a/apps/site/next.mdx.use.mjs b/apps/site/next.mdx.use.mjs index b67817de4e9ff..b14ecada80e6b 100644 --- a/apps/site/next.mdx.use.mjs +++ b/apps/site/next.mdx.use.mjs @@ -3,6 +3,7 @@ import BadgeGroup from '@node-core/ui-components/Common/BadgeGroup'; import Button from './components/Common/Button'; +import PartnersIconList from './components/Common/Partners/PartnersIconList'; import DownloadReleasesTable from './components/Downloads/DownloadReleasesTable'; import Link from './components/Link'; import LinkWithArrow from './components/LinkWithArrow'; @@ -24,6 +25,8 @@ export const mdxComponents = { WithBanner, // HOC for providing Badge Data WithBadgeGroup, + // Shows a list of Node.js Partners + PartnersIconList, // Standalone Badge Group BadgeGroup, // Renders an container for Upcoming Node.js Meetings diff --git a/apps/site/next.partners.constants.tsx b/apps/site/next.partners.constants.tsx new file mode 100644 index 0000000000000..16a8911805b7a --- /dev/null +++ b/apps/site/next.partners.constants.tsx @@ -0,0 +1,7 @@ +import type { Partners } from '#site/types'; +import { partnersList } from '#site/util/partners'; +import partners from '#site/util/partners/constants.json' with { type: 'json' }; + +const PARTNERS = partnersList(partners as Array>); + +export default PARTNERS as Array; diff --git a/apps/site/pages/en/index.mdx b/apps/site/pages/en/index.mdx index 02f5c43bd78a2..9667d9c81959f 100644 --- a/apps/site/pages/en/index.mdx +++ b/apps/site/pages/en/index.mdx @@ -26,6 +26,11 @@ layout: home
for Node.js 18 and below + +
+ +
+ Node.js is proudly supported by the partners above and more. diff --git a/apps/site/types/index.ts b/apps/site/types/index.ts index 38f5767b732db..4ca7f7a004c69 100644 --- a/apps/site/types/index.ts +++ b/apps/site/types/index.ts @@ -10,6 +10,7 @@ export * from './redirects'; export * from './server'; export * from './github'; export * from './calendar'; +export * from './partners'; export * from './author'; export * from './download'; export * from './userAgent'; diff --git a/apps/site/types/partners.ts b/apps/site/types/partners.ts new file mode 100644 index 0000000000000..fe2793bbebdb1 --- /dev/null +++ b/apps/site/types/partners.ts @@ -0,0 +1,20 @@ +// import type { ReactElement, SVGProps } from 'react'; + +import type { ReactElement, SVGProps } from 'react'; + +export interface Partners { + id: string; + // The name of the partner + name: string; + // A logo to render on the partners page + logo: ReactElement>; + // The promoted link to their website or social media + href: string; + // The categories this partner belongs to + categories: Array; + // An optional description of the partner + description?: string; + threshold: number; +} + +export type PartnerCategory = 'infrastructure' | 'security' | 'esp partner'; diff --git a/apps/site/util/partners/constants.json b/apps/site/util/partners/constants.json new file mode 100644 index 0000000000000..937099f5fcb80 --- /dev/null +++ b/apps/site/util/partners/constants.json @@ -0,0 +1,58 @@ +[ + { + "id": "RACKSPACE", + "name": "Rackspace", + "href": "https://www.rackspace.com", + "threshold": 2, + "categories": ["infrastructure"] + }, + { + "id": "CLOUDFLARE", + "name": "Cloudflare", + "href": "https://www.cloudflare.com", + "threshold": 3, + "categories": ["infrastructure"] + }, + { + "id": "VERCEL", + "name": "Vercel", + "href": "https://vercel.com", + "threshold": 1, + "categories": ["infrastructure"] + }, + { + "id": "SENTRY", + "name": "Sentry", + "href": "https://sentry.io", + "threshold": 3, + "categories": ["infrastructure"] + }, + { + "id": "CROWDIN", + "name": "Crowdin", + "href": "https://crowdin.com", + "threshold": 2, + "categories": ["infrastructure"] + }, + { + "id": "HERODEVS", + "name": "HeroDevs", + "href": "https://herodevs.com", + "threshold": 1, + "categories": ["security", "esp partner"] + }, + { + "id": "NODESOURCE", + "name": "NodeSource", + "href": "https://nodesource.com", + "threshold": 2, + "categories": ["security"] + }, + { + "id": "DATADOG", + "name": "Datadog", + "href": "https://www.datadoghq.com", + "threshold": 3, + "categories": ["security"] + } +] diff --git a/apps/site/util/partners/index.tsx b/apps/site/util/partners/index.tsx new file mode 100644 index 0000000000000..926f2cc6a06e6 --- /dev/null +++ b/apps/site/util/partners/index.tsx @@ -0,0 +1,27 @@ +import * as PartnersLogo from '@node-core/ui-components/Icons/PartnerLogos'; +import type { ElementType } from 'react'; + +import type { Partners } from '#site/types'; + +// import partners from './constants.json'; + +/** + * Creates an icon element for a component + */ +const createIcon = ( + IconModule: Record, + iconName: string +) => { + const IconComponent = IconModule[iconName]; + return ; +}; + +// Package Manager dropdown items +export const partnersList = (partnerLists: Array>) => + partnerLists.map(({ id, ...partner }) => { + return { + id: id, + logo: createIcon(PartnersLogo, id), + ...partner, + }; + }); diff --git a/apps/site/util/partners/original.json b/apps/site/util/partners/original.json new file mode 100644 index 0000000000000..aeb840a500914 --- /dev/null +++ b/apps/site/util/partners/original.json @@ -0,0 +1,129 @@ +[ + { + "id": "DIGITALOCEAN", + "name": "DigitalOcean", + "href": "https://www.digitalocean.com", + "categories": ["infrastructure"] + }, + { + "id": "RACKSPACE", + "name": "Rackspace", + "href": "https://www.rackspace.com", + "categories": ["infrastructure"] + }, + { + "id": "MICROSOFT", + "name": "Microsoft", + "href": "https://microsoft.com", + "categories": ["infrastructure"] + }, + { + "id": "MNX", + "name": "MNX", + "href": "ToDo", + "logo": "ToDo", + "categories": ["infrastructure"] + }, + { + "id": "IBM", + "name": "IBM", + "href": "https://www.ibm.com", + "categories": ["infrastructure"] + }, + { + "id": "SCALEWAY", + "name": "Scaleway", + "href": "https://www.scaleway.com", + "categories": ["infrastructure"] + }, + { + "id": "CLOUDFLARE", + "name": "Cloudflare", + "href": "https://www.cloudflare.com", + "categories": ["infrastructure"] + }, + { + "id": "ARM", + "name": "ARM", + "href": "https://www.arm.com", + "categories": ["infrastructure"] + }, + { + "id": "INTEL", + "name": "Intel", + "href": "https://www.intel.com", + "categories": ["infrastructure"] + }, + { + "id": "MACSTADIUM", + "name": "MacStadium", + "href": "https://www.macstadium.com", + "categories": ["infrastructure"] + }, + { + "id": "EQUINIXMETAL", + "name": "Equinix Metal", + "href": "https://www.equinix.com", + "categories": ["infrastructure"] + }, + { + "id": "CHROMATIC", + "name": "Chromatic", + "href": "https://www.chromatic.com", + "categories": ["infrastructure"] + }, + { + "id": "VERCEL", + "name": "Vercel", + "href": "https://vercel.com", + "categories": ["infrastructure"] + }, + { + "id": "SENTRY", + "name": "Sentry", + "href": "https://sentry.io", + "categories": ["infrastructure"] + }, + { + "id": "CROWDIN", + "name": "Crowdin", + "href": "https://crowdin.com", + "categories": ["infrastructure"] + }, + { + "id": "ORAMA", + "name": "Orama", + "href": "https://orama.com", + "categories": ["infrastructure"] + }, + { + "id": "HERODEVS", + "name": "HeroDevs", + "href": "https://herodevs.com", + "categories": ["security", "esp partner"] + }, + { + "id": "NODESOURCE", + "name": "NodeSource", + "href": "https://nodesource.com", + "categories": ["security"] + }, + { + "id": "PLATFORMATIC", + "name": "Platformatic", + "href": "https://platformatic.dev", + "categories": ["security"] + }, + { + "id": "REDHAT", + "name": "Red Hat", + "href": "https://www.redhat.com", + "categories": ["security"] + }, + { + "id": "DATADOG", + "name": "Datadog", + "href": "https://www.datadoghq.com", + "categories": ["security"] + } +] diff --git a/packages/i18n/src/locales/en.json b/packages/i18n/src/locales/en.json index cadcca42859f3..3f2084bb8508b 100644 --- a/packages/i18n/src/locales/en.json +++ b/packages/i18n/src/locales/en.json @@ -144,7 +144,8 @@ "branding": "Branding of Node.js", "governance": "Project Governance", "releases": "Node.js Releases", - "security": "Security Reporting" + "security": "Security Reporting", + "partners": "Partners" } }, "getInvolved": { diff --git a/packages/ui-components/src/Icons/PartnerLogos/Cloudflare.tsx b/packages/ui-components/src/Icons/PartnerLogos/Cloudflare.tsx new file mode 100644 index 0000000000000..59e5deca5bc35 --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/Cloudflare.tsx @@ -0,0 +1,23 @@ +// https://www.cloudflare.com/logo/ +import type { FC, SVGProps } from 'react'; + +const Cloudflare: FC> = props => ( + + + + +); + +export default Cloudflare; diff --git a/packages/ui-components/src/Icons/PartnerLogos/Crowdin.tsx b/packages/ui-components/src/Icons/PartnerLogos/Crowdin.tsx new file mode 100644 index 0000000000000..c9eb2810e15a3 --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/Crowdin.tsx @@ -0,0 +1,49 @@ +import type { FC, SVGProps } from 'react'; + +const Crowdin: FC> = props => ( + + + + + + + + + + + + + + + +); + +export default Crowdin; diff --git a/packages/ui-components/src/Icons/PartnerLogos/DataDog.tsx b/packages/ui-components/src/Icons/PartnerLogos/DataDog.tsx new file mode 100644 index 0000000000000..5b80b2295dfff --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/DataDog.tsx @@ -0,0 +1,56 @@ +import classNames from 'classnames'; +import type { FC, SVGProps } from 'react'; + +const DataDog: FC> = props => ( + + + +); + +export default DataDog; diff --git a/packages/ui-components/src/Icons/PartnerLogos/HeroDevs.tsx b/packages/ui-components/src/Icons/PartnerLogos/HeroDevs.tsx new file mode 100644 index 0000000000000..88d9cbcde3c88 --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/HeroDevs.tsx @@ -0,0 +1,56 @@ +import type { FC, SVGProps } from 'react'; + +const HeroDevs: FC> = props => ( + + + + + + + + + + + + + + + + + + + +); + +export default HeroDevs; diff --git a/packages/ui-components/src/Icons/PartnerLogos/NodeSource.tsx b/packages/ui-components/src/Icons/PartnerLogos/NodeSource.tsx new file mode 100644 index 0000000000000..eb1f12dacc349 --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/NodeSource.tsx @@ -0,0 +1,13 @@ +import type { FC, SVGProps } from 'react'; + +const NodeSource: FC> = props => ( + + mark-light-1 + + +); + +export default NodeSource; diff --git a/packages/ui-components/src/Icons/PartnerLogos/Rackspace.tsx b/packages/ui-components/src/Icons/PartnerLogos/Rackspace.tsx new file mode 100644 index 0000000000000..516b2e56f5012 --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/Rackspace.tsx @@ -0,0 +1,19 @@ +// https://www.rackspace.com/newsroom/media-kit +import classNames from 'classnames'; +import type { FC, SVGProps } from 'react'; + +const Rackspace: FC> = props => ( + + + +); + +export default Rackspace; diff --git a/packages/ui-components/src/Icons/PartnerLogos/Sentry.tsx b/packages/ui-components/src/Icons/PartnerLogos/Sentry.tsx new file mode 100644 index 0000000000000..26b826e128f39 --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/Sentry.tsx @@ -0,0 +1,20 @@ +import classNames from 'classnames'; +import type { FC, SVGProps } from 'react'; + +const Sentry: FC> = props => ( + + + +); + +export default Sentry; diff --git a/packages/ui-components/src/Icons/PartnerLogos/Vercel.tsx b/packages/ui-components/src/Icons/PartnerLogos/Vercel.tsx new file mode 100644 index 0000000000000..1685490bcd3fa --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/Vercel.tsx @@ -0,0 +1,18 @@ +import classNames from 'classnames'; +import type { FC, SVGProps } from 'react'; + +const Vercel: FC> = props => ( + + + +); + +export default Vercel; diff --git a/packages/ui-components/src/Icons/PartnerLogos/index.ts b/packages/ui-components/src/Icons/PartnerLogos/index.ts new file mode 100644 index 0000000000000..5ea78e7296f5a --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/index.ts @@ -0,0 +1,19 @@ +import CLOUDFLARE from './Cloudflare'; +import CROWDIN from './Crowdin'; +import DATADOG from './DataDog'; +import HERODEVS from './HeroDevs'; +import NODESOURCE from './NodeSource'; +import RACKSPACE from './Rackspace'; +import SENTRY from './Sentry'; +import VERCEL from './Vercel'; + +export { + CLOUDFLARE, + CROWDIN, + DATADOG, + HERODEVS, + NODESOURCE, + RACKSPACE, + SENTRY, + VERCEL, +}; From 50947984bfff37bf3bca768b7c889ea7001ebcf0 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Mon, 21 Jul 2025 22:08:31 +0000 Subject: [PATCH 02/21] chore: template for partner page --- apps/site/pages/en/about/partners.mdx | 28 +++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 apps/site/pages/en/about/partners.mdx diff --git a/apps/site/pages/en/about/partners.mdx b/apps/site/pages/en/about/partners.mdx new file mode 100644 index 0000000000000..4c0eafb460148 --- /dev/null +++ b/apps/site/pages/en/about/partners.mdx @@ -0,0 +1,28 @@ +--- +title: Partners +layout: about +--- + +# Partners + +Importance of partners and their role and explains our partner categories (Ecosystem Sustainability Program, Infrastructure, Security, etc) + +## Infrastructure + +Projects with their logo, name, tier, the description and a CTA button + +## Security + +Projects with their logo, name, tier, the description and a CTA button + +## Ecosystem Sustainability Program (ESP) + +Projects with their logo, name, tier, the description and a CTA button + +## Backers (Open Collective and GitHub Sponsors) + +Show a list of lists direct individual or organizational support that can be done through OpenCollective and GitHub Sponsors + +## Become a Partner + +this section isn't in the specification From 6a5568ccc45649e8f7570ca864adf2ba00569183 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Mon, 21 Jul 2025 23:13:28 +0000 Subject: [PATCH 03/21] ui: add name tooltip for partnerIcon --- .../Common/Partners/PartnerIcon/index.tsx | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/apps/site/components/Common/Partners/PartnerIcon/index.tsx b/apps/site/components/Common/Partners/PartnerIcon/index.tsx index c2c713816d73a..65424a3673680 100644 --- a/apps/site/components/Common/Partners/PartnerIcon/index.tsx +++ b/apps/site/components/Common/Partners/PartnerIcon/index.tsx @@ -1,4 +1,5 @@ import Skeleton from '@node-core/ui-components/Common/Skeleton'; +import Tooltip from '@node-core/ui-components/Common/Tooltip'; import type { ComponentProps, FC } from 'react'; import { cloneElement } from 'react'; @@ -9,16 +10,18 @@ import Button from '../../Button'; type ParnetsIconProps = Partners & ComponentProps; -const PartnersIcon: FC = ({ href, logo, loading }) => { +const PartnersIcon: FC = ({ name, href, logo, loading }) => { return ( - + + + ); }; From e646e298757d77346cab1e5011c9e30334155006 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Tue, 22 Jul 2025 01:56:00 +0000 Subject: [PATCH 04/21] chore: implement list of logos on download and partners page --- .../Partners/PartnerLogo/index.module.css | 19 ++++ .../Common/Partners/PartnerLogo/index.tsx | 26 ++++++ .../Partners/PartnersIconList/index.tsx | 6 +- .../PartnersLogoList/index.module.css | 7 ++ .../Partners/PartnersLogoList/index.tsx | 62 +++++++++++++ apps/site/components/Common/Partners/utils.ts | 2 + apps/site/next.mdx.use.mjs | 5 +- apps/site/next.partners.constants.tsx | 8 +- apps/site/pages/en/about/partners.mdx | 6 ++ apps/site/pages/en/download/current.mdx | 12 +++ apps/site/pages/en/download/index.mdx | 12 +++ apps/site/types/partners.ts | 2 +- apps/site/util/partners/constants.json | 2 +- apps/site/util/partners/index.tsx | 14 +-- .../Favicon.tsx} | 0 .../Icons/PartnerLogos/Cloudflare/Logo.tsx | 63 ++++++++++++++ .../Icons/PartnerLogos/Cloudflare/index.tsx | 4 + .../{Crowdin.tsx => Crowdin/Favicon.tsx} | 0 .../src/Icons/PartnerLogos/Crowdin/Logo.tsx | 86 +++++++++++++++++++ .../src/Icons/PartnerLogos/Crowdin/index.tsx | 4 + .../{DataDog.tsx => DataDog/Favicon.tsx} | 0 .../src/Icons/PartnerLogos/DataDog/Logo.tsx | 76 ++++++++++++++++ .../src/Icons/PartnerLogos/DataDog/index.ts | 4 + .../{HeroDevs.tsx => HeroDevs/Favicon.tsx} | 0 .../src/Icons/PartnerLogos/HeroDevs/Logo.tsx | 85 ++++++++++++++++++ .../src/Icons/PartnerLogos/HeroDevs/index.ts | 4 + .../Favicon.tsx} | 1 - .../Icons/PartnerLogos/NodeSource/Logo.tsx | 22 +++++ .../Icons/PartnerLogos/NodeSource/index.ts | 4 + .../{Rackspace.tsx => Rackspace/Favicon.tsx} | 0 .../src/Icons/PartnerLogos/Rackspace/Logo.tsx | 19 ++++ .../src/Icons/PartnerLogos/Rackspace/index.ts | 4 + .../{Sentry.tsx => Sentry/Favicon.tsx} | 0 .../src/Icons/PartnerLogos/Sentry/Logo.tsx | 19 ++++ .../src/Icons/PartnerLogos/Sentry/index.ts | 4 + .../{Vercel.tsx => Vercel/Favicon.tsx} | 0 .../src/Icons/PartnerLogos/Vercel/Logo.tsx | 23 +++++ .../src/Icons/PartnerLogos/Vercel/index.ts | 4 + .../src/Icons/PartnerLogos/index.ts | 16 ++-- 39 files changed, 603 insertions(+), 22 deletions(-) create mode 100644 apps/site/components/Common/Partners/PartnerLogo/index.module.css create mode 100644 apps/site/components/Common/Partners/PartnerLogo/index.tsx create mode 100644 apps/site/components/Common/Partners/PartnersLogoList/index.module.css create mode 100644 apps/site/components/Common/Partners/PartnersLogoList/index.tsx rename packages/ui-components/src/Icons/PartnerLogos/{Cloudflare.tsx => Cloudflare/Favicon.tsx} (100%) create mode 100644 packages/ui-components/src/Icons/PartnerLogos/Cloudflare/Logo.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/Cloudflare/index.tsx rename packages/ui-components/src/Icons/PartnerLogos/{Crowdin.tsx => Crowdin/Favicon.tsx} (100%) create mode 100644 packages/ui-components/src/Icons/PartnerLogos/Crowdin/Logo.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/Crowdin/index.tsx rename packages/ui-components/src/Icons/PartnerLogos/{DataDog.tsx => DataDog/Favicon.tsx} (100%) create mode 100644 packages/ui-components/src/Icons/PartnerLogos/DataDog/Logo.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/DataDog/index.ts rename packages/ui-components/src/Icons/PartnerLogos/{HeroDevs.tsx => HeroDevs/Favicon.tsx} (100%) create mode 100644 packages/ui-components/src/Icons/PartnerLogos/HeroDevs/Logo.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/HeroDevs/index.ts rename packages/ui-components/src/Icons/PartnerLogos/{NodeSource.tsx => NodeSource/Favicon.tsx} (97%) create mode 100644 packages/ui-components/src/Icons/PartnerLogos/NodeSource/Logo.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/NodeSource/index.ts rename packages/ui-components/src/Icons/PartnerLogos/{Rackspace.tsx => Rackspace/Favicon.tsx} (100%) create mode 100644 packages/ui-components/src/Icons/PartnerLogos/Rackspace/Logo.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/Rackspace/index.ts rename packages/ui-components/src/Icons/PartnerLogos/{Sentry.tsx => Sentry/Favicon.tsx} (100%) create mode 100644 packages/ui-components/src/Icons/PartnerLogos/Sentry/Logo.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/Sentry/index.ts rename packages/ui-components/src/Icons/PartnerLogos/{Vercel.tsx => Vercel/Favicon.tsx} (100%) create mode 100644 packages/ui-components/src/Icons/PartnerLogos/Vercel/Logo.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/Vercel/index.ts diff --git a/apps/site/components/Common/Partners/PartnerLogo/index.module.css b/apps/site/components/Common/Partners/PartnerLogo/index.module.css new file mode 100644 index 0000000000000..a03bf704d716f --- /dev/null +++ b/apps/site/components/Common/Partners/PartnerLogo/index.module.css @@ -0,0 +1,19 @@ +@reference "../../../../styles/index.css"; + +.partnerIcon { + @apply flex + h-[114px] + max-h-[130px] + w-auto + min-w-12 + items-center + justify-center + rounded-lg + p-6 + sm:p-10; + + svg { + @apply !h-12 + !w-auto; + } +} diff --git a/apps/site/components/Common/Partners/PartnerLogo/index.tsx b/apps/site/components/Common/Partners/PartnerLogo/index.tsx new file mode 100644 index 0000000000000..23ed2b22cca17 --- /dev/null +++ b/apps/site/components/Common/Partners/PartnerLogo/index.tsx @@ -0,0 +1,26 @@ +import Skeleton from '@node-core/ui-components/Common/Skeleton'; +import type { ComponentProps, FC } from 'react'; +import { cloneElement } from 'react'; + +import type { Partners } from '#site/types'; + +import style from './index.module.css'; +import Button from '../../Button'; + +type ParnetsIconProps = Partners & ComponentProps; + +const PartnersIcon: FC = ({ href, logo, loading }) => { + return ( + + + + ); +}; + +export default PartnersIcon; diff --git a/apps/site/components/Common/Partners/PartnersIconList/index.tsx b/apps/site/components/Common/Partners/PartnersIconList/index.tsx index 2425a3da0331f..3667090d56467 100644 --- a/apps/site/components/Common/Partners/PartnersIconList/index.tsx +++ b/apps/site/components/Common/Partners/PartnersIconList/index.tsx @@ -2,7 +2,7 @@ import { useEffect, useRef, useState, type FC } from 'react'; -import PARTNERS from '#site/next.partners.constants'; +import { ICON_PARTNERS } from '#site/next.partners.constants'; import type { PartnerCategory, Partners } from '#site/types'; import PartnerIcon from '../PartnerIcon'; @@ -21,7 +21,7 @@ const PartnersIconList: FC = ({ const initialRenderer = useRef(true); const [seedList, setSeedList] = useState>( - PARTNERS.slice(0, maxLength) + ICON_PARTNERS.slice(0, maxLength) ); useEffect(() => { @@ -37,7 +37,7 @@ const PartnersIconList: FC = ({ const renderSponsorsAnimation = setTimeout(() => { initialRenderer.current = false; - setSeedList(randomPartnerList(PARTNERS, maxLength, 1, categories)); + setSeedList(randomPartnerList(ICON_PARTNERS, maxLength, 1, categories)); }, 0); return () => clearTimeout(renderSponsorsAnimation); diff --git a/apps/site/components/Common/Partners/PartnersLogoList/index.module.css b/apps/site/components/Common/Partners/PartnersLogoList/index.module.css new file mode 100644 index 0000000000000..5123cd5271793 --- /dev/null +++ b/apps/site/components/Common/Partners/PartnersLogoList/index.module.css @@ -0,0 +1,7 @@ +@reference "../../../../styles/index.css"; + +.partnersLogoList { + display: grid; + gap: 16px; + grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); +} diff --git a/apps/site/components/Common/Partners/PartnersLogoList/index.tsx b/apps/site/components/Common/Partners/PartnersLogoList/index.tsx new file mode 100644 index 0000000000000..800ebd1a30e2e --- /dev/null +++ b/apps/site/components/Common/Partners/PartnersLogoList/index.tsx @@ -0,0 +1,62 @@ +'use client'; + +import { useEffect, useRef, useState, type FC } from 'react'; + +import { LOGO_PARTNERS } from '#site/next.partners.constants'; +import type { PartnerCategory, Partners } from '#site/types'; + +import PartnerLogo from '../PartnerLogo'; +import style from './index.module.css'; +import { randomPartnerList } from '../utils'; + +type PartnersLogoListProps = { + maxLength?: number; + categories?: PartnerCategory; +}; + +const PartnersLogoList: FC = ({ + maxLength = 3, + categories, +}) => { + const initialRenderer = useRef(true); + + const [seedList, setSeedList] = useState>( + LOGO_PARTNERS.slice(0, maxLength) + ); + + useEffect(() => { + // We intentionally render the initial default "mock" list of sponsors + // to have the Skeletons loading, and then we render the actual list + // after an enough amount of time has passed to give a proper sense of Animation + // We do this client-side effect, to ensure that a random-amount of sponsors is renderered + // on every page load. Since our page is natively static, we need to ensure that + // on the client-side we have a random amount of sponsors rendered. + // Although whilst we are deployed on Vercel or other environment that supports ISR + // (Incremental Static Generation) whose would invalidate the cache every 5 minutes + // We want to ensure that this feature is compatible on a full-static environment + const renderSponsorsAnimation = setTimeout(() => { + initialRenderer.current = false; + + setSeedList(randomPartnerList(LOGO_PARTNERS, maxLength, 1, categories)); + }, 0); + + return () => clearTimeout(renderSponsorsAnimation); + // We only want this to run once on initial render + // We don't really care if the props change as realistically they shouldn't ever + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return ( +
+ {seedList.map((partner, index) => ( + + ))} +
+ ); +}; + +export default PartnersLogoList; diff --git a/apps/site/components/Common/Partners/utils.ts b/apps/site/components/Common/Partners/utils.ts index 79683e6492368..fcc5e51b95a2e 100644 --- a/apps/site/components/Common/Partners/utils.ts +++ b/apps/site/components/Common/Partners/utils.ts @@ -1,5 +1,7 @@ import type { PartnerCategory, Partners } from '#site/types/partners.js'; +// TODO: Implement no random list +// TODO: Implement no limit items function randomPartnerList( partners: Array, pick = 4, diff --git a/apps/site/next.mdx.use.mjs b/apps/site/next.mdx.use.mjs index b14ecada80e6b..dc35c75544cff 100644 --- a/apps/site/next.mdx.use.mjs +++ b/apps/site/next.mdx.use.mjs @@ -4,6 +4,7 @@ import BadgeGroup from '@node-core/ui-components/Common/BadgeGroup'; import Button from './components/Common/Button'; import PartnersIconList from './components/Common/Partners/PartnersIconList'; +import PartnersLogoList from './components/Common/Partners/PartnersLogoList'; import DownloadReleasesTable from './components/Downloads/DownloadReleasesTable'; import Link from './components/Link'; import LinkWithArrow from './components/LinkWithArrow'; @@ -25,8 +26,10 @@ export const mdxComponents = { WithBanner, // HOC for providing Badge Data WithBadgeGroup, - // Shows a list of Node.js Partners + // Shows a list of Node.js Partners with Icons PartnersIconList, + // Shows a list of Node.js Partners with Logos + PartnersLogoList, // Standalone Badge Group BadgeGroup, // Renders an container for Upcoming Node.js Meetings diff --git a/apps/site/next.partners.constants.tsx b/apps/site/next.partners.constants.tsx index 16a8911805b7a..f63cdccaf5d09 100644 --- a/apps/site/next.partners.constants.tsx +++ b/apps/site/next.partners.constants.tsx @@ -2,6 +2,10 @@ import type { Partners } from '#site/types'; import { partnersList } from '#site/util/partners'; import partners from '#site/util/partners/constants.json' with { type: 'json' }; -const PARTNERS = partnersList(partners as Array>); +const PARTNERS = (type?: 'Logo' | 'Favicon') => + partnersList(partners as Array>, type); -export default PARTNERS as Array; +const ICON_PARTNERS = PARTNERS('Favicon'); +const LOGO_PARTNERS = PARTNERS('Logo'); + +export { ICON_PARTNERS, LOGO_PARTNERS }; diff --git a/apps/site/pages/en/about/partners.mdx b/apps/site/pages/en/about/partners.mdx index 4c0eafb460148..4f1ca98003183 100644 --- a/apps/site/pages/en/about/partners.mdx +++ b/apps/site/pages/en/about/partners.mdx @@ -11,14 +11,20 @@ Importance of partners and their role and explains our partner categories (Ecosy Projects with their logo, name, tier, the description and a CTA button + + ## Security Projects with their logo, name, tier, the description and a CTA button + + ## Ecosystem Sustainability Program (ESP) Projects with their logo, name, tier, the description and a CTA button + + ## Backers (Open Collective and GitHub Sponsors) Show a list of lists direct individual or organizational support that can be done through OpenCollective and GitHub Sponsors diff --git a/apps/site/pages/en/download/current.mdx b/apps/site/pages/en/download/current.mdx index 16e78d6a8e1d7..0ee4a3ac9a671 100644 --- a/apps/site/pages/en/download/current.mdx +++ b/apps/site/pages/en/download/current.mdx @@ -34,3 +34,15 @@ all previous releases or the unofficial binaries for other platforms. + +
+

Thanks by Our Partners

+ + + We are able to serve Node.js downloads and maintain our infrastructure thanks + to our amazing partners. + +
+ +
+
diff --git a/apps/site/pages/en/download/index.mdx b/apps/site/pages/en/download/index.mdx index 16e78d6a8e1d7..0ee4a3ac9a671 100644 --- a/apps/site/pages/en/download/index.mdx +++ b/apps/site/pages/en/download/index.mdx @@ -34,3 +34,15 @@ all previous releases or the unofficial binaries for other platforms. + +
+

Thanks by Our Partners

+ + + We are able to serve Node.js downloads and maintain our infrastructure thanks + to our amazing partners. + +
+ +
+
diff --git a/apps/site/types/partners.ts b/apps/site/types/partners.ts index fe2793bbebdb1..e5bc840401a60 100644 --- a/apps/site/types/partners.ts +++ b/apps/site/types/partners.ts @@ -17,4 +17,4 @@ export interface Partners { threshold: number; } -export type PartnerCategory = 'infrastructure' | 'security' | 'esp partner'; +export type PartnerCategory = 'infrastructure' | 'security' | 'esp'; diff --git a/apps/site/util/partners/constants.json b/apps/site/util/partners/constants.json index 937099f5fcb80..faa6f34ac2e74 100644 --- a/apps/site/util/partners/constants.json +++ b/apps/site/util/partners/constants.json @@ -39,7 +39,7 @@ "name": "HeroDevs", "href": "https://herodevs.com", "threshold": 1, - "categories": ["security", "esp partner"] + "categories": ["security", "esp"] }, { "id": "NODESOURCE", diff --git a/apps/site/util/partners/index.tsx b/apps/site/util/partners/index.tsx index 926f2cc6a06e6..25cb3521d94ef 100644 --- a/apps/site/util/partners/index.tsx +++ b/apps/site/util/partners/index.tsx @@ -9,19 +9,23 @@ import type { Partners } from '#site/types'; * Creates an icon element for a component */ const createIcon = ( - IconModule: Record, - iconName: string + IconModule: Record>, + iconName: string, + type?: 'Logo' | 'Favicon' ) => { - const IconComponent = IconModule[iconName]; + const IconComponent = IconModule[iconName][type || 'Favicon']; return ; }; // Package Manager dropdown items -export const partnersList = (partnerLists: Array>) => +export const partnersList = ( + partnerLists: Array>, + type?: 'Logo' | 'Favicon' +) => partnerLists.map(({ id, ...partner }) => { return { id: id, - logo: createIcon(PartnersLogo, id), + logo: createIcon(PartnersLogo, id, type), ...partner, }; }); diff --git a/packages/ui-components/src/Icons/PartnerLogos/Cloudflare.tsx b/packages/ui-components/src/Icons/PartnerLogos/Cloudflare/Favicon.tsx similarity index 100% rename from packages/ui-components/src/Icons/PartnerLogos/Cloudflare.tsx rename to packages/ui-components/src/Icons/PartnerLogos/Cloudflare/Favicon.tsx diff --git a/packages/ui-components/src/Icons/PartnerLogos/Cloudflare/Logo.tsx b/packages/ui-components/src/Icons/PartnerLogos/Cloudflare/Logo.tsx new file mode 100644 index 0000000000000..0ee2f3ab21525 --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/Cloudflare/Logo.tsx @@ -0,0 +1,63 @@ +// https://www.cloudflare.com/logo/ +import classNames from 'classnames'; +import type { FC, SVGProps } from 'react'; + +const Cloudflare: FC> = props => ( + + + + + + + + + + + + + + +); + +export default Cloudflare; diff --git a/packages/ui-components/src/Icons/PartnerLogos/Cloudflare/index.tsx b/packages/ui-components/src/Icons/PartnerLogos/Cloudflare/index.tsx new file mode 100644 index 0000000000000..b4cd37328b21d --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/Cloudflare/index.tsx @@ -0,0 +1,4 @@ +import Favicon from './Favicon'; +import Logo from './Logo'; + +export { Favicon, Logo }; diff --git a/packages/ui-components/src/Icons/PartnerLogos/Crowdin.tsx b/packages/ui-components/src/Icons/PartnerLogos/Crowdin/Favicon.tsx similarity index 100% rename from packages/ui-components/src/Icons/PartnerLogos/Crowdin.tsx rename to packages/ui-components/src/Icons/PartnerLogos/Crowdin/Favicon.tsx diff --git a/packages/ui-components/src/Icons/PartnerLogos/Crowdin/Logo.tsx b/packages/ui-components/src/Icons/PartnerLogos/Crowdin/Logo.tsx new file mode 100644 index 0000000000000..cd23dc2a0883c --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/Crowdin/Logo.tsx @@ -0,0 +1,86 @@ +import classNames from 'classnames'; +import type { FC, SVGProps } from 'react'; + +const Crowdin: FC> = props => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +); + +export default Crowdin; diff --git a/packages/ui-components/src/Icons/PartnerLogos/Crowdin/index.tsx b/packages/ui-components/src/Icons/PartnerLogos/Crowdin/index.tsx new file mode 100644 index 0000000000000..b4cd37328b21d --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/Crowdin/index.tsx @@ -0,0 +1,4 @@ +import Favicon from './Favicon'; +import Logo from './Logo'; + +export { Favicon, Logo }; diff --git a/packages/ui-components/src/Icons/PartnerLogos/DataDog.tsx b/packages/ui-components/src/Icons/PartnerLogos/DataDog/Favicon.tsx similarity index 100% rename from packages/ui-components/src/Icons/PartnerLogos/DataDog.tsx rename to packages/ui-components/src/Icons/PartnerLogos/DataDog/Favicon.tsx diff --git a/packages/ui-components/src/Icons/PartnerLogos/DataDog/Logo.tsx b/packages/ui-components/src/Icons/PartnerLogos/DataDog/Logo.tsx new file mode 100644 index 0000000000000..23cd9025d84c9 --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/DataDog/Logo.tsx @@ -0,0 +1,76 @@ +import classNames from 'classnames'; +import type { FC, SVGProps } from 'react'; + +const DataDog: FC> = props => ( + + + + + + + + + + +); + +export default DataDog; diff --git a/packages/ui-components/src/Icons/PartnerLogos/DataDog/index.ts b/packages/ui-components/src/Icons/PartnerLogos/DataDog/index.ts new file mode 100644 index 0000000000000..b4cd37328b21d --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/DataDog/index.ts @@ -0,0 +1,4 @@ +import Favicon from './Favicon'; +import Logo from './Logo'; + +export { Favicon, Logo }; diff --git a/packages/ui-components/src/Icons/PartnerLogos/HeroDevs.tsx b/packages/ui-components/src/Icons/PartnerLogos/HeroDevs/Favicon.tsx similarity index 100% rename from packages/ui-components/src/Icons/PartnerLogos/HeroDevs.tsx rename to packages/ui-components/src/Icons/PartnerLogos/HeroDevs/Favicon.tsx diff --git a/packages/ui-components/src/Icons/PartnerLogos/HeroDevs/Logo.tsx b/packages/ui-components/src/Icons/PartnerLogos/HeroDevs/Logo.tsx new file mode 100644 index 0000000000000..23de36b18ecb4 --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/HeroDevs/Logo.tsx @@ -0,0 +1,85 @@ +import classNames from 'classnames'; +import type { FC, SVGProps } from 'react'; + +const HeroDevs: FC> = props => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +); + +export default HeroDevs; diff --git a/packages/ui-components/src/Icons/PartnerLogos/HeroDevs/index.ts b/packages/ui-components/src/Icons/PartnerLogos/HeroDevs/index.ts new file mode 100644 index 0000000000000..b4cd37328b21d --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/HeroDevs/index.ts @@ -0,0 +1,4 @@ +import Favicon from './Favicon'; +import Logo from './Logo'; + +export { Favicon, Logo }; diff --git a/packages/ui-components/src/Icons/PartnerLogos/NodeSource.tsx b/packages/ui-components/src/Icons/PartnerLogos/NodeSource/Favicon.tsx similarity index 97% rename from packages/ui-components/src/Icons/PartnerLogos/NodeSource.tsx rename to packages/ui-components/src/Icons/PartnerLogos/NodeSource/Favicon.tsx index eb1f12dacc349..93919fc60dc77 100644 --- a/packages/ui-components/src/Icons/PartnerLogos/NodeSource.tsx +++ b/packages/ui-components/src/Icons/PartnerLogos/NodeSource/Favicon.tsx @@ -2,7 +2,6 @@ import type { FC, SVGProps } from 'react'; const NodeSource: FC> = props => ( - mark-light-1 > = props => ( + + + + +); + +export default NodeSource; diff --git a/packages/ui-components/src/Icons/PartnerLogos/NodeSource/index.ts b/packages/ui-components/src/Icons/PartnerLogos/NodeSource/index.ts new file mode 100644 index 0000000000000..b4cd37328b21d --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/NodeSource/index.ts @@ -0,0 +1,4 @@ +import Favicon from './Favicon'; +import Logo from './Logo'; + +export { Favicon, Logo }; diff --git a/packages/ui-components/src/Icons/PartnerLogos/Rackspace.tsx b/packages/ui-components/src/Icons/PartnerLogos/Rackspace/Favicon.tsx similarity index 100% rename from packages/ui-components/src/Icons/PartnerLogos/Rackspace.tsx rename to packages/ui-components/src/Icons/PartnerLogos/Rackspace/Favicon.tsx diff --git a/packages/ui-components/src/Icons/PartnerLogos/Rackspace/Logo.tsx b/packages/ui-components/src/Icons/PartnerLogos/Rackspace/Logo.tsx new file mode 100644 index 0000000000000..060834eec06fb --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/Rackspace/Logo.tsx @@ -0,0 +1,19 @@ +// https://www.rackspace.com/newsroom/media-kit +import classNames from 'classnames'; +import type { FC, SVGProps } from 'react'; + +const Rackspace: FC> = props => ( + + + +); + +export default Rackspace; diff --git a/packages/ui-components/src/Icons/PartnerLogos/Rackspace/index.ts b/packages/ui-components/src/Icons/PartnerLogos/Rackspace/index.ts new file mode 100644 index 0000000000000..b4cd37328b21d --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/Rackspace/index.ts @@ -0,0 +1,4 @@ +import Favicon from './Favicon'; +import Logo from './Logo'; + +export { Favicon, Logo }; diff --git a/packages/ui-components/src/Icons/PartnerLogos/Sentry.tsx b/packages/ui-components/src/Icons/PartnerLogos/Sentry/Favicon.tsx similarity index 100% rename from packages/ui-components/src/Icons/PartnerLogos/Sentry.tsx rename to packages/ui-components/src/Icons/PartnerLogos/Sentry/Favicon.tsx diff --git a/packages/ui-components/src/Icons/PartnerLogos/Sentry/Logo.tsx b/packages/ui-components/src/Icons/PartnerLogos/Sentry/Logo.tsx new file mode 100644 index 0000000000000..429ecd0f3cc01 --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/Sentry/Logo.tsx @@ -0,0 +1,19 @@ +import classNames from 'classnames'; +import type { FC, SVGProps } from 'react'; + +const Sentry: FC> = props => ( + + + +); + +export default Sentry; diff --git a/packages/ui-components/src/Icons/PartnerLogos/Sentry/index.ts b/packages/ui-components/src/Icons/PartnerLogos/Sentry/index.ts new file mode 100644 index 0000000000000..b4cd37328b21d --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/Sentry/index.ts @@ -0,0 +1,4 @@ +import Favicon from './Favicon'; +import Logo from './Logo'; + +export { Favicon, Logo }; diff --git a/packages/ui-components/src/Icons/PartnerLogos/Vercel.tsx b/packages/ui-components/src/Icons/PartnerLogos/Vercel/Favicon.tsx similarity index 100% rename from packages/ui-components/src/Icons/PartnerLogos/Vercel.tsx rename to packages/ui-components/src/Icons/PartnerLogos/Vercel/Favicon.tsx diff --git a/packages/ui-components/src/Icons/PartnerLogos/Vercel/Logo.tsx b/packages/ui-components/src/Icons/PartnerLogos/Vercel/Logo.tsx new file mode 100644 index 0000000000000..858cca55d261c --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/Vercel/Logo.tsx @@ -0,0 +1,23 @@ +import classNames from 'classnames'; +import type { FC, SVGProps } from 'react'; + +const Vercel: FC> = props => ( + + + +); + +export default Vercel; diff --git a/packages/ui-components/src/Icons/PartnerLogos/Vercel/index.ts b/packages/ui-components/src/Icons/PartnerLogos/Vercel/index.ts new file mode 100644 index 0000000000000..b4cd37328b21d --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/Vercel/index.ts @@ -0,0 +1,4 @@ +import Favicon from './Favicon'; +import Logo from './Logo'; + +export { Favicon, Logo }; diff --git a/packages/ui-components/src/Icons/PartnerLogos/index.ts b/packages/ui-components/src/Icons/PartnerLogos/index.ts index 5ea78e7296f5a..c27682993c683 100644 --- a/packages/ui-components/src/Icons/PartnerLogos/index.ts +++ b/packages/ui-components/src/Icons/PartnerLogos/index.ts @@ -1,11 +1,11 @@ -import CLOUDFLARE from './Cloudflare'; -import CROWDIN from './Crowdin'; -import DATADOG from './DataDog'; -import HERODEVS from './HeroDevs'; -import NODESOURCE from './NodeSource'; -import RACKSPACE from './Rackspace'; -import SENTRY from './Sentry'; -import VERCEL from './Vercel'; +import * as CLOUDFLARE from './Cloudflare'; +import * as CROWDIN from './Crowdin'; +import * as DATADOG from './DataDog'; +import * as HERODEVS from './HeroDevs'; +import * as NODESOURCE from './NodeSource'; +import * as RACKSPACE from './Rackspace'; +import * as SENTRY from './Sentry'; +import * as VERCEL from './Vercel'; export { CLOUDFLARE, From 8302e8a46508dfca5d024e7dc542af2b58913b6e Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Tue, 22 Jul 2025 15:36:47 +0000 Subject: [PATCH 05/21] chore: add partner list on security blog post --- .../Partners/PartnersLogoList/index.module.css | 1 + apps/site/layouts/Post.tsx | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/apps/site/components/Common/Partners/PartnersLogoList/index.module.css b/apps/site/components/Common/Partners/PartnersLogoList/index.module.css index 5123cd5271793..a57ae2d4d0582 100644 --- a/apps/site/components/Common/Partners/PartnersLogoList/index.module.css +++ b/apps/site/components/Common/Partners/PartnersLogoList/index.module.css @@ -4,4 +4,5 @@ display: grid; gap: 16px; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); + width: 100%; } diff --git a/apps/site/layouts/Post.tsx b/apps/site/layouts/Post.tsx index 9b5234b727757..7e588fbdbb25d 100644 --- a/apps/site/layouts/Post.tsx +++ b/apps/site/layouts/Post.tsx @@ -1,6 +1,7 @@ import Preview from '@node-core/ui-components/Common/Preview'; import type { FC, PropsWithChildren } from 'react'; +import Link from '#site/components/Link'; import WithAvatarGroup from '#site/components/withAvatarGroup'; import WithBlogCrossLinks from '#site/components/withBlogCrossLinks'; import WithFooter from '#site/components/withFooter'; @@ -11,6 +12,7 @@ import { mapAuthorToCardAuthors } from '#site/util/author'; import { mapBlogCategoryToPreviewType } from '#site/util/blog'; import styles from './layouts.module.css'; +import PartnersLogoList from '../components/Common/Partners/PartnersLogoList'; const PostLayout: FC = ({ children }) => { const { frontmatter } = useClientContext(); @@ -37,7 +39,17 @@ const PostLayout: FC = ({ children }) => { {children} - + {type === 'vulnerability' && ( +
+

Thanks by Our Partners

+

+ We are able to offer security releases proudly due to the + support of these partners + and more. +

+ + + )} From 2f0e2bef3439b3d759c0c0c2786b058941eea0ea Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Tue, 22 Jul 2025 16:00:41 +0000 Subject: [PATCH 06/21] feat: enhance PartnersLogoList to filter partners by category and allow unlimited items --- .../Common/Partners/PartnersLogoList/index.tsx | 11 ++++++++--- apps/site/components/Common/Partners/utils.ts | 11 +++++++---- apps/site/pages/en/about/partners.mdx | 6 +++--- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/apps/site/components/Common/Partners/PartnersLogoList/index.tsx b/apps/site/components/Common/Partners/PartnersLogoList/index.tsx index 800ebd1a30e2e..c03729a4bb3f7 100644 --- a/apps/site/components/Common/Partners/PartnersLogoList/index.tsx +++ b/apps/site/components/Common/Partners/PartnersLogoList/index.tsx @@ -20,9 +20,14 @@ const PartnersLogoList: FC = ({ }) => { const initialRenderer = useRef(true); - const [seedList, setSeedList] = useState>( - LOGO_PARTNERS.slice(0, maxLength) - ); + const [seedList, setSeedList] = useState>(() => { + if (maxLength === null) { + return LOGO_PARTNERS.filter( + partner => !categories || partner.categories.includes(categories) + ); + } + return LOGO_PARTNERS.slice(0, maxLength); + }); useEffect(() => { // We intentionally render the initial default "mock" list of sponsors diff --git a/apps/site/components/Common/Partners/utils.ts b/apps/site/components/Common/Partners/utils.ts index fcc5e51b95a2e..c86e116c53f24 100644 --- a/apps/site/components/Common/Partners/utils.ts +++ b/apps/site/components/Common/Partners/utils.ts @@ -1,7 +1,7 @@ import type { PartnerCategory, Partners } from '#site/types/partners.js'; // TODO: Implement no random list -// TODO: Implement no limit items +// TODO: Implement no importance of partner function randomPartnerList( partners: Array, pick = 4, @@ -28,12 +28,15 @@ function randomPartnerList( const rng = mulberry32(seed); // Create a copy of the array to avoid modifying the original - const shuffled = partners + let shuffled = [...partners] .filter(partner => !category || partner.categories.includes(category)) - .slice() .sort(() => rng() - 0.5); - return shuffled.slice(0, pick); + if (pick !== null) { + shuffled = shuffled.slice(0, pick); + } + + return shuffled; } // This function returns a random list of partners based on a fixed time seed diff --git a/apps/site/pages/en/about/partners.mdx b/apps/site/pages/en/about/partners.mdx index 4f1ca98003183..0b3b1dbf70a61 100644 --- a/apps/site/pages/en/about/partners.mdx +++ b/apps/site/pages/en/about/partners.mdx @@ -11,19 +11,19 @@ Importance of partners and their role and explains our partner categories (Ecosy Projects with their logo, name, tier, the description and a CTA button - + ## Security Projects with their logo, name, tier, the description and a CTA button - + ## Ecosystem Sustainability Program (ESP) Projects with their logo, name, tier, the description and a CTA button - + ## Backers (Open Collective and GitHub Sponsors) From 435eb912c9785cc651c536913a0e6fc6ececb4f4 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Tue, 22 Jul 2025 20:45:17 +0000 Subject: [PATCH 07/21] feat: add new partner categories and update partner weights --- apps/site/pages/en/about/partners.mdx | 12 ++ apps/site/types/partners.ts | 10 +- apps/site/util/partners/constants.json | 24 ++-- apps/site/util/partners/original.json | 156 ++++++++++++++++--------- 4 files changed, 131 insertions(+), 71 deletions(-) diff --git a/apps/site/pages/en/about/partners.mdx b/apps/site/pages/en/about/partners.mdx index 0b3b1dbf70a61..ea8d1e5d5bee7 100644 --- a/apps/site/pages/en/about/partners.mdx +++ b/apps/site/pages/en/about/partners.mdx @@ -25,6 +25,18 @@ Projects with their logo, name, tier, the description and a CTA button +## Releases + +Projects with their logo, name, tier, the description and a CTA button + + + +## Services + +Projects with their logo, name, tier, the description and a CTA button + + + ## Backers (Open Collective and GitHub Sponsors) Show a list of lists direct individual or organizational support that can be done through OpenCollective and GitHub Sponsors diff --git a/apps/site/types/partners.ts b/apps/site/types/partners.ts index e5bc840401a60..61a07d5f43e1a 100644 --- a/apps/site/types/partners.ts +++ b/apps/site/types/partners.ts @@ -14,7 +14,13 @@ export interface Partners { categories: Array; // An optional description of the partner description?: string; - threshold: number; + // The weight of the partner, used for random selection + weight: number; } -export type PartnerCategory = 'infrastructure' | 'security' | 'esp'; +export type PartnerCategory = + | 'infrastructure' + | 'security' + | 'esp' + | 'release' + | 'service'; diff --git a/apps/site/util/partners/constants.json b/apps/site/util/partners/constants.json index faa6f34ac2e74..1612f787d8f02 100644 --- a/apps/site/util/partners/constants.json +++ b/apps/site/util/partners/constants.json @@ -3,56 +3,56 @@ "id": "RACKSPACE", "name": "Rackspace", "href": "https://www.rackspace.com", - "threshold": 2, + "weight": 3, "categories": ["infrastructure"] }, { "id": "CLOUDFLARE", "name": "Cloudflare", "href": "https://www.cloudflare.com", - "threshold": 3, + "weight": 3, "categories": ["infrastructure"] }, { "id": "VERCEL", "name": "Vercel", "href": "https://vercel.com", - "threshold": 1, + "weight": 2, "categories": ["infrastructure"] }, { "id": "SENTRY", "name": "Sentry", "href": "https://sentry.io", - "threshold": 3, - "categories": ["infrastructure"] + "weight": 1, + "categories": ["service"] }, { "id": "CROWDIN", "name": "Crowdin", "href": "https://crowdin.com", - "threshold": 2, - "categories": ["infrastructure"] + "weight": 1, + "categories": ["service"] }, { "id": "HERODEVS", "name": "HeroDevs", "href": "https://herodevs.com", - "threshold": 1, - "categories": ["security", "esp"] + "weight": 2, + "categories": ["security", "esp", "release"] }, { "id": "NODESOURCE", "name": "NodeSource", "href": "https://nodesource.com", - "threshold": 2, - "categories": ["security"] + "weight": 2, + "categories": ["security", "release"] }, { "id": "DATADOG", "name": "Datadog", "href": "https://www.datadoghq.com", - "threshold": 3, + "weight": 2, "categories": ["security"] } ] diff --git a/apps/site/util/partners/original.json b/apps/site/util/partners/original.json index aeb840a500914..a63657ac50ff3 100644 --- a/apps/site/util/partners/original.json +++ b/apps/site/util/partners/original.json @@ -1,129 +1,171 @@ [ - { - "id": "DIGITALOCEAN", - "name": "DigitalOcean", - "href": "https://www.digitalocean.com", - "categories": ["infrastructure"] - }, { "id": "RACKSPACE", "name": "Rackspace", "href": "https://www.rackspace.com", + "weight": 3, + "categories": ["infrastructure"] + }, + { + "id": "CLOUDFLARE", + "name": "Cloudflare", + "href": "https://www.cloudflare.com", + "weight": 3, + "categories": ["infrastructure"] + }, + { + "id": "VERCEL", + "name": "Vercel", + "href": "https://vercel.com", + "weight": 2, "categories": ["infrastructure"] }, + { + "id": "SENTRY", + "name": "Sentry", + "href": "https://sentry.io", + "weight": 1, + "categories": ["infrastructure"] + }, + { + "id": "CROWDIN", + "name": "Crowdin", + "href": "https://crowdin.com", + "weight": 1, + "categories": ["service"] + }, + { + "id": "HERODEVS", + "name": "HeroDevs", + "href": "https://herodevs.com", + "weight": 3, + "categories": ["security", "esp", "release"] + }, + { + "id": "NODESOURCE", + "name": "NodeSource", + "href": "https://nodesource.com", + "weight": 2, + "categories": ["security", "release"] + }, + { + "id": "DATADOG", + "name": "Datadog", + "href": "https://www.datadoghq.com", + "weight": 2, + "categories": ["security"] + }, + { + "id": "DIGITALOCEAN", + "name": "DigitalOcean", + "href": "https://www.digitalocean.com", + "categories": ["infrastructure"], + "weight": 3 + }, { "id": "MICROSOFT", "name": "Microsoft", "href": "https://microsoft.com", - "categories": ["infrastructure"] + "categories": ["infrastructure"], + "weight": 2 }, { "id": "MNX", "name": "MNX", "href": "ToDo", "logo": "ToDo", - "categories": ["infrastructure"] + "categories": ["infrastructure"], + "weight": 2 }, { "id": "IBM", "name": "IBM", "href": "https://www.ibm.com", - "categories": ["infrastructure"] + "categories": ["infrastructure", "release"], + "weight": 3 }, { "id": "SCALEWAY", "name": "Scaleway", "href": "https://www.scaleway.com", - "categories": ["infrastructure"] - }, - { - "id": "CLOUDFLARE", - "name": "Cloudflare", - "href": "https://www.cloudflare.com", - "categories": ["infrastructure"] + "categories": ["infrastructure"], + "weight": 2 }, { "id": "ARM", "name": "ARM", "href": "https://www.arm.com", - "categories": ["infrastructure"] + "categories": ["infrastructure"], + "weight": 2 }, { "id": "INTEL", "name": "Intel", "href": "https://www.intel.com", - "categories": ["infrastructure"] + "categories": ["infrastructure"], + "weight": 2 }, { "id": "MACSTADIUM", "name": "MacStadium", "href": "https://www.macstadium.com", - "categories": ["infrastructure"] + "categories": ["infrastructure"], + "weight": 2 }, { "id": "EQUINIXMETAL", "name": "Equinix Metal", "href": "https://www.equinix.com", - "categories": ["infrastructure"] + "categories": ["infrastructure"], + "weight": 2 }, { "id": "CHROMATIC", "name": "Chromatic", "href": "https://www.chromatic.com", - "categories": ["infrastructure"] - }, - { - "id": "VERCEL", - "name": "Vercel", - "href": "https://vercel.com", - "categories": ["infrastructure"] - }, - { - "id": "SENTRY", - "name": "Sentry", - "href": "https://sentry.io", - "categories": ["infrastructure"] - }, - { - "id": "CROWDIN", - "name": "Crowdin", - "href": "https://crowdin.com", - "categories": ["infrastructure"] + "categories": ["service"], + "weight": 1 }, { "id": "ORAMA", "name": "Orama", "href": "https://orama.com", - "categories": ["infrastructure"] - }, - { - "id": "HERODEVS", - "name": "HeroDevs", - "href": "https://herodevs.com", - "categories": ["security", "esp partner"] - }, - { - "id": "NODESOURCE", - "name": "NodeSource", - "href": "https://nodesource.com", - "categories": ["security"] + "categories": ["service"], + "weight": 1 }, { "id": "PLATFORMATIC", "name": "Platformatic", "href": "https://platformatic.dev", - "categories": ["security"] + "categories": ["security"], + "weight": 2 }, { "id": "REDHAT", "name": "Red Hat", "href": "https://www.redhat.com", - "categories": ["security"] + "categories": ["security"], + "weight": 2 }, { - "id": "DATADOG", - "name": "Datadog", - "href": "https://www.datadoghq.com", + "id": "OPENSSF", + "name": "Open SSF", + "href": "https://openssf.org/", + "weight": 2, "categories": ["security"] + }, + { + "id": "VLT", + "name": "Vlt", + "href": "https://www.vlt.sh", + "weight": 2, + "categories": ["release"] + }, + { + "id": "ZAKODIUM", + "name": "zakodium", + "href": "https://www.zakodium.com", + "weight": 2, + "categories": ["release"] } ] From 5fd31f8c5db2b8884da258edf609a43df9e4a0e7 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Tue, 22 Jul 2025 20:45:42 +0000 Subject: [PATCH 08/21] feat: update partner selection logic to use weighted randomization --- apps/site/components/Common/Partners/utils.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/apps/site/components/Common/Partners/utils.ts b/apps/site/components/Common/Partners/utils.ts index c86e116c53f24..a0649ed7d2bdd 100644 --- a/apps/site/components/Common/Partners/utils.ts +++ b/apps/site/components/Common/Partners/utils.ts @@ -27,20 +27,26 @@ function randomPartnerList( const seed = fixedTime.getTime(); const rng = mulberry32(seed); + const weightedPartners = partners.flatMap(partner => { + if (category && !partner.categories.includes(category)) return []; + const weight = partner.weight; + return Array(weight).fill(partner); + }); + // Create a copy of the array to avoid modifying the original - let shuffled = [...partners] - .filter(partner => !category || partner.categories.includes(category)) - .sort(() => rng() - 0.5); + const shuffled = [...weightedPartners].sort(() => rng() - 0.5); + + // Remove duplicates while preserving order + const unique = Array.from(new Set(shuffled)); if (pick !== null) { - shuffled = shuffled.slice(0, pick); + return unique.slice(0, pick); } - return shuffled; + return unique; } // This function returns a random list of partners based on a fixed time seed - function mulberry32(seed: number) { return function () { let t = (seed += 0x6d2b79f5); From 91b65359cd7d275713bda2fb1cda1ddbb5899aec Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Tue, 22 Jul 2025 20:55:36 +0000 Subject: [PATCH 09/21] feat: update button href to include UTM parameters for tracking --- apps/site/components/Common/Partners/PartnerIcon/index.tsx | 6 +++++- apps/site/components/Common/Partners/PartnerLogo/index.tsx | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/apps/site/components/Common/Partners/PartnerIcon/index.tsx b/apps/site/components/Common/Partners/PartnerIcon/index.tsx index 65424a3673680..57d085c881d71 100644 --- a/apps/site/components/Common/Partners/PartnerIcon/index.tsx +++ b/apps/site/components/Common/Partners/PartnerIcon/index.tsx @@ -14,7 +14,11 @@ const PartnersIcon: FC = ({ name, href, logo, loading }) => { return ( - + + From 95702583df57868c8d3c36ec6c43dc179cfd8a40 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Thu, 24 Jul 2025 19:26:10 +0000 Subject: [PATCH 13/21] ui-components: add more partner logos --- apps/site/util/partners/constants.json | 23 +- .../src/Icons/PartnerLogos/ARM/Favicon.tsx | 38 +++ .../src/Icons/PartnerLogos/ARM/Logo.tsx | 38 +++ .../src/Icons/PartnerLogos/ARM/index.tsx | 4 + .../Icons/PartnerLogos/DataDog/Favicon.tsx | 40 +++- .../src/Icons/PartnerLogos/DataDog/Logo.tsx | 159 +++++++++---- .../PartnerLogos/DigitalOcean/Favicon.tsx | 62 +++++ .../Icons/PartnerLogos/DigitalOcean/Logo.tsx | 217 ++++++++++++++++++ .../Icons/PartnerLogos/DigitalOcean/index.ts | 4 + .../Icons/PartnerLogos/NodeSource/Logo.tsx | 12 +- .../src/Icons/PartnerLogos/Vlt/Favicon.tsx | 23 ++ .../src/Icons/PartnerLogos/Vlt/Logo.tsx | 23 ++ .../src/Icons/PartnerLogos/Vlt/index.ts | 4 + .../src/Icons/PartnerLogos/index.ts | 6 + 14 files changed, 598 insertions(+), 55 deletions(-) create mode 100644 packages/ui-components/src/Icons/PartnerLogos/ARM/Favicon.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/ARM/Logo.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/ARM/index.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/DigitalOcean/Favicon.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/DigitalOcean/Logo.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/DigitalOcean/index.ts create mode 100644 packages/ui-components/src/Icons/PartnerLogos/Vlt/Favicon.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/Vlt/Logo.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/Vlt/index.ts diff --git a/apps/site/util/partners/constants.json b/apps/site/util/partners/constants.json index 1612f787d8f02..b934f56661336 100644 --- a/apps/site/util/partners/constants.json +++ b/apps/site/util/partners/constants.json @@ -38,7 +38,7 @@ "id": "HERODEVS", "name": "HeroDevs", "href": "https://herodevs.com", - "weight": 2, + "weight": 3, "categories": ["security", "esp", "release"] }, { @@ -54,5 +54,26 @@ "href": "https://www.datadoghq.com", "weight": 2, "categories": ["security"] + }, + { + "id": "DIGITALOCEAN", + "name": "DigitalOcean", + "href": "https://www.digitalocean.com", + "categories": ["infrastructure"], + "weight": 3 + }, + { + "id": "ARM", + "name": "ARM", + "href": "https://www.arm.com", + "categories": ["infrastructure"], + "weight": 2 + }, + { + "id": "VLT", + "name": "Vlt", + "href": "https://www.vlt.sh", + "weight": 2, + "categories": ["release"] } ] diff --git a/packages/ui-components/src/Icons/PartnerLogos/ARM/Favicon.tsx b/packages/ui-components/src/Icons/PartnerLogos/ARM/Favicon.tsx new file mode 100644 index 0000000000000..771999c825b93 --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/ARM/Favicon.tsx @@ -0,0 +1,38 @@ +import classNames from 'classnames'; +import type { FC, SVGProps } from 'react'; + +const ARM: FC> = props => ( + + + + + +); + +export default ARM; diff --git a/packages/ui-components/src/Icons/PartnerLogos/ARM/Logo.tsx b/packages/ui-components/src/Icons/PartnerLogos/ARM/Logo.tsx new file mode 100644 index 0000000000000..771999c825b93 --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/ARM/Logo.tsx @@ -0,0 +1,38 @@ +import classNames from 'classnames'; +import type { FC, SVGProps } from 'react'; + +const ARM: FC> = props => ( + + + + + +); + +export default ARM; diff --git a/packages/ui-components/src/Icons/PartnerLogos/ARM/index.tsx b/packages/ui-components/src/Icons/PartnerLogos/ARM/index.tsx new file mode 100644 index 0000000000000..b4cd37328b21d --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/ARM/index.tsx @@ -0,0 +1,4 @@ +import Favicon from './Favicon'; +import Logo from './Logo'; + +export { Favicon, Logo }; diff --git a/packages/ui-components/src/Icons/PartnerLogos/DataDog/Favicon.tsx b/packages/ui-components/src/Icons/PartnerLogos/DataDog/Favicon.tsx index 5b80b2295dfff..0b6bfaf8f5930 100644 --- a/packages/ui-components/src/Icons/PartnerLogos/DataDog/Favicon.tsx +++ b/packages/ui-components/src/Icons/PartnerLogos/DataDog/Favicon.tsx @@ -14,8 +14,46 @@ const DataDog: FC> = props => ( {...props} > + + > = props => ( + + + + + + + + + + + diff --git a/packages/ui-components/src/Icons/PartnerLogos/DigitalOcean/Favicon.tsx b/packages/ui-components/src/Icons/PartnerLogos/DigitalOcean/Favicon.tsx new file mode 100644 index 0000000000000..9a9e27c3f0048 --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/DigitalOcean/Favicon.tsx @@ -0,0 +1,62 @@ +import classNames from 'classnames'; +import type { FC, SVGProps } from 'react'; + +const Crowdin: FC> = props => ( + + + + + + + + + + + + + + + + + + + + + +); + +export default Crowdin; diff --git a/packages/ui-components/src/Icons/PartnerLogos/DigitalOcean/Logo.tsx b/packages/ui-components/src/Icons/PartnerLogos/DigitalOcean/Logo.tsx new file mode 100644 index 0000000000000..76c6770fa090f --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/DigitalOcean/Logo.tsx @@ -0,0 +1,217 @@ +import classNames from 'classnames'; +import type { FC, SVGProps } from 'react'; + +const Crowdin: FC> = props => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +); + +export default Crowdin; diff --git a/packages/ui-components/src/Icons/PartnerLogos/DigitalOcean/index.ts b/packages/ui-components/src/Icons/PartnerLogos/DigitalOcean/index.ts new file mode 100644 index 0000000000000..b4cd37328b21d --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/DigitalOcean/index.ts @@ -0,0 +1,4 @@ +import Favicon from './Favicon'; +import Logo from './Logo'; + +export { Favicon, Logo }; diff --git a/packages/ui-components/src/Icons/PartnerLogos/NodeSource/Logo.tsx b/packages/ui-components/src/Icons/PartnerLogos/NodeSource/Logo.tsx index 547d0c4993658..f6907cd79c800 100644 --- a/packages/ui-components/src/Icons/PartnerLogos/NodeSource/Logo.tsx +++ b/packages/ui-components/src/Icons/PartnerLogos/NodeSource/Logo.tsx @@ -1,20 +1,20 @@ +import classNames from 'classnames'; import type { FC, SVGProps } from 'react'; const NodeSource: FC> = props => ( ); diff --git a/packages/ui-components/src/Icons/PartnerLogos/Vlt/Favicon.tsx b/packages/ui-components/src/Icons/PartnerLogos/Vlt/Favicon.tsx new file mode 100644 index 0000000000000..30812054f4eb4 --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/Vlt/Favicon.tsx @@ -0,0 +1,23 @@ +import classNames from 'classnames'; +import type { FC, SVGProps } from 'react'; + +const Vlt: FC> = props => ( + + + +); + +export default Vlt; diff --git a/packages/ui-components/src/Icons/PartnerLogos/Vlt/Logo.tsx b/packages/ui-components/src/Icons/PartnerLogos/Vlt/Logo.tsx new file mode 100644 index 0000000000000..30812054f4eb4 --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/Vlt/Logo.tsx @@ -0,0 +1,23 @@ +import classNames from 'classnames'; +import type { FC, SVGProps } from 'react'; + +const Vlt: FC> = props => ( + + + +); + +export default Vlt; diff --git a/packages/ui-components/src/Icons/PartnerLogos/Vlt/index.ts b/packages/ui-components/src/Icons/PartnerLogos/Vlt/index.ts new file mode 100644 index 0000000000000..b4cd37328b21d --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/Vlt/index.ts @@ -0,0 +1,4 @@ +import Favicon from './Favicon'; +import Logo from './Logo'; + +export { Favicon, Logo }; diff --git a/packages/ui-components/src/Icons/PartnerLogos/index.ts b/packages/ui-components/src/Icons/PartnerLogos/index.ts index c27682993c683..2a21b58a14e05 100644 --- a/packages/ui-components/src/Icons/PartnerLogos/index.ts +++ b/packages/ui-components/src/Icons/PartnerLogos/index.ts @@ -1,19 +1,25 @@ +import * as ARM from './ARM'; import * as CLOUDFLARE from './Cloudflare'; import * as CROWDIN from './Crowdin'; import * as DATADOG from './DataDog'; +import * as DIGITALOCEAN from './DigitalOcean'; import * as HERODEVS from './HeroDevs'; import * as NODESOURCE from './NodeSource'; import * as RACKSPACE from './Rackspace'; import * as SENTRY from './Sentry'; import * as VERCEL from './Vercel'; +import * as VLT from './Vlt'; export { + ARM, CLOUDFLARE, CROWDIN, DATADOG, + DIGITALOCEAN, HERODEVS, NODESOURCE, RACKSPACE, SENTRY, VERCEL, + VLT, }; From 96bc9f9c45d0be07122fc0bbb7c6fd3ac5a8914f Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Thu, 24 Jul 2025 22:43:02 +0000 Subject: [PATCH 14/21] ui-components: add more partners logos --- apps/site/util/partners/constants.json | 35 +++ .../PartnerLogos/EquinixMetal/Favicon.tsx | 35 +++ .../Icons/PartnerLogos/EquinixMetal/Logo.tsx | 84 +++++++ .../Icons/PartnerLogos/EquinixMetal/index.ts | 4 + .../src/Icons/PartnerLogos/IBM/Favicon.tsx | 224 +++++++++++++++++ .../src/Icons/PartnerLogos/IBM/Logo.tsx | 224 +++++++++++++++++ .../src/Icons/PartnerLogos/IBM/index.ts | 4 + .../Icons/PartnerLogos/Microsoft/Favicon.tsx | 30 +++ .../src/Icons/PartnerLogos/Microsoft/Logo.tsx | 36 +++ .../src/Icons/PartnerLogos/Microsoft/index.ts | 4 + .../Icons/PartnerLogos/OpenSSF/Favicon.tsx | 99 ++++++++ .../src/Icons/PartnerLogos/OpenSSF/Logo.tsx | 234 ++++++++++++++++++ .../src/Icons/PartnerLogos/OpenSSF/index.ts | 4 + .../Icons/PartnerLogos/Rackspace/Favicon.tsx | 5 +- .../src/Icons/PartnerLogos/Rackspace/Logo.tsx | 3 +- .../Icons/PartnerLogos/Scaleway/Favicon.tsx | 30 +++ .../src/Icons/PartnerLogos/Scaleway/Logo.tsx | 68 +++++ .../src/Icons/PartnerLogos/Scaleway/index.ts | 4 + .../src/Icons/PartnerLogos/Vlt/Favicon.tsx | 4 +- .../src/Icons/PartnerLogos/Vlt/Logo.tsx | 4 +- .../src/Icons/PartnerLogos/index.ts | 10 + 21 files changed, 1136 insertions(+), 9 deletions(-) create mode 100644 packages/ui-components/src/Icons/PartnerLogos/EquinixMetal/Favicon.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/EquinixMetal/Logo.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/EquinixMetal/index.ts create mode 100644 packages/ui-components/src/Icons/PartnerLogos/IBM/Favicon.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/IBM/Logo.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/IBM/index.ts create mode 100644 packages/ui-components/src/Icons/PartnerLogos/Microsoft/Favicon.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/Microsoft/Logo.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/Microsoft/index.ts create mode 100644 packages/ui-components/src/Icons/PartnerLogos/OpenSSF/Favicon.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/OpenSSF/Logo.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/OpenSSF/index.ts create mode 100644 packages/ui-components/src/Icons/PartnerLogos/Scaleway/Favicon.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/Scaleway/Logo.tsx create mode 100644 packages/ui-components/src/Icons/PartnerLogos/Scaleway/index.ts diff --git a/apps/site/util/partners/constants.json b/apps/site/util/partners/constants.json index b934f56661336..0f64d21e3e672 100644 --- a/apps/site/util/partners/constants.json +++ b/apps/site/util/partners/constants.json @@ -62,6 +62,27 @@ "categories": ["infrastructure"], "weight": 3 }, + { + "id": "MICROSOFT", + "name": "Microsoft", + "href": "https://microsoft.com", + "categories": ["infrastructure"], + "weight": 2 + }, + { + "id": "IBM", + "name": "IBM", + "href": "https://www.ibm.com", + "categories": ["infrastructure", "release"], + "weight": 3 + }, + { + "id": "SCALEWAY", + "name": "Scaleway", + "href": "https://www.scaleway.com", + "categories": ["infrastructure"], + "weight": 2 + }, { "id": "ARM", "name": "ARM", @@ -69,6 +90,20 @@ "categories": ["infrastructure"], "weight": 2 }, + { + "id": "EQUINIXMETAL", + "name": "Equinix Metal", + "href": "https://www.equinix.com", + "categories": ["infrastructure"], + "weight": 2 + }, + { + "id": "OPENSSF", + "name": "OpenSSF", + "href": "https://openssf.org/", + "weight": 2, + "categories": ["security"] + }, { "id": "VLT", "name": "Vlt", diff --git a/packages/ui-components/src/Icons/PartnerLogos/EquinixMetal/Favicon.tsx b/packages/ui-components/src/Icons/PartnerLogos/EquinixMetal/Favicon.tsx new file mode 100644 index 0000000000000..364f53a536ca1 --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/EquinixMetal/Favicon.tsx @@ -0,0 +1,35 @@ +import classNames from 'classnames'; +import type { FC, SVGProps } from 'react'; + +const EquinixMetal: FC> = props => ( + + + + +); + +export default EquinixMetal; diff --git a/packages/ui-components/src/Icons/PartnerLogos/EquinixMetal/Logo.tsx b/packages/ui-components/src/Icons/PartnerLogos/EquinixMetal/Logo.tsx new file mode 100644 index 0000000000000..371889dab83a5 --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/EquinixMetal/Logo.tsx @@ -0,0 +1,84 @@ +import classNames from 'classnames'; +import type { FC, SVGProps } from 'react'; + +const EquinixMetal: FC> = props => ( + + + + + + + + + + + + + + + + + +); + +export default EquinixMetal; diff --git a/packages/ui-components/src/Icons/PartnerLogos/EquinixMetal/index.ts b/packages/ui-components/src/Icons/PartnerLogos/EquinixMetal/index.ts new file mode 100644 index 0000000000000..b4cd37328b21d --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/EquinixMetal/index.ts @@ -0,0 +1,4 @@ +import Favicon from './Favicon'; +import Logo from './Logo'; + +export { Favicon, Logo }; diff --git a/packages/ui-components/src/Icons/PartnerLogos/IBM/Favicon.tsx b/packages/ui-components/src/Icons/PartnerLogos/IBM/Favicon.tsx new file mode 100644 index 0000000000000..3479708ad3c95 --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/IBM/Favicon.tsx @@ -0,0 +1,224 @@ +import classNames from 'classnames'; +import type { FC, SVGProps } from 'react'; + +const IBM: FC> = props => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +); + +export default IBM; diff --git a/packages/ui-components/src/Icons/PartnerLogos/IBM/Logo.tsx b/packages/ui-components/src/Icons/PartnerLogos/IBM/Logo.tsx new file mode 100644 index 0000000000000..3479708ad3c95 --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/IBM/Logo.tsx @@ -0,0 +1,224 @@ +import classNames from 'classnames'; +import type { FC, SVGProps } from 'react'; + +const IBM: FC> = props => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +); + +export default IBM; diff --git a/packages/ui-components/src/Icons/PartnerLogos/IBM/index.ts b/packages/ui-components/src/Icons/PartnerLogos/IBM/index.ts new file mode 100644 index 0000000000000..b4cd37328b21d --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/IBM/index.ts @@ -0,0 +1,4 @@ +import Favicon from './Favicon'; +import Logo from './Logo'; + +export { Favicon, Logo }; diff --git a/packages/ui-components/src/Icons/PartnerLogos/Microsoft/Favicon.tsx b/packages/ui-components/src/Icons/PartnerLogos/Microsoft/Favicon.tsx new file mode 100644 index 0000000000000..88fbb9d363872 --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/Microsoft/Favicon.tsx @@ -0,0 +1,30 @@ +import type { FC, SVGProps } from 'react'; + +const Microsoft: FC> = props => ( + + + + + + + + + + + + + +); + +export default Microsoft; diff --git a/packages/ui-components/src/Icons/PartnerLogos/Microsoft/Logo.tsx b/packages/ui-components/src/Icons/PartnerLogos/Microsoft/Logo.tsx new file mode 100644 index 0000000000000..89c7661aec3e4 --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/Microsoft/Logo.tsx @@ -0,0 +1,36 @@ +import type { FC, SVGProps } from 'react'; + +const Microsoft: FC> = props => ( + + + + + + + + + + + + + + +); + +export default Microsoft; diff --git a/packages/ui-components/src/Icons/PartnerLogos/Microsoft/index.ts b/packages/ui-components/src/Icons/PartnerLogos/Microsoft/index.ts new file mode 100644 index 0000000000000..b4cd37328b21d --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/Microsoft/index.ts @@ -0,0 +1,4 @@ +import Favicon from './Favicon'; +import Logo from './Logo'; + +export { Favicon, Logo }; diff --git a/packages/ui-components/src/Icons/PartnerLogos/OpenSSF/Favicon.tsx b/packages/ui-components/src/Icons/PartnerLogos/OpenSSF/Favicon.tsx new file mode 100644 index 0000000000000..de3a0f39679c6 --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/OpenSSF/Favicon.tsx @@ -0,0 +1,99 @@ +import classNames from 'classnames'; +import type { FC, SVGProps } from 'react'; + +const OpenSSF: FC> = props => ( + + + + + + + + + + + + + + + + + + + + + + + + + +); + +export default OpenSSF; diff --git a/packages/ui-components/src/Icons/PartnerLogos/OpenSSF/Logo.tsx b/packages/ui-components/src/Icons/PartnerLogos/OpenSSF/Logo.tsx new file mode 100644 index 0000000000000..c5e6b86657f33 --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/OpenSSF/Logo.tsx @@ -0,0 +1,234 @@ +import classNames from 'classnames'; +import type { FC, SVGProps } from 'react'; + +const OpenSSF: FC> = props => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +); + +export default OpenSSF; diff --git a/packages/ui-components/src/Icons/PartnerLogos/OpenSSF/index.ts b/packages/ui-components/src/Icons/PartnerLogos/OpenSSF/index.ts new file mode 100644 index 0000000000000..b4cd37328b21d --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/OpenSSF/index.ts @@ -0,0 +1,4 @@ +import Favicon from './Favicon'; +import Logo from './Logo'; + +export { Favicon, Logo }; diff --git a/packages/ui-components/src/Icons/PartnerLogos/Rackspace/Favicon.tsx b/packages/ui-components/src/Icons/PartnerLogos/Rackspace/Favicon.tsx index 516b2e56f5012..1c805ca663c80 100644 --- a/packages/ui-components/src/Icons/PartnerLogos/Rackspace/Favicon.tsx +++ b/packages/ui-components/src/Icons/PartnerLogos/Rackspace/Favicon.tsx @@ -1,4 +1,3 @@ -// https://www.rackspace.com/newsroom/media-kit import classNames from 'classnames'; import type { FC, SVGProps } from 'react'; @@ -6,12 +5,12 @@ const Rackspace: FC> = props => ( ); diff --git a/packages/ui-components/src/Icons/PartnerLogos/Rackspace/Logo.tsx b/packages/ui-components/src/Icons/PartnerLogos/Rackspace/Logo.tsx index 060834eec06fb..2f70a8ee278e7 100644 --- a/packages/ui-components/src/Icons/PartnerLogos/Rackspace/Logo.tsx +++ b/packages/ui-components/src/Icons/PartnerLogos/Rackspace/Logo.tsx @@ -1,4 +1,3 @@ -// https://www.rackspace.com/newsroom/media-kit import classNames from 'classnames'; import type { FC, SVGProps } from 'react'; @@ -7,7 +6,7 @@ const Rackspace: FC> = props => ( viewBox="0 0 400 124" xmlns="http://www.w3.org/2000/svg" {...props} - className={classNames('text-[#eb0000]', props.className)} + className={classNames('text-[#eb0000] dark:text-white', props.className)} > > = props => ( + + + + + +); + +export default Scaleway; diff --git a/packages/ui-components/src/Icons/PartnerLogos/Scaleway/Logo.tsx b/packages/ui-components/src/Icons/PartnerLogos/Scaleway/Logo.tsx new file mode 100644 index 0000000000000..4dcbe7d5756f0 --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/Scaleway/Logo.tsx @@ -0,0 +1,68 @@ +import classNames from 'classnames'; +import type { FC, SVGProps } from 'react'; + +const Scaleway: FC> = props => ( + + + + + + + + + + + + + +); + +export default Scaleway; diff --git a/packages/ui-components/src/Icons/PartnerLogos/Scaleway/index.ts b/packages/ui-components/src/Icons/PartnerLogos/Scaleway/index.ts new file mode 100644 index 0000000000000..b4cd37328b21d --- /dev/null +++ b/packages/ui-components/src/Icons/PartnerLogos/Scaleway/index.ts @@ -0,0 +1,4 @@ +import Favicon from './Favicon'; +import Logo from './Logo'; + +export { Favicon, Logo }; diff --git a/packages/ui-components/src/Icons/PartnerLogos/Vlt/Favicon.tsx b/packages/ui-components/src/Icons/PartnerLogos/Vlt/Favicon.tsx index 30812054f4eb4..ede3e459a7e93 100644 --- a/packages/ui-components/src/Icons/PartnerLogos/Vlt/Favicon.tsx +++ b/packages/ui-components/src/Icons/PartnerLogos/Vlt/Favicon.tsx @@ -12,8 +12,8 @@ const Vlt: FC> = props => ( {...props} > diff --git a/packages/ui-components/src/Icons/PartnerLogos/Vlt/Logo.tsx b/packages/ui-components/src/Icons/PartnerLogos/Vlt/Logo.tsx index 30812054f4eb4..ede3e459a7e93 100644 --- a/packages/ui-components/src/Icons/PartnerLogos/Vlt/Logo.tsx +++ b/packages/ui-components/src/Icons/PartnerLogos/Vlt/Logo.tsx @@ -12,8 +12,8 @@ const Vlt: FC> = props => ( {...props} > diff --git a/packages/ui-components/src/Icons/PartnerLogos/index.ts b/packages/ui-components/src/Icons/PartnerLogos/index.ts index 2a21b58a14e05..fe46cde4ce60d 100644 --- a/packages/ui-components/src/Icons/PartnerLogos/index.ts +++ b/packages/ui-components/src/Icons/PartnerLogos/index.ts @@ -3,9 +3,14 @@ import * as CLOUDFLARE from './Cloudflare'; import * as CROWDIN from './Crowdin'; import * as DATADOG from './DataDog'; import * as DIGITALOCEAN from './DigitalOcean'; +import * as EQUINIXMETAL from './EquinixMetal'; import * as HERODEVS from './HeroDevs'; +import * as IBM from './IBM'; +import * as MICROSOFT from './Microsoft'; import * as NODESOURCE from './NodeSource'; +import * as OPENSSF from './OpenSSF'; import * as RACKSPACE from './Rackspace'; +import * as SCALEWAY from './Scaleway'; import * as SENTRY from './Sentry'; import * as VERCEL from './Vercel'; import * as VLT from './Vlt'; @@ -16,9 +21,14 @@ export { CROWDIN, DATADOG, DIGITALOCEAN, + EQUINIXMETAL, HERODEVS, + IBM, + MICROSOFT, NODESOURCE, + OPENSSF, RACKSPACE, + SCALEWAY, SENTRY, VERCEL, VLT, From edf525993f703892fd0fc6166b516f0409c4c981 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Fri, 25 Jul 2025 00:04:22 +0000 Subject: [PATCH 15/21] clean up --- .../Common/Partners/PartnerIcon/index.module.css | 8 ++++---- .../Common/Partners/PartnerIcon/index.tsx | 5 ++--- .../Common/Partners/PartnerLogo/index.module.css | 2 +- .../Common/Partners/PartnerLogo/index.tsx | 3 +-- .../Common/Partners/PartnersIconList/index.tsx | 2 +- .../Partners/PartnersLogoList/index.module.css | 8 ++++---- .../Common/Partners/PartnersLogoList/index.tsx | 2 +- apps/site/next.mdx.use.mjs | 4 ++-- apps/site/next.partners.constants.tsx | 10 +++++----- apps/site/pages/en/about/partners.mdx | 9 +++++---- apps/site/pages/en/download/current.mdx | 4 ++-- apps/site/pages/en/download/index.mdx | 4 ++-- apps/site/types/partners.ts | 2 -- apps/site/util/partners/index.tsx | 6 ++---- packages/i18n/src/locales/en.json | 2 +- .../src/Icons/PartnerLogos/ARM/Favicon.tsx | 3 +-- .../src/Icons/PartnerLogos/ARM/Logo.tsx | 3 +-- .../src/Icons/PartnerLogos/DataDog/Favicon.tsx | 3 +-- .../src/Icons/PartnerLogos/DataDog/Logo.tsx | 3 +-- .../Icons/PartnerLogos/DigitalOcean/Favicon.tsx | 3 +-- .../src/Icons/PartnerLogos/DigitalOcean/Logo.tsx | 3 +-- .../src/Icons/PartnerLogos/Microsoft/Favicon.tsx | 2 +- .../src/Icons/PartnerLogos/Microsoft/Logo.tsx | 2 +- .../src/Icons/PartnerLogos/Scaleway/Logo.tsx | 16 ++++++++-------- 24 files changed, 49 insertions(+), 60 deletions(-) diff --git a/apps/site/components/Common/Partners/PartnerIcon/index.module.css b/apps/site/components/Common/Partners/PartnerIcon/index.module.css index 5ca11edb40806..6c04f8a429085 100644 --- a/apps/site/components/Common/Partners/PartnerIcon/index.module.css +++ b/apps/site/components/Common/Partners/PartnerIcon/index.module.css @@ -1,10 +1,10 @@ @reference "../../../../styles/index.css"; .partnerIcon { - @apply h-9! - w-auto! - min-w-9! - !p-2; + @apply h-9 + w-auto + min-w-9 + p-2; svg { @apply !h-4 diff --git a/apps/site/components/Common/Partners/PartnerIcon/index.tsx b/apps/site/components/Common/Partners/PartnerIcon/index.tsx index 1ede82557ab7b..9709435623f57 100644 --- a/apps/site/components/Common/Partners/PartnerIcon/index.tsx +++ b/apps/site/components/Common/Partners/PartnerIcon/index.tsx @@ -13,14 +13,13 @@ type ParnetsIconProps = Partners & ComponentProps; const PartnersIcon: FC = ({ name, href, logo, loading }) => { return ( - {name}}> + {name}}> + diff --git a/apps/site/pages/en/download/current.mdx b/apps/site/pages/en/download/current.mdx index 0ee4a3ac9a671..2fbab9656dd11 100644 --- a/apps/site/pages/en/download/current.mdx +++ b/apps/site/pages/en/download/current.mdx @@ -39,8 +39,8 @@ or the unof

Thanks by Our Partners

- We are able to serve Node.js downloads and maintain our infrastructure thanks - to our amazing partners. + We are able to serve Node.js's downloads and maintain our infrastructure + proudly due to the support of these partners, and more.
diff --git a/apps/site/pages/en/download/index.mdx b/apps/site/pages/en/download/index.mdx index 0ee4a3ac9a671..2fbab9656dd11 100644 --- a/apps/site/pages/en/download/index.mdx +++ b/apps/site/pages/en/download/index.mdx @@ -39,8 +39,8 @@ or the unof

Thanks by Our Partners

- We are able to serve Node.js downloads and maintain our infrastructure thanks - to our amazing partners. + We are able to serve Node.js's downloads and maintain our infrastructure + proudly due to the support of these partners, and more.
diff --git a/apps/site/types/partners.ts b/apps/site/types/partners.ts index b808bad8f22c6..67ae2e70b3da9 100644 --- a/apps/site/types/partners.ts +++ b/apps/site/types/partners.ts @@ -1,5 +1,3 @@ -// import type { ReactElement, SVGProps } from 'react'; - import type { ReactElement, SVGProps } from 'react'; export interface Partners { diff --git a/apps/site/util/partners/index.tsx b/apps/site/util/partners/index.tsx index 25cb3521d94ef..9562a9b7e9c6f 100644 --- a/apps/site/util/partners/index.tsx +++ b/apps/site/util/partners/index.tsx @@ -3,8 +3,6 @@ import type { ElementType } from 'react'; import type { Partners } from '#site/types'; -// import partners from './constants.json'; - /** * Creates an icon element for a component */ @@ -17,8 +15,8 @@ const createIcon = ( return ; }; -// Package Manager dropdown items -export const partnersList = ( +// Creates a list of partners with their respective icons +export const createPartnersList = ( partnerLists: Array>, type?: 'Logo' | 'Favicon' ) => diff --git a/packages/i18n/src/locales/en.json b/packages/i18n/src/locales/en.json index 3f2084bb8508b..6eff244decf52 100644 --- a/packages/i18n/src/locales/en.json +++ b/packages/i18n/src/locales/en.json @@ -145,7 +145,7 @@ "governance": "Project Governance", "releases": "Node.js Releases", "security": "Security Reporting", - "partners": "Partners" + "partners": "Partners & Supporters" } }, "getInvolved": { diff --git a/packages/ui-components/src/Icons/PartnerLogos/ARM/Favicon.tsx b/packages/ui-components/src/Icons/PartnerLogos/ARM/Favicon.tsx index 771999c825b93..b2cee516e7c43 100644 --- a/packages/ui-components/src/Icons/PartnerLogos/ARM/Favicon.tsx +++ b/packages/ui-components/src/Icons/PartnerLogos/ARM/Favicon.tsx @@ -14,8 +14,7 @@ const ARM: FC> = props => ( viewBox="0 0 4332.3 1318.7" className={classNames('text-[#0D0B21] dark:text-white', props.className)} xmlSpace="preserve" - // @ts-expect-error style is not a valid prop in SVGProps - style={{ enableBackground: 'new 0 0 4332.3 1318.7' }} + enableBackground="new 0 0 4332.3 1318.7" > > = props => ( viewBox="0 0 4332.3 1318.7" className={classNames('text-[#0D0B21] dark:text-white', props.className)} xmlSpace="preserve" - // @ts-expect-error style is not a valid prop in SVGProps - style={{ enableBackground: 'new 0 0 4332.3 1318.7' }} + enableBackground="new 0 0 4332.3 1318.7" > > = props => ( x="0px" y="0px" viewBox="0 0 800.55 856.85" - // @ts-expect-error style is not a valid prop in SVGProps - style={{ enableBackground: 'new 0 0 800.55 856.85' }} + enableBackground="new 0 0 800.55 856.85" className={classNames('text-[#632CA6] dark:text-white', props.className)} {...props} > diff --git a/packages/ui-components/src/Icons/PartnerLogos/DataDog/Logo.tsx b/packages/ui-components/src/Icons/PartnerLogos/DataDog/Logo.tsx index a105883e36f03..0740b0cb317c9 100644 --- a/packages/ui-components/src/Icons/PartnerLogos/DataDog/Logo.tsx +++ b/packages/ui-components/src/Icons/PartnerLogos/DataDog/Logo.tsx @@ -9,8 +9,7 @@ const DataDog: FC> = props => ( y="0px" viewBox="0 0 800.5 196.2" className={classNames('text-[#632CA6] dark:text-white', props.className)} - // @ts-expect-error style is not a valid prop in SVGProps - style={{ enableBackground: 'new 0 0 800.55 856.85' }} + enableBackground="new 0 0 800.5 856.85" > diff --git a/packages/ui-components/src/Icons/PartnerLogos/DigitalOcean/Favicon.tsx b/packages/ui-components/src/Icons/PartnerLogos/DigitalOcean/Favicon.tsx index 9a9e27c3f0048..e1ef1270a9b64 100644 --- a/packages/ui-components/src/Icons/PartnerLogos/DigitalOcean/Favicon.tsx +++ b/packages/ui-components/src/Icons/PartnerLogos/DigitalOcean/Favicon.tsx @@ -11,8 +11,7 @@ const Crowdin: FC> = props => ( y="0px" viewBox="65.2 173.5 180 180" className={classNames('text-[#0080FF] dark:text-white', props.className)} - // @ts-expect-error style is not a valid prop in SVGProps - style={{ enableBackground: 'new 65.2 173.5 180 180' }} + enableBackground="new 65.2 173.5 180 180" xmlSpace="preserve" > diff --git a/packages/ui-components/src/Icons/PartnerLogos/DigitalOcean/Logo.tsx b/packages/ui-components/src/Icons/PartnerLogos/DigitalOcean/Logo.tsx index 76c6770fa090f..88c40901903aa 100644 --- a/packages/ui-components/src/Icons/PartnerLogos/DigitalOcean/Logo.tsx +++ b/packages/ui-components/src/Icons/PartnerLogos/DigitalOcean/Logo.tsx @@ -11,8 +11,7 @@ const Crowdin: FC> = props => ( y="0px" viewBox="0 0 603 103" className={classNames('text-[#0080FF] dark:text-white', props.className)} - // @ts-expect-error style is not a valid prop in SVGProps - style={{ enableBackground: 'new 0 0 603 103' }} + enableBackground="new 0 0 603 103" xmlSpace="preserve" > diff --git a/packages/ui-components/src/Icons/PartnerLogos/Microsoft/Favicon.tsx b/packages/ui-components/src/Icons/PartnerLogos/Microsoft/Favicon.tsx index 88fbb9d363872..fcf0db2ff3cee 100644 --- a/packages/ui-components/src/Icons/PartnerLogos/Microsoft/Favicon.tsx +++ b/packages/ui-components/src/Icons/PartnerLogos/Microsoft/Favicon.tsx @@ -7,7 +7,7 @@ const Microsoft: FC> = props => ( xmlns="http://www.w3.org/2000/svg" {...props} > - + > = props => ( xmlns="http://www.w3.org/2000/svg" {...props} > - + > = props => ( fill="currentColor" /> @@ -33,8 +33,8 @@ const Scaleway: FC> = props => ( fill="currentColor" /> @@ -47,14 +47,14 @@ const Scaleway: FC> = props => ( fill="currentColor" /> From 625ed9c21703627ebd1344d41077e65c502e65d1 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Sat, 26 Jul 2025 16:10:18 +0000 Subject: [PATCH 16/21] feat: update supporters and partners sections --- .../components/Common/Supporters/index.tsx | 5 ++-- apps/site/components/withSupporters.tsx | 2 +- apps/site/layouts/Post.tsx | 26 ++++++++++++------- apps/site/pages/en/about/partners.mdx | 11 ++++---- apps/site/pages/en/download/current.mdx | 6 +++-- apps/site/pages/en/download/index.mdx | 8 +++--- 6 files changed, 35 insertions(+), 23 deletions(-) diff --git a/apps/site/components/Common/Supporters/index.tsx b/apps/site/components/Common/Supporters/index.tsx index fc2e61bc47efa..9afb941a5d5c2 100644 --- a/apps/site/components/Common/Supporters/index.tsx +++ b/apps/site/components/Common/Supporters/index.tsx @@ -10,13 +10,14 @@ type SupportersProps = { supporters: Promise>; }; +// TODO: Sort supporters by all time contribution amount and link to their Open Collective page const SupportersList: FC = ({ supporters }) => { const supportersList = use(supporters); return (
- {supportersList.map(({ name, image, url }, i) => ( - + {supportersList.map(({ name, image }, i) => ( + ))}
); diff --git a/apps/site/components/withSupporters.tsx b/apps/site/components/withSupporters.tsx index a144f366e20bc..63f1a4792c18b 100644 --- a/apps/site/components/withSupporters.tsx +++ b/apps/site/components/withSupporters.tsx @@ -9,7 +9,7 @@ const WithSupporters: FC = () => { const supporters = fetchOpenCollectiveData() as Promise>; return ( -
+
); diff --git a/apps/site/layouts/Post.tsx b/apps/site/layouts/Post.tsx index 7e588fbdbb25d..0c3eea2f72edd 100644 --- a/apps/site/layouts/Post.tsx +++ b/apps/site/layouts/Post.tsx @@ -39,18 +39,24 @@ const PostLayout: FC = ({ children }) => { {children} + + {type === 'vulnerability' && ( -
-

Thanks by Our Partners

-

- We are able to offer security releases proudly due to the - support of these partners - and more. -

- -
+
+
+
+

+ These security releases are possible by: +

+

+ We are able to offer security releases proudly due to the + support of these partners + and more. +

+ +
+
)} -
diff --git a/apps/site/pages/en/about/partners.mdx b/apps/site/pages/en/about/partners.mdx index 9e2a93c54e0e9..fb17b6568b9d0 100644 --- a/apps/site/pages/en/about/partners.mdx +++ b/apps/site/pages/en/about/partners.mdx @@ -65,12 +65,13 @@ End-Of-Life versions, please visit [End-Of-Life Node.js Releases](/eol) -
- ## Become a Partner -If you are interested in becoming a partner, please reach out to us - - +Become a partner of the Node.js project and help us to continue to develop and maintain +this project. Your support is crucial to ensure that Node.js remains a reliable and secure platform +for developers and organizations around the world. If you are interested in becoming a partner, +please reach out to us through the OpenJS Foundation. +
+
diff --git a/apps/site/pages/en/download/current.mdx b/apps/site/pages/en/download/current.mdx index 2fbab9656dd11..f03bffb9ef6cd 100644 --- a/apps/site/pages/en/download/current.mdx +++ b/apps/site/pages/en/download/current.mdx @@ -35,8 +35,10 @@ or the unof -
-

Thanks by Our Partners

+--- + +
+

Proudly supported by the partners below:

We are able to serve Node.js's downloads and maintain our infrastructure diff --git a/apps/site/pages/en/download/index.mdx b/apps/site/pages/en/download/index.mdx index 2fbab9656dd11..e7fa07af57cb6 100644 --- a/apps/site/pages/en/download/index.mdx +++ b/apps/site/pages/en/download/index.mdx @@ -19,7 +19,7 @@ Or get a prebuilt Node.js® for running a -
+
Read the changelog or blog post for this version. @@ -35,8 +35,10 @@ or the unof
-
-

Thanks by Our Partners

+--- + +
+

Proudly supported by the partners below:

We are able to serve Node.js's downloads and maintain our infrastructure From cdaa6d6af9c2e7b99e72ca18a900a7e38fa16569 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Sat, 26 Jul 2025 16:47:13 +0000 Subject: [PATCH 17/21] feat: enhance partner list functionality with sorting options --- .../Partners/PartnersIconList/index.tsx | 8 +++- .../Partners/PartnersLogoList/index.tsx | 11 ++++- apps/site/components/Common/Partners/utils.ts | 47 ++++++++++++++++--- apps/site/pages/en/about/partners.mdx | 10 ++-- 4 files changed, 62 insertions(+), 14 deletions(-) diff --git a/apps/site/components/Common/Partners/PartnersIconList/index.tsx b/apps/site/components/Common/Partners/PartnersIconList/index.tsx index 76d38b1c6da27..3091f2bb32d9c 100644 --- a/apps/site/components/Common/Partners/PartnersIconList/index.tsx +++ b/apps/site/components/Common/Partners/PartnersIconList/index.tsx @@ -37,7 +37,13 @@ const PartnersIconList: FC = ({ const renderSponsorsAnimation = setTimeout(() => { initialRenderer.current = false; - setSeedList(randomPartnerList(ICON_PARTNERS, maxLength, 5, categories)); + setSeedList( + randomPartnerList(ICON_PARTNERS, { + pick: maxLength, + dateSeed: 5, + category: categories, + }) + ); }, 0); return () => clearTimeout(renderSponsorsAnimation); diff --git a/apps/site/components/Common/Partners/PartnersLogoList/index.tsx b/apps/site/components/Common/Partners/PartnersLogoList/index.tsx index 07f0b13e9c83c..8ea1d0f975b03 100644 --- a/apps/site/components/Common/Partners/PartnersLogoList/index.tsx +++ b/apps/site/components/Common/Partners/PartnersLogoList/index.tsx @@ -12,10 +12,12 @@ import { randomPartnerList } from '../utils'; type PartnersLogoListProps = { maxLength?: number; categories?: PartnerCategory; + sort?: 'name' | 'weight'; }; const PartnersLogoList: FC = ({ maxLength = 3, + sort = 'weight', categories, }) => { const initialRenderer = useRef(true); @@ -42,7 +44,14 @@ const PartnersLogoList: FC = ({ const renderSponsorsAnimation = setTimeout(() => { initialRenderer.current = false; - setSeedList(randomPartnerList(LOGO_PARTNERS, maxLength, 5, categories)); + setSeedList( + randomPartnerList(LOGO_PARTNERS, { + pick: maxLength, + dateSeed: 5, + category: categories, + sort: sort, + }) + ); }, 0); return () => clearTimeout(renderSponsorsAnimation); diff --git a/apps/site/components/Common/Partners/utils.ts b/apps/site/components/Common/Partners/utils.ts index a0649ed7d2bdd..ab070e1595d9c 100644 --- a/apps/site/components/Common/Partners/utils.ts +++ b/apps/site/components/Common/Partners/utils.ts @@ -1,13 +1,47 @@ import type { PartnerCategory, Partners } from '#site/types/partners.js'; -// TODO: Implement no random list -// TODO: Implement no importance of partner function randomPartnerList( partners: Array, - pick = 4, - dateSeed = 5, - category?: PartnerCategory + config: { + /** + * Number of partners to pick from the list. + * If null, all partners will be returned. + */ + pick?: number | null; + /** + * Date seed to use for the randomization. + * This is used to ensure that the same partners are returned for the same date. + */ + dateSeed?: number; + /** + * Category of partners to filter by. + * If not provided, all partners will be returned. + */ + category?: PartnerCategory; + /** + * Whether to randomize the partners or not. + */ + sort?: 'name' | 'weight' | null; + } ) { + const { pick = 4, dateSeed = 5, category, sort = 'weight' } = config; + + const filteredPartners = [...partners].filter(partner => { + return !category || partner.categories.includes(category); + }); + + if (sort === null) { + return pick !== null ? filteredPartners.slice(0, pick) : filteredPartners; + } + + if (sort === 'name') { + const shuffled = [...filteredPartners].sort((a, b) => + a.name.localeCompare(b.name) + ); + + return pick !== null ? shuffled.slice(0, pick) : shuffled; + } + const now = new Date(); const minutes = Math.floor(now.getUTCMinutes() / dateSeed) * dateSeed; @@ -27,8 +61,7 @@ function randomPartnerList( const seed = fixedTime.getTime(); const rng = mulberry32(seed); - const weightedPartners = partners.flatMap(partner => { - if (category && !partner.categories.includes(category)) return []; + const weightedPartners = filteredPartners.flatMap(partner => { const weight = partner.weight; return Array(weight).fill(partner); }); diff --git a/apps/site/pages/en/about/partners.mdx b/apps/site/pages/en/about/partners.mdx index fb17b6568b9d0..c5d907bcff878 100644 --- a/apps/site/pages/en/about/partners.mdx +++ b/apps/site/pages/en/about/partners.mdx @@ -18,7 +18,7 @@ The infrastructure partners provide important support for the Node.js project, providing hardware and machines for our continuous integration and testing processes, without we can't test and release new versions of Node.js. - + ## Security @@ -26,7 +26,7 @@ The security partners help us to provide new security releases in a timely manne properly good practices for vulnerability disclosure and remediation. Their contributions are crucial to ensure that the Node.js ecosystem remains secure and resilient against vulnerabilities. - + ## Releases @@ -34,7 +34,7 @@ The release partners help us to provide new releases, ensuring that new features are delivered to the Node.js ecosystem in a timely manner. Their contributions are essential to the ongoing development and evolution of Node.js. - + ## Services @@ -42,7 +42,7 @@ The service partners help us to provide a range of services that support the Nod Their contributions are vital to ensuring that nodejs maintainers have access to the tools and resources they need to build and maintain this project. - + ## Supporters @@ -63,7 +63,7 @@ End-Of-Life versions, please visit [End-Of-Life Node.js Releases](/eol) > Using EOL releases through NES should be viewed as a temporary solution, the goal should always > be to upgrade to actively supported versions. - + ## Become a Partner From d73736489ceb6fbbcd77862e27a5f492adc42f6d Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Wed, 30 Jul 2025 15:34:05 +0000 Subject: [PATCH 18/21] fix typos and small nits --- .../Common/Partners/PartnerIcon/index.tsx | 38 +++++++++---------- .../Partners/PartnerLogo/index.module.css | 4 +- .../Common/Partners/PartnerLogo/index.tsx | 36 +++++++++--------- .../Partners/PartnersIconList/index.tsx | 3 +- .../Partners/PartnersLogoList/index.tsx | 3 +- 5 files changed, 41 insertions(+), 43 deletions(-) diff --git a/apps/site/components/Common/Partners/PartnerIcon/index.tsx b/apps/site/components/Common/Partners/PartnerIcon/index.tsx index 9709435623f57..aa0784384fb86 100644 --- a/apps/site/components/Common/Partners/PartnerIcon/index.tsx +++ b/apps/site/components/Common/Partners/PartnerIcon/index.tsx @@ -3,30 +3,28 @@ import Tooltip from '@node-core/ui-components/Common/Tooltip'; import type { ComponentProps, FC } from 'react'; import { cloneElement } from 'react'; +import Button from '#site/components/Common/Button'; import type { Partners } from '#site/types'; import style from './index.module.css'; -import Button from '../../Button'; -type ParnetsIconProps = Partners & ComponentProps; +type PartnersIconProps = Partners & ComponentProps; -const PartnersIcon: FC = ({ name, href, logo, loading }) => { - return ( - - {name}}> - - - - ); -}; +const PartnersIcon: FC = ({ name, href, logo, loading }) => ( + + {name}}> + + + +); export default PartnersIcon; diff --git a/apps/site/components/Common/Partners/PartnerLogo/index.module.css b/apps/site/components/Common/Partners/PartnerLogo/index.module.css index 7db66015ed48a..8f7b772426abe 100644 --- a/apps/site/components/Common/Partners/PartnerLogo/index.module.css +++ b/apps/site/components/Common/Partners/PartnerLogo/index.module.css @@ -2,8 +2,8 @@ .partnerIcon { @apply flex - h-[114px] - max-h-[114px] + h-28 + max-h-28 w-auto min-w-12 items-center diff --git a/apps/site/components/Common/Partners/PartnerLogo/index.tsx b/apps/site/components/Common/Partners/PartnerLogo/index.tsx index 4639912991326..1f9d9ee13d18f 100644 --- a/apps/site/components/Common/Partners/PartnerLogo/index.tsx +++ b/apps/site/components/Common/Partners/PartnerLogo/index.tsx @@ -2,28 +2,26 @@ import Skeleton from '@node-core/ui-components/Common/Skeleton'; import type { ComponentProps, FC } from 'react'; import { cloneElement } from 'react'; +import Button from '#site/components/Common/Button'; import type { Partners } from '#site/types'; import style from './index.module.css'; -import Button from '../../Button'; -type ParnetsIconProps = Partners & ComponentProps; +type PartnersLogoProps = Partners & ComponentProps; -const PartnersIcon: FC = ({ href, logo, loading }) => { - return ( - - - - ); -}; +const PartnersLogo: FC = ({ href, logo, loading }) => ( + + + +); -export default PartnersIcon; +export default PartnersLogo; diff --git a/apps/site/components/Common/Partners/PartnersIconList/index.tsx b/apps/site/components/Common/Partners/PartnersIconList/index.tsx index 3091f2bb32d9c..2473526573f81 100644 --- a/apps/site/components/Common/Partners/PartnersIconList/index.tsx +++ b/apps/site/components/Common/Partners/PartnersIconList/index.tsx @@ -1,6 +1,7 @@ 'use client'; -import { useEffect, useRef, useState, type FC } from 'react'; +import { useEffect, useRef, useState } from 'react'; +import type { FC } from 'react'; import { ICON_PARTNERS } from '#site/next.partners.constants'; import type { PartnerCategory, Partners } from '#site/types'; diff --git a/apps/site/components/Common/Partners/PartnersLogoList/index.tsx b/apps/site/components/Common/Partners/PartnersLogoList/index.tsx index 8ea1d0f975b03..379b4d26fec93 100644 --- a/apps/site/components/Common/Partners/PartnersLogoList/index.tsx +++ b/apps/site/components/Common/Partners/PartnersLogoList/index.tsx @@ -1,6 +1,7 @@ 'use client'; -import { useEffect, useRef, useState, type FC } from 'react'; +import { useEffect, useRef, useState } from 'react'; +import type { FC } from 'react'; import { LOGO_PARTNERS } from '#site/next.partners.constants'; import type { PartnerCategory, Partners } from '#site/types'; From 4da9fadc4e5af594cf41984191eefefe02f29d28 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Wed, 30 Jul 2025 15:51:52 +0000 Subject: [PATCH 19/21] refactor: update partners and supporters sections by removing unused categories and cleaning up content --- apps/site/layouts/Post.tsx | 8 +-- apps/site/pages/en/about/partners.mdx | 26 +-------- apps/site/types/partners.ts | 7 +-- apps/site/util/partners/constants.json | 79 +------------------------- 4 files changed, 7 insertions(+), 113 deletions(-) diff --git a/apps/site/layouts/Post.tsx b/apps/site/layouts/Post.tsx index 0c3eea2f72edd..7f6bea5bfcafe 100644 --- a/apps/site/layouts/Post.tsx +++ b/apps/site/layouts/Post.tsx @@ -1,7 +1,7 @@ import Preview from '@node-core/ui-components/Common/Preview'; import type { FC, PropsWithChildren } from 'react'; -import Link from '#site/components/Link'; +// import Link from '#site/components/Link'; import WithAvatarGroup from '#site/components/withAvatarGroup'; import WithBlogCrossLinks from '#site/components/withBlogCrossLinks'; import WithFooter from '#site/components/withFooter'; @@ -12,7 +12,7 @@ import { mapAuthorToCardAuthors } from '#site/util/author'; import { mapBlogCategoryToPreviewType } from '#site/util/blog'; import styles from './layouts.module.css'; -import PartnersLogoList from '../components/Common/Partners/PartnersLogoList'; +// import PartnersLogoList from '../components/Common/Partners/PartnersLogoList'; const PostLayout: FC = ({ children }) => { const { frontmatter } = useClientContext(); @@ -41,7 +41,7 @@ const PostLayout: FC = ({ children }) => { {children} - {type === 'vulnerability' && ( + {/* {type === 'vulnerability' && (

@@ -56,7 +56,7 @@ const PostLayout: FC = ({ children }) => {
- )} + )} */}
diff --git a/apps/site/pages/en/about/partners.mdx b/apps/site/pages/en/about/partners.mdx index c5d907bcff878..ddc498fe5832c 100644 --- a/apps/site/pages/en/about/partners.mdx +++ b/apps/site/pages/en/about/partners.mdx @@ -3,7 +3,7 @@ title: Partners & Supporters layout: about --- -# Partners +# Partners & Supporters The Node.js community is enriched by a vibrant network of partners who contribute in diverse ways. Through these collaborations, we maintain our resilient infrastructure, @@ -20,30 +20,6 @@ without we can't test and release new versions of Node.js. -## Security - -The security partners help us to provide new security releases in a timely manner, ensuring -properly good practices for vulnerability disclosure and remediation. Their contributions are -crucial to ensure that the Node.js ecosystem remains secure and resilient against vulnerabilities. - - - -## Releases - -The release partners help us to provide new releases, ensuring that new features and improvements -are delivered to the Node.js ecosystem in a timely manner. Their contributions are essential -to the ongoing development and evolution of Node.js. - - - -## Services - -The service partners help us to provide a range of services that support the Node.js project. -Their contributions are vital to ensuring that nodejs maintainers have access to the tools and -resources they need to build and maintain this project. - - - ## Supporters Supporters are individuals and organizations that provide financial support through diff --git a/apps/site/types/partners.ts b/apps/site/types/partners.ts index 67ae2e70b3da9..0f9c1a6dd7d08 100644 --- a/apps/site/types/partners.ts +++ b/apps/site/types/partners.ts @@ -16,12 +16,7 @@ export interface Partners { weight: number; } -export type PartnerCategory = - | 'infrastructure' - | 'security' - | 'esp' - | 'release' - | 'service'; +export type PartnerCategory = 'infrastructure' | 'esp'; export interface Supporters { name: string; diff --git a/apps/site/util/partners/constants.json b/apps/site/util/partners/constants.json index 0f64d21e3e672..fcb3a733d7cac 100644 --- a/apps/site/util/partners/constants.json +++ b/apps/site/util/partners/constants.json @@ -1,11 +1,4 @@ [ - { - "id": "RACKSPACE", - "name": "Rackspace", - "href": "https://www.rackspace.com", - "weight": 3, - "categories": ["infrastructure"] - }, { "id": "CLOUDFLARE", "name": "Cloudflare", @@ -20,20 +13,6 @@ "weight": 2, "categories": ["infrastructure"] }, - { - "id": "SENTRY", - "name": "Sentry", - "href": "https://sentry.io", - "weight": 1, - "categories": ["service"] - }, - { - "id": "CROWDIN", - "name": "Crowdin", - "href": "https://crowdin.com", - "weight": 1, - "categories": ["service"] - }, { "id": "HERODEVS", "name": "HeroDevs", @@ -41,20 +20,6 @@ "weight": 3, "categories": ["security", "esp", "release"] }, - { - "id": "NODESOURCE", - "name": "NodeSource", - "href": "https://nodesource.com", - "weight": 2, - "categories": ["security", "release"] - }, - { - "id": "DATADOG", - "name": "Datadog", - "href": "https://www.datadoghq.com", - "weight": 2, - "categories": ["security"] - }, { "id": "DIGITALOCEAN", "name": "DigitalOcean", @@ -64,51 +29,9 @@ }, { "id": "MICROSOFT", - "name": "Microsoft", + "name": "Microsoft Azure", "href": "https://microsoft.com", "categories": ["infrastructure"], "weight": 2 - }, - { - "id": "IBM", - "name": "IBM", - "href": "https://www.ibm.com", - "categories": ["infrastructure", "release"], - "weight": 3 - }, - { - "id": "SCALEWAY", - "name": "Scaleway", - "href": "https://www.scaleway.com", - "categories": ["infrastructure"], - "weight": 2 - }, - { - "id": "ARM", - "name": "ARM", - "href": "https://www.arm.com", - "categories": ["infrastructure"], - "weight": 2 - }, - { - "id": "EQUINIXMETAL", - "name": "Equinix Metal", - "href": "https://www.equinix.com", - "categories": ["infrastructure"], - "weight": 2 - }, - { - "id": "OPENSSF", - "name": "OpenSSF", - "href": "https://openssf.org/", - "weight": 2, - "categories": ["security"] - }, - { - "id": "VLT", - "name": "Vlt", - "href": "https://www.vlt.sh", - "weight": 2, - "categories": ["release"] } ] From 26c9f8c0e5b082358f91531167ac4044638c83b0 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Wed, 30 Jul 2025 16:32:11 +0000 Subject: [PATCH 20/21] feat: add comprehensive partners documentation outlining addition, removal, and display processes --- docs/partners.md | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 docs/partners.md diff --git a/docs/partners.md b/docs/partners.md new file mode 100644 index 0000000000000..824914f2c1f4a --- /dev/null +++ b/docs/partners.md @@ -0,0 +1,66 @@ +# Partners + +This document describes how partners and supporters of the Node.js project are referenced and managed. + +## Adding or Removing Partners + +All partners must be approved by the Node.js Marketing Team and the Node.js Technical Steering Committee (TSC). Therefore, partners cannot be added or removed without their approval. + +To add or remove a partner: + +1. Modify the `apps/site/util/partners/constants.json` file. This file contains an array of partner objects, each with the following fields: + - `id`: A unique identifier for the partner (used for logo import). + - `name`: The display name of the partner. + - `href`: A URL linking to the partner’s website. + - `categories`: An array of categories the partner belongs to. These are used to filter partners on the Partners and Downloads pages. Valid categories include: + - `infrastructure`: Partners providing infrastructure for the Node.js project. + - `esp`: Partners offering support for EOL Node.js versions through the Ecosystem Sustainability Program (ESP). + - `weight`: A number representing the partner's visibility weight. This is used in the randomization algorithm — higher values increase the partner's likelihood of being shown. + +2. Add the partner's logo to the `packages/ui-components/icons/PartnersLogos/` directory. + The filename must match the partner's `id`, in lowercase. + +3. Register the logo in `packages/ui-components/icons/PartnersLogos/index.ts`. + For example, if the partner’s `id` is `MICROSOFT`, the import must be written as: + + ```ts + import * as MICROSOFT from './microsoft'; + ``` + +## Home Page + +On the homepage, all partners are displayed regardless of category. The `weight` field is used by the randomization algorithm to determine how likely a partner is to appear e.g., a partner with a `weight` of 3 will be three times more likely to be shown than one with a `weight` of 1. + +## Partners Page + +The Partners page organizes partners by category. Each category has a description that must be approved by the Node.js Marketing Team and the TSC. +Each partner is displayed with: + +- Their logo +- Their name +- A link to their website with UTM parameters for tracking + +Partners are sorted alphabetically within each category. + +## Downloads Section + +The Downloads section only features partners categorized under `infrastructure`. These partners provide essential infrastructure for testing, releasing, and maintaining Node.js website, etc. +The same randomization algorithm used on the homepage is applied here as well. + +## Supporters + +> [!NOTE] +> Donations made through GitHub Sponsors are not displayed yet; they will be added soon. + +Supporters are individuals and organizations that provide financial support to the Node.js project through OpenCollective and GitHub Sponsors. They are displayed on the Partner page, but not on the homepage or Downloads section. + +## Partner Randomization Algorithm + +The randomization algorithm determines the order in which partners are displayed on both the homepage and the Downloads section. It takes into account: + +- The `weight` of each partner (higher weight = higher probability of being shown). +- A time-based seed: the order is refreshed every 5 minutes, not on every request. + This ensures that the display remains consistent for a short period, rather than changing constantly. E.g., if a user visits the homepage multiple times within 5 minutes, they will see the same order of partners. + +> [!NOTE] +> Partner randomization and rendering is performed on the client side, not during server-side rendering (SSR). From 844cd09991302ef0d547cd49ecca7e75b4572141 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Wed, 30 Jul 2025 17:40:34 +0000 Subject: [PATCH 21/21] style: center-align partner support heading and adjust text balance --- apps/site/pages/en/download/index.mdx | 2 +- apps/site/pages/en/index.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/site/pages/en/download/index.mdx b/apps/site/pages/en/download/index.mdx index e7fa07af57cb6..87044079c9284 100644 --- a/apps/site/pages/en/download/index.mdx +++ b/apps/site/pages/en/download/index.mdx @@ -38,7 +38,7 @@ or the unof ---
-

Proudly supported by the partners below:

+

Proudly supported by the partners below:

We are able to serve Node.js's downloads and maintain our infrastructure diff --git a/apps/site/pages/en/index.mdx b/apps/site/pages/en/index.mdx index 9667d9c81959f..402c4fe8cefc0 100644 --- a/apps/site/pages/en/index.mdx +++ b/apps/site/pages/en/index.mdx @@ -30,7 +30,7 @@ layout: home
- Node.js is proudly supported by the partners above and more. + Node.js is proudly supported by the partners above and more.