Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/(landing)/bounties/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React from 'react';
import { redirect } from 'next/navigation';
import { Metadata } from 'next';
import { generatePageMetadata } from '@/lib/metadata';

export const metadata: Metadata = generatePageMetadata('grants');

@coderabbitai coderabbitai Bot Feb 28, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, check if the bounties page file exists and read its contents
echo "=== Checking app/(landing)/bounties/page.tsx ==="
if [ -f "app/(landing)/bounties/page.tsx" ]; then
  cat -n "app/(landing)/bounties/page.tsx" | head -30
else
  echo "File not found at app/(landing)/bounties/page.tsx"
  # Try to find bounties page with different path patterns
  find . -name "page.tsx" -path "*/bounties/*" 2>/dev/null | head -5
fi

Repository: boundlessfi/boundless

Length of output: 686


🏁 Script executed:

#!/bin/bash
# Check for pageMetadata definition and 'bounties' key
echo "=== Searching for pageMetadata and bounties key ==="
if [ -f "lib/metadata.ts" ]; then
  echo "--- lib/metadata.ts content ---"
  cat -n "lib/metadata.ts"
else
  echo "Checking for metadata file in different locations:"
  find . -name "*metadata*" -type f 2>/dev/null | grep -E "\.(ts|js)$" | head -10
fi

Repository: boundlessfi/boundless

Length of output: 23611


Incorrect metadata key and unreachable code in bounties page.

The metadata uses 'grants' but this is the bounties page, causing incorrect SEO metadata to be served. Additionally, the JSX return statements (lines 9–13) are unreachable after the redirect() call on line 8 and should be removed.

