diff --git a/frontend/src/app/community/layout.tsx b/frontend/src/app/community/layout.tsx new file mode 100644 index 0000000000..7729190f14 --- /dev/null +++ b/frontend/src/app/community/layout.tsx @@ -0,0 +1,8 @@ +import React from 'react' +import { getStaticMetadata } from 'utils/metaconfig' + +export const metadata = getStaticMetadata('community', '/community') + +export default function CommunityLayout({ children }: { children: React.ReactNode }) { + return children +} diff --git a/frontend/src/app/community/page.tsx b/frontend/src/app/community/page.tsx new file mode 100644 index 0000000000..d864cd6b2a --- /dev/null +++ b/frontend/src/app/community/page.tsx @@ -0,0 +1,251 @@ +'use client' + +import { useQuery } from '@apollo/client/react' +import millify from 'millify' +import Link from 'next/link' +import { FaMapMarkerAlt } from 'react-icons/fa' +import { + FaBuilding, + FaChevronRight, + FaFolder, + FaHandshakeAngle, + FaPeopleGroup, + FaUsers, + FaTag, +} from 'react-icons/fa6' +import { HiUserGroup } from 'react-icons/hi' +import { IconWrapper } from 'wrappers/IconWrapper' +import { GetCommunityPageDataDocument } from 'types/__generated__/communityQueries.generated' +import AnchorTitle from 'components/AnchorTitle' +import ContributorsList from 'components/ContributorsList' +import LoadingSpinner from 'components/LoadingSpinner' +import Release from 'components/Release' +import SecondaryCard from 'components/SecondaryCard' + +const NAV_SECTIONS = [ + { + title: 'Chapters', + description: 'Find local OWASP chapters and connect with your community.', + href: '/chapters', + icon: FaMapMarkerAlt, + color: 'text-gray-900 dark:text-gray-100', + }, + { + title: 'Projects', + description: 'Explore open-source security projects and contribute.', + href: '/projects', + icon: FaFolder, + color: 'text-gray-900 dark:text-gray-100', + }, + { + title: 'Committees', + description: 'OWASP committees driving security governance.', + href: '/committees', + icon: FaPeopleGroup, + color: 'text-gray-900 dark:text-gray-100', + }, + { + title: 'Organizations', + description: 'Browse OWASP organizations and their work.', + href: '/organizations', + icon: FaBuilding, + color: 'text-gray-900 dark:text-gray-100', + }, + { + title: 'Members', + description: 'Meet the people behind OWASP.', + href: '/members', + icon: FaUsers, + color: 'text-gray-900 dark:text-gray-100', + }, + { + title: 'Contribute', + description: 'Find issues and start contributing today.', + href: '/contribute', + icon: FaHandshakeAngle, + color: 'text-gray-900 dark:text-gray-100', + }, +] + +const CommunityPage = () => { + const { data, loading, error } = useQuery(GetCommunityPageDataDocument, { + variables: { + distinct: true, + }, + }) + + if (loading) return + if (error) + return
Error loading community data.
+ + const statsOverview = data?.statsOverview + + const stats = [ + { + icon: FaUsers, + value: millify(statsOverview?.contributorsStats || 0), + label: 'Contributors', + color: 'text-gray-900 dark:text-gray-100', + bg: 'bg-gray-100 dark:bg-gray-800', + }, + { + icon: FaMapMarkerAlt, + value: millify(statsOverview?.activeChaptersStats || 0), + label: 'Active Chapters', + color: 'text-gray-900 dark:text-gray-100', + bg: 'bg-gray-100 dark:bg-gray-800', + }, + { + icon: FaFolder, + value: millify(statsOverview?.activeProjectsStats || 0), + label: 'Active Projects', + color: 'text-gray-900 dark:text-gray-100', + bg: 'bg-gray-100 dark:bg-gray-800', + }, + ] + + return ( +
+
+ {/* Hero */} +
+
+

+ Community Hub +

+

+ Your gateway into the OWASP community — explore chapters, projects, and people. +

+
+
+ + {/* Explore the Community (Resources) */} +
+ + +
+ } + className="overflow-hidden" + > +
+ {NAV_SECTIONS.map((section) => ( + +
+ +
+
+

+ {section.title} + +

+

+ {section.description} +

+
+ + ))} +
+ +
+ + {/* Stats Grid */} +
+ {stats.map((stat) => ( +
+
+
+ +
+
+

+ {stat.label} +

+

{stat.value}

+
+
+
+ ))} +
+ +
+ {/* Main Content: Recent Releases (Renamed from Activity Feed) */} +
+ } + className="!mb-0 h-full" + > +
+

