Skip to content

Community page design proposal#3918

Open
Mr-Rahul-Paul wants to merge 4 commits intoOWASP:mainfrom
Mr-Rahul-Paul:community
Open

Community page design proposal#3918
Mr-Rahul-Paul wants to merge 4 commits intoOWASP:mainfrom
Mr-Rahul-Paul:community

Conversation

@Mr-Rahul-Paul
Copy link
Contributor

@Mr-Rahul-Paul Mr-Rahul-Paul commented Feb 11, 2026

Proposed change

Resolves #3862

Description

This PR proposes a design for the /Community page , aligned with OWASP's visual identity.

Static page implementation (as requested), clean & Community first design:

visuals

2026-02-12.04-09-03.mp4

disscussion

some tests will need to be added / updated related to the PR. After the design is approved.

Checklist

  • Required: I followed the contributing workflow
  • Required: I verified that my code works as intended and resolves the issue as described
  • Required: I ran make check-test locally: all warnings addressed, tests passed
  • I used AI for code, documentation, tests, or communication related to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 11, 2026

Summary by CodeRabbit

Release Notes

  • New Features
    • Introduced the Community Hub—a new central destination featuring community chapters, projects, committees, organizations, members, and contribution opportunities.
    • Displays community statistics (contributors, active chapters, active projects) and recent releases.
    • Highlights top community contributors and provides quick links to GitHub and member profiles.

Walkthrough

Introduces a new Community Hub page with layout template, GraphQL queries, and components. Displays community statistics, navigable resource sections, recent releases, and top contributors. Updates metadata configuration and enhances ContributorsList component with customizable styling options.

Changes

Cohort / File(s) Summary
Community Page Implementation
frontend/src/app/community/layout.tsx, frontend/src/app/community/page.tsx
Adds community layout with metadata export and a new Community Hub page featuring stats overview, navigation grid, recent releases section, top contributors sidebar, and quick links footer.
GraphQL Queries & Data
frontend/src/server/queries/homeQueries.ts, frontend/src/server/queries/communityQueries.ts
Introduces new GetCommunityPageData query for community stats, releases, and contributors. Refactors homeQueries to use parameterized limits for topContributors and recentReleases instead of hard-coded values.
Configuration & Utilities
frontend/src/utils/metadata.ts
Adds "community" metadata entry with description, keywords, pageTitle, and type fields to METADATA_CONFIG.
Component Enhancements
frontend/src/components/ContributorsList.tsx
Extends ContributorsList component with className and gridClassName optional props for custom styling; uses tailwind-merge to unify grid classes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Suggested reviewers

  • arkid15r
  • kasya
🚥 Pre-merge checks | ✅ 3 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Community page design proposal' is vague and generic, using non-descriptive terms that don't clearly convey the specific implementation details or main technical changes introduced in this PR. Consider a more specific title like 'Add Community page with stats and navigation sections' or 'Implement Community Hub page with overview stats and resource exploration'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The PR description is related to the changeset, mentioning the Community page design proposal and referencing issue #3862, though it lacks technical detail about the implementation.
Linked Issues check ✅ Passed The PR successfully implements all key requirements from #3862: provides a Community page with overview introduction, displays high-level statistics (contributors, active chapters, active projects), and surfaces community context through navigation sections and recent releases.
Out of Scope Changes check ✅ Passed The PR introduces changes to ContributorsList component styling (className and gridClassName props), which extends beyond the #3862 issue scope but is reasonably necessary to support the Community page's sidebar implementation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
frontend/src/components/ContributorsList.tsx (1)

53-59: Consider always merging defaults instead of conditionally excluding them.

The current logic skips all default responsive columns when gridClassName is provided, forcing callers to re-specify everything (including breakpoints). If this is intentional (full override), it works. But if callers typically just want to tweak one breakpoint, twMerge can handle the conflict resolution automatically:

♻️ Optional simplification
-        className={twMerge(
-          'grid gap-4',
-          !gridClassName && 'sm:grid-cols-1 md:grid-cols-3 lg:grid-cols-4',
-          gridClassName
-        )}
+        className={twMerge(
+          'grid gap-4 sm:grid-cols-1 md:grid-cols-3 lg:grid-cols-4',
+          gridClassName
+        )}

This way twMerge resolves conflicting grid-cols utilities automatically while preserving any non-conflicting defaults.

frontend/src/app/community/page.tsx (4)

25-68: color is identical across all NAV_SECTIONS entries — extract it.

Every section uses 'text-gray-900 dark:text-gray-100'. If this is intentional uniformity, just apply it at the render site and remove the per-item color field.

♻️ Suggested simplification
 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',
   },
   // ... same for all others
 ]

Then at the render site (line 140):

-  <IconWrapper icon={section.icon} className={`h-6 w-6 ${section.color}`} />
+  <IconWrapper icon={section.icon} className="h-6 w-6 text-gray-900 dark:text-gray-100" />

