From b1783410315a8e4457f8a49aba97f594f5740a60 Mon Sep 17 00:00:00 2001 From: Mr-Rahul-Paul <179798584+Mr-Rahul-Paul@users.noreply.github.com> Date: Tue, 7 Apr 2026 18:47:04 +0530 Subject: [PATCH 01/21] sponsor page design --- frontend/src/app/sponsors/apply/layout.tsx | 18 ++ frontend/src/app/sponsors/apply/page.tsx | 15 ++ frontend/src/app/sponsors/layout.tsx | 12 ++ frontend/src/app/sponsors/page.tsx | 93 ++++++++++ frontend/src/components/Header.tsx | 4 +- frontend/src/components/LogoCarousel.tsx | 3 +- .../components/skeletons/SponsorsSkeleton.tsx | 93 ++++++++++ .../components/sponsors/BecomeSponsorCTA.tsx | 49 +++++ .../sponsors/SponsorApplicationForm.tsx | 173 ++++++++++++++++++ .../sponsors/SponsorDiamondCard.tsx | 57 ++++++ .../src/components/sponsors/SponsorHero.tsx | 40 ++++ .../components/sponsors/SponsorTierCard.tsx | 68 +++++++ .../sponsors/SponsorTierSection.tsx | 47 +++++ .../sponsors/SponsorsFaqSection.tsx | 63 +++++++ .../sponsors/SponsorsOpenSourceShowcase.tsx | 98 ++++++++++ frontend/src/server/queries/sponsorQueries.ts | 14 ++ frontend/src/types/__generated__/graphql.ts | 1 + .../__generated__/sponsorQueries.generated.ts | 10 + frontend/src/types/sponsor.ts | 20 ++ frontend/src/utils/constants.ts | 8 +- frontend/src/utils/metadata.ts | 6 + 21 files changed, 887 insertions(+), 5 deletions(-) create mode 100644 frontend/src/app/sponsors/apply/layout.tsx create mode 100644 frontend/src/app/sponsors/apply/page.tsx create mode 100644 frontend/src/app/sponsors/layout.tsx create mode 100644 frontend/src/app/sponsors/page.tsx create mode 100644 frontend/src/components/skeletons/SponsorsSkeleton.tsx create mode 100644 frontend/src/components/sponsors/BecomeSponsorCTA.tsx create mode 100644 frontend/src/components/sponsors/SponsorApplicationForm.tsx create mode 100644 frontend/src/components/sponsors/SponsorDiamondCard.tsx create mode 100644 frontend/src/components/sponsors/SponsorHero.tsx create mode 100644 frontend/src/components/sponsors/SponsorTierCard.tsx create mode 100644 frontend/src/components/sponsors/SponsorTierSection.tsx create mode 100644 frontend/src/components/sponsors/SponsorsFaqSection.tsx create mode 100644 frontend/src/components/sponsors/SponsorsOpenSourceShowcase.tsx create mode 100644 frontend/src/server/queries/sponsorQueries.ts create mode 100644 frontend/src/types/__generated__/sponsorQueries.generated.ts create mode 100644 frontend/src/types/sponsor.ts diff --git a/frontend/src/app/sponsors/apply/layout.tsx b/frontend/src/app/sponsors/apply/layout.tsx new file mode 100644 index 0000000000..8f5cfa4033 --- /dev/null +++ b/frontend/src/app/sponsors/apply/layout.tsx @@ -0,0 +1,18 @@ +import { Metadata } from 'next' +import React from 'react' +import { generateSeoMetadata } from 'utils/metaconfig' + +export const metadata: Metadata = generateSeoMetadata({ + title: 'Become a Sponsor', + description: 'Apply to become an OWASP Nest sponsor and support open source security.', + canonicalPath: '/sponsors/apply', + keywords: ['OWASP sponsor', 'sponsorship', 'open source security', 'support OWASP'], +}) + +export default function SponsorApplyLayout({ + children, +}: Readonly<{ + children: React.ReactNode +}>) { + return <>{children}> +} diff --git a/frontend/src/app/sponsors/apply/page.tsx b/frontend/src/app/sponsors/apply/page.tsx new file mode 100644 index 0000000000..4efc06f5af --- /dev/null +++ b/frontend/src/app/sponsors/apply/page.tsx @@ -0,0 +1,15 @@ +'use client' + +import SponsorApplicationForm from 'components/sponsors/SponsorApplicationForm' + +const SponsorApplyPage = () => { + return ( +
+ No sponsors yet. Be the first to support OWASP Nest! +
+If you're interested in sponsoring the OWASP Nest project ❤️{' '} { + return ( +
+ Your organization can appear here. Applications are reviewed by the OWASP Nest team. +
+ + Apply to sponsor + + → + + ++ Support Nest and OWASP with a single gift through the Foundation — no sponsorship + application required. +
+ + Donate once + + → + + ++ Thank you for your interest in sponsoring OWASP Nest. Our team will review your + application and get in touch. +
++ Fill out the form below and our team will review your application. We'll follow up + within a few business days. +
+ ++ {sponsor.description} +
+ )} ++ “{mottoAside}” +
++ Community Support +
++ These organizations invest in open, secure software for everyone. +
++ Their support keeps OWASP Nest free, open source, and community-driven. +
++ {sponsor.name} +
+ + ) +} diff --git a/frontend/src/components/sponsors/SponsorTierSection.tsx b/frontend/src/components/sponsors/SponsorTierSection.tsx new file mode 100644 index 0000000000..37a84cec62 --- /dev/null +++ b/frontend/src/components/sponsors/SponsorTierSection.tsx @@ -0,0 +1,47 @@ +import type { SponsorData, SponsorTier } from 'types/sponsor' + +import SponsorTierCard from './SponsorTierCard' + +interface SponsorTierSectionProps { + tier: SponsorTier + sponsors: SponsorData[] +} + +const TIER_GRID: Record+ {tier} +
++ {description} +
+ + {cta} + + › + + + > + ) + + const cardClass = + 'flex h-full flex-col rounded-2xl bg-gray-50 p-6 transition-colors hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700 sm:p-7' + + if (external) { + return ( + + {inner} + + ) + } + + return ( + + {inner} + + ) + })} +{error}
} + {hasError && ( +{error}
+ )}- Thank you for your interest in sponsoring OWASP Nest. Our team will review your - application and get in touch. -
++ Thanks for your interest in sponsoring OWASP Nest. The team will review your application + and follow up via the email you provided. +
++ Want to introduce yourself sooner? Reach out in{' '} + + #project-nest + {' '} + on Slack. +
++ + ← Back to sponsors + +
+
- Fill out the form below and our team will review your application. We'll follow up
- within a few business days.
+
+ Required fields are marked. The Nest team reviews applications via Django Admin and will
+ follow up by email.
+ Application details
+
+
+ {serverError} +
+ )} + + + ) } diff --git a/frontend/src/components/sponsors/SponsorApplyHero.tsx b/frontend/src/components/sponsors/SponsorApplyHero.tsx new file mode 100644 index 0000000000..1bb2b33ad9 --- /dev/null +++ b/frontend/src/components/sponsors/SponsorApplyHero.tsx @@ -0,0 +1,22 @@ +import Link from 'next/link' + +export default function SponsorApplyHero() { + return ( ++ Continue to a pre-filled GitHub issue draft — the Nest team tracks inquiries there. +
+- {sponsor.description} -
- )} -+
“{mottoAside}”
Community Support
diff --git a/frontend/src/components/sponsors/SponsorTierCard.tsx b/frontend/src/components/sponsors/SponsorTierCard.tsx index 8bcec8cfba..cbd7782781 100644 --- a/frontend/src/components/sponsors/SponsorTierCard.tsx +++ b/frontend/src/components/sponsors/SponsorTierCard.tsx @@ -10,9 +10,8 @@ interface SponsorTierCardProps { tier: SponsorTier } -/** Blender credits–style tile: logo-forward, minimal frame, name as caption. */ const tileBase = - 'group flex flex-col items-center rounded-xl border border-gray-200/70 bg-gray-50/90 text-center outline-none transition hover:border-amber-300/55 hover:bg-white focus-visible:ring-2 focus-visible:ring-amber-400/50 focus-visible:ring-offset-2 focus-visible:ring-offset-gray-50 dark:border-gray-600/50 dark:bg-[#2b2e32] dark:hover:border-amber-500/45 dark:hover:bg-[#32363c] dark:focus-visible:ring-amber-400/60 dark:focus-visible:ring-offset-[#212529]' + 'group flex flex-col items-center rounded-lg bg-gray-200 text-center outline-none transition-all duration-300 hover:bg-blue-100 focus-visible:ring-2 focus-visible:ring-gray-900/25 focus-visible:ring-offset-2 focus-visible:ring-offset-gray-100 dark:bg-gray-700 dark:hover:bg-gray-600 dark:focus-visible:ring-gray-300/35 dark:focus-visible:ring-offset-[#212529]' export default function SponsorTierCard({ sponsor, size, tier }: SponsorTierCardProps) { if (tier === 'Diamond') { diff --git a/frontend/src/server/queries/sponsorQueries.ts b/frontend/src/server/queries/sponsorQueries.ts index 26dcb77f1c..3a3d0cb2aa 100644 --- a/frontend/src/server/queries/sponsorQueries.ts +++ b/frontend/src/server/queries/sponsorQueries.ts @@ -4,7 +4,6 @@ export const GET_SPONSORS_PAGE_DATA = gql` query GetSponsorsPageData { sponsors { id - description imageUrl name sponsorType diff --git a/frontend/src/types/__generated__/graphql.ts b/frontend/src/types/__generated__/graphql.ts index dcc0224a6e..0e0cb4ff2a 100644 --- a/frontend/src/types/__generated__/graphql.ts +++ b/frontend/src/types/__generated__/graphql.ts @@ -1054,7 +1054,6 @@ export type SnapshotNode = Node & { export type SponsorNode = Node & { __typename?: 'SponsorNode'; - description: Scalars['String']['output']; /** The Globally Unique ID of this object */ id: Scalars['ID']['output']; imageUrl: Scalars['String']['output']; diff --git a/frontend/src/types/__generated__/sponsorQueries.generated.ts b/frontend/src/types/__generated__/sponsorQueries.generated.ts index 4db373b308..c5cfe7ea2a 100644 --- a/frontend/src/types/__generated__/sponsorQueries.generated.ts +++ b/frontend/src/types/__generated__/sponsorQueries.generated.ts @@ -4,7 +4,7 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/ export type GetSponsorsPageDataQueryVariables = Types.Exact<{ [key: string]: never; }>; -export type GetSponsorsPageDataQuery = { sponsors: Array<{ __typename: 'SponsorNode', id: string, description: string, imageUrl: string, name: string, sponsorType: string, url: string }> }; +export type GetSponsorsPageDataQuery = { sponsors: Array<{ __typename: 'SponsorNode', id: string, imageUrl: string, name: string, sponsorType: string, url: string }> }; -export const GetSponsorsPageDataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetSponsorsPageData"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"sponsors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"imageUrl"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"sponsorType"}},{"kind":"Field","name":{"kind":"Name","value":"url"}}]}}]}}]} as unknown as DocumentNode