+ Latest updates from across the OWASP ecosystem. +

+
+
+ {data?.recentReleases?.map((release, index) => ( + + ))} +
+
+ + View all recent releases → + +
+
+
+ + {/* Sidebar: Top Contributors (Spotlight Removed) */} +
+ `/members/${login}`} + className="!mb-0 h-full" + gridClassName="grid-cols-1 gap-4" + /> +
+
+ + {/* Quick Links */} +
+

Want to get more involved?

+
+ + Github + + · + + Members + + · + + Organizations + +
+
+
+ + ) +} + +export default CommunityPage diff --git a/frontend/src/components/ContributorsList.tsx b/frontend/src/components/ContributorsList.tsx index ece26973b6..87c3b4537d 100644 --- a/frontend/src/components/ContributorsList.tsx +++ b/frontend/src/components/ContributorsList.tsx @@ -3,6 +3,7 @@ import Image from 'next/image' import Link from 'next/link' import { useState } from 'react' import type { IconType } from 'react-icons' +import { twMerge } from 'tailwind-merge' import type { Contributor } from 'types/contributor' import AnchorTitle from 'components/AnchorTitle' import SecondaryCard from 'components/SecondaryCard' @@ -14,6 +15,8 @@ interface ContributorsListProps { maxInitialDisplay?: number icon?: IconType getUrl: (login: string) => string + className?: string + gridClassName?: string } const ContributorsList = ({ @@ -22,6 +25,8 @@ const ContributorsList = ({ maxInitialDisplay = 12, icon, getUrl, + className, + gridClassName, }: ContributorsListProps) => { const [showAllContributors, setShowAllContributors] = useState(false) @@ -43,8 +48,15 @@ const ContributorsList = ({ } + className={className} > -
+
{displayContributors.map((item) => (
; + recentReleasesLimit?: Types.InputMaybe; + topContributorsLimit?: Types.InputMaybe; +}>; + + +export type GetCommunityPageDataQuery = { topContributors: Array<{ __typename: 'RepositoryContributorNode', id: string, avatarUrl: string, login: string, name: string }>, recentReleases: Array<{ __typename: 'ReleaseNode', id: string, name: string, organizationName: string | null, publishedAt: any | null, repositoryName: string | null, tagName: string, url: string, author: { __typename: 'UserNode', id: string, avatarUrl: string, login: string, name: string } | null }>, statsOverview: { __typename: 'StatsNode', activeChaptersStats: number, activeProjectsStats: number, contributorsStats: number, countriesStats: number, slackWorkspaceStats: number } }; + + +export const GetCommunityPageDataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetCommunityPageData"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"distinct"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Boolean"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"recentReleasesLimit"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}},"defaultValue":{"kind":"IntValue","value":"6"}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"topContributorsLimit"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}},"defaultValue":{"kind":"IntValue","value":"10"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"topContributors"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"hasFullName"},"value":{"kind":"BooleanValue","value":true}},{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"Variable","name":{"kind":"Name","value":"topContributorsLimit"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"avatarUrl"}},{"kind":"Field","name":{"kind":"Name","value":"login"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"recentReleases"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"Variable","name":{"kind":"Name","value":"recentReleasesLimit"}}},{"kind":"Argument","name":{"kind":"Name","value":"distinct"},"value":{"kind":"Variable","name":{"kind":"Name","value":"distinct"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"author"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"avatarUrl"}},{"kind":"Field","name":{"kind":"Name","value":"login"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"organizationName"}},{"kind":"Field","name":{"kind":"Name","value":"publishedAt"}},{"kind":"Field","name":{"kind":"Name","value":"repositoryName"}},{"kind":"Field","name":{"kind":"Name","value":"tagName"}},{"kind":"Field","name":{"kind":"Name","value":"url"}}]}},{"kind":"Field","name":{"kind":"Name","value":"statsOverview"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeChaptersStats"}},{"kind":"Field","name":{"kind":"Name","value":"activeProjectsStats"}},{"kind":"Field","name":{"kind":"Name","value":"contributorsStats"}},{"kind":"Field","name":{"kind":"Name","value":"countriesStats"}},{"kind":"Field","name":{"kind":"Name","value":"slackWorkspaceStats"}}]}}]}}]} as unknown as DocumentNode; \ No newline at end of file diff --git a/frontend/src/types/__generated__/homeQueries.generated.ts b/frontend/src/types/__generated__/homeQueries.generated.ts index 9189eebfb4..76b718812b 100644 --- a/frontend/src/types/__generated__/homeQueries.generated.ts +++ b/frontend/src/types/__generated__/homeQueries.generated.ts @@ -3,10 +3,12 @@ import * as Types from './graphql'; import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type GetMainPageDataQueryVariables = Types.Exact<{ distinct?: Types.InputMaybe; + recentReleasesLimit?: Types.InputMaybe; + topContributorsLimit?: Types.InputMaybe; }>; export type GetMainPageDataQuery = { recentProjects: Array<{ __typename: 'ProjectNode', id: string, createdAt: any | null, key: string, leaders: Array, name: string, openIssuesCount: number, repositoriesCount: number, type: string }>, recentPosts: Array<{ __typename: 'PostNode', id: string, authorName: string, authorImageUrl: string, publishedAt: any, title: string, url: string }>, recentChapters: Array<{ __typename: 'ChapterNode', id: string, createdAt: number, key: string, leaders: Array, name: string, suggestedLocation: string | null }>, topContributors: Array<{ __typename: 'RepositoryContributorNode', id: string, avatarUrl: string, login: string, name: string }>, recentIssues: Array<{ __typename: 'IssueNode', id: string, createdAt: any, organizationName: string | null, repositoryName: string | null, title: string, url: string, author: { __typename: 'UserNode', id: string, avatarUrl: string, login: string, name: string } | null }>, recentPullRequests: Array<{ __typename: 'PullRequestNode', id: string, createdAt: any, organizationName: string | null, repositoryName: string | null, title: string, url: string, author: { __typename: 'UserNode', id: string, avatarUrl: string, login: string, name: string } | null }>, recentReleases: Array<{ __typename: 'ReleaseNode', id: string, name: string, organizationName: string | null, publishedAt: any | null, repositoryName: string | null, tagName: string, url: string, author: { __typename: 'UserNode', id: string, avatarUrl: string, login: string, name: string } | null }>, sponsors: Array<{ __typename: 'SponsorNode', id: string, imageUrl: string, name: string, sponsorType: string, url: string }>, statsOverview: { __typename: 'StatsNode', activeChaptersStats: number, activeProjectsStats: number, contributorsStats: number, countriesStats: number, slackWorkspaceStats: number }, upcomingEvents: Array<{ __typename: 'EventNode', id: string, category: string, endDate: any | null, key: string, name: string, startDate: any, summary: string, suggestedLocation: string, url: string }>, recentMilestones: Array<{ __typename: 'MilestoneNode', id: string, title: string, openIssuesCount: number, closedIssuesCount: number, repositoryName: string | null, organizationName: string | null, createdAt: any, url: string, author: { __typename: 'UserNode', id: string, avatarUrl: string, login: string, name: string } | null }> }; -export const GetMainPageDataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetMainPageData"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"distinct"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Boolean"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"recentProjects"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"3"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"leaders"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"openIssuesCount"}},{"kind":"Field","name":{"kind":"Name","value":"repositoriesCount"}},{"kind":"Field","name":{"kind":"Name","value":"type"}}]}},{"kind":"Field","name":{"kind":"Name","value":"recentPosts"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"6"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"authorName"}},{"kind":"Field","name":{"kind":"Name","value":"authorImageUrl"}},{"kind":"Field","name":{"kind":"Name","value":"publishedAt"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"url"}}]}},{"kind":"Field","name":{"kind":"Name","value":"recentChapters"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"3"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"leaders"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"suggestedLocation"}}]}},{"kind":"Field","name":{"kind":"Name","value":"topContributors"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"hasFullName"},"value":{"kind":"BooleanValue","value":true}},{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"40"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"avatarUrl"}},{"kind":"Field","name":{"kind":"Name","value":"login"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"recentIssues"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"5"}},{"kind":"Argument","name":{"kind":"Name","value":"distinct"},"value":{"kind":"Variable","name":{"kind":"Name","value":"distinct"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"author"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"avatarUrl"}},{"kind":"Field","name":{"kind":"Name","value":"login"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"organizationName"}},{"kind":"Field","name":{"kind":"Name","value":"repositoryName"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"url"}}]}},{"kind":"Field","name":{"kind":"Name","value":"recentPullRequests"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"5"}},{"kind":"Argument","name":{"kind":"Name","value":"distinct"},"value":{"kind":"Variable","name":{"kind":"Name","value":"distinct"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"author"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"avatarUrl"}},{"kind":"Field","name":{"kind":"Name","value":"login"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"organizationName"}},{"kind":"Field","name":{"kind":"Name","value":"repositoryName"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"url"}}]}},{"kind":"Field","name":{"kind":"Name","value":"recentReleases"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"5"}},{"kind":"Argument","name":{"kind":"Name","value":"distinct"},"value":{"kind":"Variable","name":{"kind":"Name","value":"distinct"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"author"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"avatarUrl"}},{"kind":"Field","name":{"kind":"Name","value":"login"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"organizationName"}},{"kind":"Field","name":{"kind":"Name","value":"publishedAt"}},{"kind":"Field","name":{"kind":"Name","value":"repositoryName"}},{"kind":"Field","name":{"kind":"Name","value":"tagName"}},{"kind":"Field","name":{"kind":"Name","value":"url"}}]}},{"kind":"Field","name":{"kind":"Name","value":"sponsors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"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"}}]}},{"kind":"Field","name":{"kind":"Name","value":"statsOverview"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeChaptersStats"}},{"kind":"Field","name":{"kind":"Name","value":"activeProjectsStats"}},{"kind":"Field","name":{"kind":"Name","value":"contributorsStats"}},{"kind":"Field","name":{"kind":"Name","value":"countriesStats"}},{"kind":"Field","name":{"kind":"Name","value":"slackWorkspaceStats"}}]}},{"kind":"Field","name":{"kind":"Name","value":"upcomingEvents"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"9"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"category"}},{"kind":"Field","name":{"kind":"Name","value":"endDate"}},{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"startDate"}},{"kind":"Field","name":{"kind":"Name","value":"summary"}},{"kind":"Field","name":{"kind":"Name","value":"suggestedLocation"}},{"kind":"Field","name":{"kind":"Name","value":"url"}}]}},{"kind":"Field","name":{"kind":"Name","value":"recentMilestones"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"5"}},{"kind":"Argument","name":{"kind":"Name","value":"distinct"},"value":{"kind":"Variable","name":{"kind":"Name","value":"distinct"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"author"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"avatarUrl"}},{"kind":"Field","name":{"kind":"Name","value":"login"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"openIssuesCount"}},{"kind":"Field","name":{"kind":"Name","value":"closedIssuesCount"}},{"kind":"Field","name":{"kind":"Name","value":"repositoryName"}},{"kind":"Field","name":{"kind":"Name","value":"organizationName"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"url"}}]}}]}}]} as unknown as DocumentNode; \ No newline at end of file +export const GetMainPageDataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetMainPageData"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"distinct"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Boolean"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"recentReleasesLimit"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}},"defaultValue":{"kind":"IntValue","value":"5"}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"topContributorsLimit"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}},"defaultValue":{"kind":"IntValue","value":"40"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"recentProjects"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"3"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"leaders"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"openIssuesCount"}},{"kind":"Field","name":{"kind":"Name","value":"repositoriesCount"}},{"kind":"Field","name":{"kind":"Name","value":"type"}}]}},{"kind":"Field","name":{"kind":"Name","value":"recentPosts"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"6"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"authorName"}},{"kind":"Field","name":{"kind":"Name","value":"authorImageUrl"}},{"kind":"Field","name":{"kind":"Name","value":"publishedAt"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"url"}}]}},{"kind":"Field","name":{"kind":"Name","value":"recentChapters"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"3"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"leaders"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"suggestedLocation"}}]}},{"kind":"Field","name":{"kind":"Name","value":"topContributors"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"hasFullName"},"value":{"kind":"BooleanValue","value":true}},{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"Variable","name":{"kind":"Name","value":"topContributorsLimit"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"avatarUrl"}},{"kind":"Field","name":{"kind":"Name","value":"login"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"recentIssues"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"5"}},{"kind":"Argument","name":{"kind":"Name","value":"distinct"},"value":{"kind":"Variable","name":{"kind":"Name","value":"distinct"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"author"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"avatarUrl"}},{"kind":"Field","name":{"kind":"Name","value":"login"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"organizationName"}},{"kind":"Field","name":{"kind":"Name","value":"repositoryName"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"url"}}]}},{"kind":"Field","name":{"kind":"Name","value":"recentPullRequests"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"5"}},{"kind":"Argument","name":{"kind":"Name","value":"distinct"},"value":{"kind":"Variable","name":{"kind":"Name","value":"distinct"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"author"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"avatarUrl"}},{"kind":"Field","name":{"kind":"Name","value":"login"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"organizationName"}},{"kind":"Field","name":{"kind":"Name","value":"repositoryName"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"url"}}]}},{"kind":"Field","name":{"kind":"Name","value":"recentReleases"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"Variable","name":{"kind":"Name","value":"recentReleasesLimit"}}},{"kind":"Argument","name":{"kind":"Name","value":"distinct"},"value":{"kind":"Variable","name":{"kind":"Name","value":"distinct"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"author"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"avatarUrl"}},{"kind":"Field","name":{"kind":"Name","value":"login"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"organizationName"}},{"kind":"Field","name":{"kind":"Name","value":"publishedAt"}},{"kind":"Field","name":{"kind":"Name","value":"repositoryName"}},{"kind":"Field","name":{"kind":"Name","value":"tagName"}},{"kind":"Field","name":{"kind":"Name","value":"url"}}]}},{"kind":"Field","name":{"kind":"Name","value":"sponsors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"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"}}]}},{"kind":"Field","name":{"kind":"Name","value":"statsOverview"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeChaptersStats"}},{"kind":"Field","name":{"kind":"Name","value":"activeProjectsStats"}},{"kind":"Field","name":{"kind":"Name","value":"contributorsStats"}},{"kind":"Field","name":{"kind":"Name","value":"countriesStats"}},{"kind":"Field","name":{"kind":"Name","value":"slackWorkspaceStats"}}]}},{"kind":"Field","name":{"kind":"Name","value":"upcomingEvents"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"9"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"category"}},{"kind":"Field","name":{"kind":"Name","value":"endDate"}},{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"startDate"}},{"kind":"Field","name":{"kind":"Name","value":"summary"}},{"kind":"Field","name":{"kind":"Name","value":"suggestedLocation"}},{"kind":"Field","name":{"kind":"Name","value":"url"}}]}},{"kind":"Field","name":{"kind":"Name","value":"recentMilestones"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"5"}},{"kind":"Argument","name":{"kind":"Name","value":"distinct"},"value":{"kind":"Variable","name":{"kind":"Name","value":"distinct"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"author"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"avatarUrl"}},{"kind":"Field","name":{"kind":"Name","value":"login"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"openIssuesCount"}},{"kind":"Field","name":{"kind":"Name","value":"closedIssuesCount"}},{"kind":"Field","name":{"kind":"Name","value":"repositoryName"}},{"kind":"Field","name":{"kind":"Name","value":"organizationName"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"url"}}]}}]}}]} as unknown as DocumentNode; \ No newline at end of file diff --git a/frontend/src/utils/metadata.ts b/frontend/src/utils/metadata.ts index d174adf440..cb47598c80 100644 --- a/frontend/src/utils/metadata.ts +++ b/frontend/src/utils/metadata.ts @@ -48,6 +48,19 @@ export const METADATA_CONFIG = { pageTitle: 'About', type: 'website', }, + community: { + description: + 'The OWASP Community Hub — discover chapters, projects, contributors, and the pulse of the global security community.', + keywords: [ + 'OWASP community', + 'community hub', + 'contributors', + 'chapters', + 'security community', + ], + pageTitle: 'Community', + type: 'website', + }, organizations: { description: 'Explore OWASP organizations and their contributions to web security.', keywords: ['OWASP organizations', 'security organizations', 'web security'],