83-105: Same observation for statscolor and bg are identical across all items.

All three stat entries share the same color and bg values. Consider extracting these as constants or applying them directly in the JSX.


108-108: Hardcoded hex color dark:bg-[#212529] — prefer Tailwind palette.

Using an arbitrary hex value bypasses the design system. dark:bg-gray-900 or dark:bg-gray-850 (if available in your config) would be more consistent with the rest of the page which uses standard Tailwind gray shades.


70-79: No error recovery or user action on failure.

The error state renders static text with no retry option. Consider adding a retry button or linking to a fallback so users aren't stuck.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@frontend/src/app/community/page.tsx`:
- Around line 72-77: The page is over-fetching by using GetMainPageDataDocument;
create a dedicated, smaller GraphQL query (e.g., GetCommunityPageDataDocument)
that only requests statsOverview, recentReleases, and topContributors (with the
same recentReleasesLimit and topContributorsLimit variables), replace the
useQuery call that references GetMainPageDataDocument with one that uses the new
document, and remove any references to unused fields (recentProjects,
recentPosts, recentChapters, recentIssues, recentPullRequests, recentMilestones,
sponsors, upcomingEvents) so only the needed data is fetched and returned to the
component.
- Around line 234-235: The external GitHub Link in community/page.tsx (the Link
with href="https://github.com/owasp") needs to open in a new tab and prevent
reverse-tabnapping; update the Link so the rendered anchor includes
target="_blank" and rel="noopener noreferrer" (for Next.js/React, add these
attributes to the child <a> or the Link element that renders the anchor) to
ensure it opens in a new tab safely.
- Line 197: The code fetches up to recentReleasesLimit (set to 10) but then
truncates the UI with data?.recentReleases?.slice(0, 6), causing 4 items to be
dropped; pick one: if you want to show 6 items, change recentReleasesLimit to 6
(update the variable/constant named recentReleasesLimit), or if you want to show
all fetched items, remove the .slice(0, 6) in the JSX mapping (the line
referencing data?.recentReleases?.slice) so the map renders data?.recentReleases
directly; update the corresponding symbol(s) accordingly.
🧹 Nitpick comments (3)
frontend/src/components/CommunityContributorsList.tsx (2)

27-31: Move the early return before the slice for clarity.

The empty-array guard on line 29 should come before the slice on line 27. Currently the slice runs unnecessarily when contributors is empty — functionally harmless but reads better with the guard first.

Proposed reorder
 }: CommunityContributorsListProps) => {
+  if (contributors.length === 0) {
+    return null
+  }
+
   const displayContributors = contributors.slice(0, maxInitialDisplay)
-
-  if (contributors.length === 0) {
-    return null
-  }

41-41: twMerge with a single argument is a no-op.

twMerge(className) just returns className unchanged. Either pass className directly or merge it with a base class string if one is intended.

frontend/src/app/community/page.tsx (1)

1-1: Consider whether 'use client' is necessary for the entire page.

The page currently uses useQuery which requires client-side rendering, but the bulk of the page is static content (hero, nav sections, quick links). If the project supports it, you could split the data-dependent sections into a client component and keep the rest as a server component for better initial load performance and SEO.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 6 files

Confidence score: 3/5

  • The community page in frontend/src/app/community/page.tsx reuses a heavy GraphQL query but only consumes a small subset of fields, which can cause unnecessary data fetching and user-visible performance impact.
  • frontend/src/components/CommunityContributorsList.tsx largely duplicates ContributorsList.tsx, increasing maintenance risk and the chance of divergence over time.
  • The score reflects some concrete user-impacting risk (overfetching) plus a medium maintainability concern.
  • Pay close attention to frontend/src/app/community/page.tsx and frontend/src/components/CommunityContributorsList.tsx - reduce overfetching and avoid duplicated component logic.
Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="frontend/src/app/community/page.tsx">

<violation number="1" location="frontend/src/app/community/page.tsx:18">
P1: This page reuses the home page's GraphQL query (`GetMainPageDataDocument`) which fetches ~12 top-level fields, but only 3 are used here (`statsOverview`, `recentReleases`, `topContributors`). This causes significant over-fetching of data (projects, posts, chapters, issues, PRs, sponsors, events, milestones are all fetched and discarded). Create a dedicated query for the community page that only requests the fields it needs.

(Based on your team's feedback about using existing shared components and utilities.) [FEEDBACK_USED]</violation>
</file>

<file name="frontend/src/components/CommunityContributorsList.tsx">

<violation number="1" location="frontend/src/components/CommunityContributorsList.tsx:19">
P2: This component is a near-exact duplicate of the existing `ContributorsList.tsx`. Instead of creating a parallel implementation, extend the existing `ContributorsList` with additional props (e.g., `className`, `showMore`, `gridClassName`, `cardClassName`) to customize its behavior. This avoids maintaining two almost-identical components that will easily drift out of sync.

(Based on your team's feedback about using existing shared components and utilities.) [FEEDBACK_USED]</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@Mr-Rahul-Paul Mr-Rahul-Paul marked this pull request as draft February 11, 2026 23:37
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 4 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="frontend/src/app/community/page.tsx">

<violation number="1" location="frontend/src/app/community/page.tsx:240">
P3: Spurious `{' '}` adds a leading space inside the link text, rendering as " Github" instead of "Github". Remove this line to avoid the extra whitespace.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@frontend/src/app/community/page.tsx`:
- Around line 240-241: Update the displayed label text in the component that
renders the string "Github" to use the correct capitalization "GitHub" and
remove the stray JSX whitespace token {' '} surrounding it; locate the JSX
element in page.tsx that currently contains {' '} Github and replace it with a
single plain "GitHub" text node so the UI renders with correct spelling and no
extra space token.
- Around line 197-204: The map uses release.tagName as the React key which can
collide across repos; change the key to the unique GraphQL id (use release.id)
in the mapping that renders the Release component so each <Release key=...
release={release as ReleaseType} .../> uses release.id instead of
release.tagName to avoid duplicate key warnings and rendering bugs.
- Line 200: Remove the unsafe cast "as ReleaseType" when passing the
recentReleases item to the release prop and make the types align: update the
GraphQL query that supplies recentReleases to return publishedAt as a number
(e.g., epoch or timestamp) and shape author to match your User type, or
alternatively modify the ReleaseType definition to accept publishedAt: any |
null and the actual author shape from GraphQL; ensure checks/conversions occur
where you map recentReleases to the component (so ReleaseType and the data
returned by recentReleases are concordant and you no longer need the cast).
🧹 Nitpick comments (4)
frontend/src/components/ContributorCard.tsx (1)

22-35: Inconsistent optional chaining on contributor.

contributor is a required prop (non-optional Contributor), yet lines 23, 26, 27, 32, 33 use contributor?. while line 35 accesses contributor.name / contributor.login directly. Pick one style — since the prop is required, drop the unnecessary optional chaining for consistency.

♻️ Suggested diff
-          alt={contributor?.name ? `${contributor.name}'s avatar` : 'Contributor avatar'}
+          alt={contributor.name ? `${contributor.name}'s avatar` : 'Contributor avatar'}
           className="rounded-full"
           height={24}
-          src={`${contributor?.avatarUrl}${contributor?.avatarUrl?.includes('?') ? '&' : '?'}s=60`}
-          title={contributor?.name || contributor?.login}
+          src={`${contributor.avatarUrl}${contributor.avatarUrl.includes('?') ? '&' : '?'}s=60`}
+          title={contributor.name || contributor.login}
           width={24}
         />
         <Link
           className="cursor-pointer overflow-hidden font-semibold text-ellipsis whitespace-nowrap text-blue-400 hover:underline"
-          href={getUrl(contributor?.login)}
-          title={contributor?.name || contributor?.login}
+          href={getUrl(contributor.login)}
+          title={contributor.name || contributor.login}
         >
frontend/src/app/community/page.tsx (3)

26-69: The color property is identical for every entry in NAV_SECTIONS.

All six items use 'text-gray-900 dark:text-gray-100'. You could extract this as a constant or apply it directly in the rendering code, removing the per-item boilerplate.


71-81: Full-page loading spinner with no error recovery.

The entire page shows a spinner while data loads (no skeleton/placeholder), and on error the user sees a static message with no way to retry. Consider adding a retry button or using Apollo's refetch to let users recover from transient failures.

Minimal retry example
-  if (error)
-    return <div className="p-8 text-center text-red-500">Error loading community data.</div>
+  if (error)
+    return (
+      <div className="p-8 text-center text-red-500">
+        Error loading community data.
+        <button
+          className="ml-2 text-blue-500 underline"
+          onClick={() => void refetch()}
+        >
+          Retry
+        </button>
+      </div>
+    )

You'll need to destructure refetch from useQuery:

-  const { data, loading, error } = useQuery(...)
+  const { data, loading, error, refetch } = useQuery(...)

109-110: Use a theme token or define the color in the Tailwind config for consistency.

dark:bg-[#212529] is inconsistent with the surrounding code, which uses theme tokens like dark:bg-gray-800 and dark:text-gray-100. Add this color to the Tailwind config's theme if it's intentional, or switch to an existing token that matches the design intent.

@Mr-Rahul-Paul Mr-Rahul-Paul marked this pull request as ready for review February 12, 2026 00:36
@Mr-Rahul-Paul Mr-Rahul-Paul marked this pull request as draft February 12, 2026 02:43
@sonarqubecloud
Copy link

@Mr-Rahul-Paul Mr-Rahul-Paul marked this pull request as ready for review February 12, 2026 09:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Community Overview Stats Section

1 participant