Refactor Winners Tab to Match Organizer Design (app/hackathons/[slug])
Objective
Upgrade the participant-facing "Winners" tab to use the premium design already established in the organizer's PublishWinnersWizard, and ensure all project and participant links are fully functional with correct deep-linking parameters. The current implementation renders a basic card grid that lacks the visual hierarchy, deep linking, and premium "Podium" aesthetics that the organizer-side already delivers. This refactor closes that gap — the participant-facing winners experience should be indistinguishable in quality from what organizers see when publishing results.
Context & Current Implementation
Route
app/(landing)/hackathons/[slug]/page.tsx
Primary Component
components/hackathons/winners/WinnersTab.tsx
How It Currently Works
- The page uses the
useHackathonData() hook to fetch the winners dataset
WinnersTab is conditionally rendered when winners.length > 0 and the winnersTab feature is enabled in currentHackathon.enabledTabs
- The current implementation renders a basic grid of winner cards that lack:
- Clickable deep links for projects and participant profiles
- The premium "Podium" visual hierarchy for top 3 ranks
- USDC financial branding next to prize amounts
- The
Ribbon rank display and high-quality avatar treatments from the organizer design
UI & Design Replication
Design Source
- Mirror the design found in
components/organization/hackathons/rewards/WinnerCard.tsx exactly — this is the canonical reference and the participant-facing card must reach the same level of visual quality
Card Aesthetics
- Use the
Ribbon component for rank display on each winner tile — the ribbon should be prominently placed and visually distinct per rank position
- Use high-quality
Avatar circles for winner profile images, with appropriate fallback initials if no avatar is available
- Include a stylized project preview card at the bottom of each winner tile, showing the project image or thumbnail alongside the project name
- Prize amounts must display the USDC logo inline next to the value to ensure clear, unambiguous financial branding
Card Hierarchy & Podium Layout
- Replicate the
WinnersGrid layout from components/organization/hackathons/rewards/WinnersGrid.tsx as the structural foundation
- Where applicable (i.e., when the top 3 ranked winners are present), implement the "Podium" effect — visually elevating 1st place above 2nd and 3rd, with proportional sizing or vertical offset that communicates rank at a glance
- Cards beyond the top 3 should render in a standard grid below the podium section, maintaining the same card design without the podium elevation treatment
- The overall layout must be responsive — the podium and grid should reflow gracefully at tablet and mobile breakpoints without breaking the visual hierarchy
Deep Linking & Logic
Project Link
- Refactor the project name and project image/thumbnail on each winner card to be clickable links
- Path:
/projects/${projectId}?type=submission
- The
?type=submission query parameter is required — it must always be appended to ensure the project page renders in the correct submission view context. Do not omit this parameter under any circumstance.
Participant Link
- Refactor the participant name and avatar on each winner card to be clickable links
- Path:
/profile/${username} — linking to the participant's public profile page
Fallback Rendering
- Both links must degrade gracefully when metadata is missing:
- If
projectId is null or undefined, render the project name and image as non-clickable text/image rather than a broken link
- If
username is null or undefined, render the participant name and avatar as non-clickable elements
- If avatar image fails to load, fall back to styled initials using the existing
Avatar component fallback pattern
- Missing metadata must never cause a rendering error or blank card — the tile should always display whatever information is available
Technical Details
Hooks & Data Path
- All winner data is provided by the
useHackathonData() hook in the parent HackathonPage — no additional API calls should be introduced
- Map the
winners array (typed as Array<HackathonWinner>) from the hook's context output to the new WinnerCard component props
- The mapping should be explicit and type-safe — strictly no
any types
Components to Modify
- Overhaul
components/hackathons/winners/WinnersTab.tsx — this is the primary deliverable
- Reference the logic and structure from
components/organization/hackathons/rewards/PublishWinnersWizard.tsx for implementation guidance
- Reference
components/organization/hackathons/rewards/WinnerCard.tsx for the card design spec
- Reference
components/organization/hackathons/rewards/WinnersGrid.tsx for the grid and podium layout
⚠️ Caution
This is a production environment — not a sandbox.
- Code must be performant, accessible, and clean
- No dummy data — all winner data must come exclusively from the
useHackathonData() hook; no hardcoded or mock values
- AI-generated code will be scrutinized; poorly structured or "hallucinated" code will result in immediate issue closure
- Follow the existing design system: shadcn/ui, Tailwind, Framer Motion
Testing & Verification
Automated Tests
npm run lint # Ensure code quality
npm run build # Verify no breaking changes in routing or types
Manual Verification
Refactor Winners Tab to Match Organizer Design (
app/hackathons/[slug])Objective
Upgrade the participant-facing "Winners" tab to use the premium design already established in the organizer's
PublishWinnersWizard, and ensure all project and participant links are fully functional with correct deep-linking parameters. The current implementation renders a basic card grid that lacks the visual hierarchy, deep linking, and premium "Podium" aesthetics that the organizer-side already delivers. This refactor closes that gap — the participant-facing winners experience should be indistinguishable in quality from what organizers see when publishing results.Context & Current Implementation
Route
app/(landing)/hackathons/[slug]/page.tsxPrimary Component
components/hackathons/winners/WinnersTab.tsxHow It Currently Works
useHackathonData()hook to fetch thewinnersdatasetWinnersTabis conditionally rendered whenwinners.length > 0and thewinnersTabfeature is enabled incurrentHackathon.enabledTabsRibbonrank display and high-quality avatar treatments from the organizer designUI & Design Replication
Design Source
components/organization/hackathons/rewards/WinnerCard.tsxexactly — this is the canonical reference and the participant-facing card must reach the same level of visual qualityCard Aesthetics
Ribboncomponent for rank display on each winner tile — the ribbon should be prominently placed and visually distinct per rank positionAvatarcircles for winner profile images, with appropriate fallback initials if no avatar is availableCard Hierarchy & Podium Layout
WinnersGridlayout fromcomponents/organization/hackathons/rewards/WinnersGrid.tsxas the structural foundationDeep Linking & Logic
Project Link
/projects/${projectId}?type=submission?type=submissionquery parameter is required — it must always be appended to ensure the project page renders in the correct submission view context. Do not omit this parameter under any circumstance.Participant Link
/profile/${username}— linking to the participant's public profile pageFallback Rendering
projectIdis null or undefined, render the project name and image as non-clickable text/image rather than a broken linkusernameis null or undefined, render the participant name and avatar as non-clickable elementsAvatarcomponent fallback patternTechnical Details
Hooks & Data Path
useHackathonData()hook in the parentHackathonPage— no additional API calls should be introducedwinnersarray (typed asArray<HackathonWinner>) from the hook's context output to the newWinnerCardcomponent propsanytypesComponents to Modify
components/hackathons/winners/WinnersTab.tsx— this is the primary deliverablecomponents/organization/hackathons/rewards/PublishWinnersWizard.tsxfor implementation guidancecomponents/organization/hackathons/rewards/WinnerCard.tsxfor the card design speccomponents/organization/hackathons/rewards/WinnersGrid.tsxfor the grid and podium layoutuseHackathonData()hook; no hardcoded or mock valuesTesting & Verification
Automated Tests
Manual Verification
WinnersTabis only rendered whenwinners.length > 0andwinnersTabis present incurrentHackathon.enabledTabsRibboncomponent displays the correct rank on each card/projects/${projectId}?type=submissionwith the query parameter correctly appended/profile/${username}projectId,username, or avatar image render gracefully without broken links, blank tiles, or console errorsuseHackathonData()anytypes are present in the winner data mapping layercomponents/organization/hackathons/rewards/WinnerCard.tsxat full fidelity