Note: The 'bounties' key does not exist in pageMetadata (lib/metadata.ts). Before changing the metadata key, either add a 'bounties' entry to the pageMetadata object or use an existing key like 'projects'.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/`(landing)/bounties/page.tsx at line 5, The file wrongly sets export
const metadata: Metadata = generatePageMetadata('grants') on the bounties page
and also contains unreachable JSX after a redirect(); fix by either replacing
the key 'grants' with an existing key like 'projects' or add a 'bounties' entry
to the pageMetadata map in lib/metadata.ts, update the generatePageMetadata call
accordingly (use generatePageMetadata('bounties') only if you add that entry),
and remove the dead JSX/return statements after the redirect() call so only the
redirect remains; update references to the metadata constant and the
generatePageMetadata invocation to reflect the chosen key.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The code is meant to be unreachable as for the incorrect metadata, I didn't have a touch in that part of the code. I just did what I was asked to do.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@Shadow-MMN, thank you for the clarification. You're absolutely right that the metadata issue with 'grants' was pre-existing—your changes only added the redirect.

Regarding the unreachable code: I notice that in other files within this same PR, the return statements were handled differently. For example:

  • app/me/analytics/page.tsx, app/me/hackathons/page.tsx, app/me/profile/page.tsx → only contain the redirect, no return statement
  • app/(landing)/profile/[username]/projects/page.tsx → the return statement was removed

While in bounties/page.tsx, grants/page.tsx, contact/page.tsx, and organizations/[id]/grants/page.tsx, the return statements remain after the redirect.

For consistency and cleanliness (especially given the PR's quality constraints), you might consider removing the unreachable return statements in these files. But if you prefer to keep them as-is, that's your call—the redirect will work either way.


const GrantPage = () => {
redirect('/coming-soon');
return (
<div className='mx-auto mt-10 max-w-[1440px] px-5 py-5 text-center text-4xl font-bold text-white md:px-[50px] lg:px-[100px]'>
Bounties Page
Expand Down
3 changes: 2 additions & 1 deletion app/(landing)/contact/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React from 'react';
import { redirect } from 'next/navigation';
import { Metadata } from 'next';
import { generatePageMetadata } from '@/lib/metadata';

export const metadata: Metadata = generatePageMetadata('contact');

const ContactPage = () => {
redirect('/coming-soon');
return (
<div className='mx-auto mt-10 max-w-[1440px] px-5 py-5 text-center text-4xl font-bold text-white md:px-[50px] lg:px-[100px]'>
Contact Page
Expand Down
3 changes: 2 additions & 1 deletion app/(landing)/grants/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React from 'react';
import { redirect } from 'next/navigation';
import { Metadata } from 'next';
import { generatePageMetadata } from '@/lib/metadata';

export const metadata: Metadata = generatePageMetadata('grants');

const GrantPage = () => {
redirect('/coming-soon');
return (
<div className='mx-auto mt-10 max-w-[1440px] px-5 py-5 text-center text-4xl font-bold text-white md:px-[50px] lg:px-[100px]'>
Grant Page
Expand Down
2 changes: 2 additions & 0 deletions app/(landing)/organizations/[id]/grants/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { redirect } from 'next/navigation';
import { AuthGuard } from '@/components/auth';
import Loading from '@/components/Loading';

export default function GrantsPage() {
redirect('/coming-soon');
return (
<AuthGuard redirectTo='/auth?mode=signin' fallback={<Loading />}>
<div className='min-h-screen bg-black text-white'>
Expand Down
5 changes: 2 additions & 3 deletions app/(landing)/profile/[username]/projects/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React from 'react';

import { redirect } from 'next/navigation';
const Page = () => {
return <div>Projects</div>;
redirect('/coming-soon');
};

export default Page;
17 changes: 17 additions & 0 deletions app/coming-soon/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import ComingSoon from '@/components/ComingSoon';
import { Footer, Navbar } from '@/components/landing-page';
import React from 'react';

const page = () => {
return (
<>
<Navbar />
<main className='min-h-[calc(100vh-56px)] flex-1'>
<ComingSoon />
</main>
<Footer />
</>
);
};

export default page;
7 changes: 7 additions & 0 deletions app/me/analytics/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { redirect } from 'next/navigation';

const page = () => {
redirect('/coming-soon');
};

export default page;
7 changes: 7 additions & 0 deletions app/me/hackathons/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { redirect } from 'next/navigation';

const page = () => {
redirect('/coming-soon');
};

export default page;
7 changes: 7 additions & 0 deletions app/me/hackathons/submissions/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { redirect } from 'next/navigation';

const page = () => {
redirect('/coming-soon');
};

export default page;
7 changes: 7 additions & 0 deletions app/me/notifications/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { redirect } from 'next/navigation';

const page = () => {
redirect('/coming-soon');
};

export default page;
7 changes: 7 additions & 0 deletions app/me/profile/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { redirect } from 'next/navigation';

const page = () => {
redirect('/coming-soon');
};

export default page;
7 changes: 7 additions & 0 deletions app/me/projects/create/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { redirect } from 'next/navigation';

const page = () => {
redirect('/coming-soon');
};

export default page;
115 changes: 115 additions & 0 deletions components/ComingSoon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
'use client';

import {
ArrowDownUp,
CircleDollarSign,
ChartNoAxesColumnIncreasing,
ShieldCheck,
LucideIcon,
} from 'lucide-react';
import { motion } from 'framer-motion';

type Feature = {
id: string;
title: string;
description: string;
icon: LucideIcon;
};

const features: Feature[] = [
{
id: 'grant-flow',
title: 'Full Grant Flow & Architecture',
description:
'End-to-end grant lifecycle system covering submission, evaluation, approval, and fund distribution.',
icon: ArrowDownUp,
},
{
id: 'bounty-implementation',
title: 'Bounty Implementation',
description:
'Structured bounty creation with decentralized submission handling and transparent verification.',
icon: CircleDollarSign,
},
{
id: 'analytics-dashboard',
title: 'Advanced Analytics Dashboard',
description:
'Clear financial and participation metrics with intuitive visual breakdowns.',
icon: ChartNoAxesColumnIncreasing,
},
{
id: 'verified-badging',
title: 'Verified Project Badging',
description:
'Recognition layer for trusted and high-quality ecosystem projects.',
icon: ShieldCheck,
},
];

const FeatureBlock = ({
title,
description,
icon: Icon,
index,
}: Feature & { index: number }) => {
return (
<motion.div
initial={{ opacity: 0, scale: 0.95 }}
whileInView={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.6, delay: index * 0.12 }}
viewport={{ once: true }}
whileHover={{ scale: 1.02 }}
className='relative overflow-hidden rounded-3xl bg-gradient-to-br from-[#0e0e0e] to-[#1a1a1a] p-10'
>
<div className='pointer-events-none absolute -top-16 -right-16 opacity-5'>
<Icon className='h-64 w-64' />
</div>

<div className='mb-6 flex items-center gap-2 text-sm text-[#a7f950]'>
<div className='h-2 w-2 animate-pulse rounded-full bg-[#a7f950]' />
In Progress
</div>

<h3 className='text-2xl font-semibold tracking-tight text-white'>
{title}
</h3>

<p className='mt-4 max-w-xl text-sm leading-relaxed text-neutral-400'>
{description}
</p>
</motion.div>
);
};

const ComingSoon = () => {
return (
<section className='py-24'>
<div className='mx-auto max-w-6xl px-6'>
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
viewport={{ once: true }}
className='mb-20 max-w-2xl'
>
<h1 className='text-5xl font-bold tracking-tight text-white md:text-6xl'>
Coming Soon
</h1>
<p className='mt-6 text-lg text-neutral-400'>
We’re building foundational systems to power a more transparent,
efficient grant and bounty ecosystem.
</p>
</motion.div>

<div className='flex flex-col gap-12'>
{features.map((feature, index) => (
<FeatureBlock key={feature.id} {...feature} index={index} />
))}
</div>
</div>
</section>
);
};
Comment on lines +85 to +113

@coderabbitai coderabbitai Bot Feb 28, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Missing "Notify Me" form per requirements.

The linked issue #393 specifies: "Integrate a 'Notify Me' form wired to the subscription/waitlist API." This engagement feature is absent from the current implementation.

Would you like me to help scaffold a "Notify Me" form component that can be wired to your subscription/waitlist API, or open an issue to track this separately?

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/ComingSoon.tsx` around lines 83 - 113, The ComingSoon component is
missing the required "Notify Me" form (per issue `#393`); add a small controlled
form inside ComingSoon (e.g., below the Abstract Feature Blocks or inside the
container div) with inputs for email (and optional name) and a submit button,
implement local validation, and call the subscription/waitlist API on submit;
wire state handlers (useState) and an async submit handler (e.g.,
handleNotifySubmit) that POSTs to your API endpoint, shows loading/error/success
feedback, and prevent duplicate submissions; ensure the form component is either
inlined in ComingSoon or extracted as a new NotifyMe component and referenced
from ComingSoon, and include tests/aria attributes for accessibility.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Maintainer said I should not worry about the notfiy me button

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@Shadow-MMN, understood! If the maintainer has waived that requirement, you're all set.

ฅ^•ﻌ•^ฅ


export default ComingSoon;
Loading