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
12 changes: 12 additions & 0 deletions src/app/(discover)/bounties/opengraph-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { getPillar } from '@/config/pillars';
import { OG_CONTENT_TYPE, OG_SIZE, renderOgImage } from '@/lib/og-image';

const pillar = getPillar('bounties');

export const size = OG_SIZE;
export const contentType = OG_CONTENT_TYPE;
export const alt = pillar.heading;

export default function Image() {
return renderOgImage({ title: pillar.heading, subtitle: pillar.subtext });
}
11 changes: 11 additions & 0 deletions src/app/(discover)/bounties/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
import type { Metadata } from 'next';

import { getPillar } from '@/config/pillars';
import { DiscoverView } from '@/features/discover';

import { discoverMetadata } from '../seo';

export const metadata: Metadata = discoverMetadata({
title: 'Bounties',
description:
'Discover bounties that match your skills and compete for rewards on Boundless.',
path: '/bounties',
});

export default function BountiesPage() {
const pillar = getPillar('bounties');
return (
Expand Down
12 changes: 12 additions & 0 deletions src/app/(discover)/crowdfunding/opengraph-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { getPillar } from '@/config/pillars';
import { OG_CONTENT_TYPE, OG_SIZE, renderOgImage } from '@/lib/og-image';

const pillar = getPillar('crowdfunding');

export const size = OG_SIZE;
export const contentType = OG_CONTENT_TYPE;
export const alt = pillar.heading;

export default function Image() {
return renderOgImage({ title: pillar.heading, subtitle: pillar.subtext });
}
11 changes: 11 additions & 0 deletions src/app/(discover)/crowdfunding/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
import type { Metadata } from 'next';

import { getPillar } from '@/config/pillars';
import { DiscoverView } from '@/features/discover';

import { discoverMetadata } from '../seo';

export const metadata: Metadata = discoverMetadata({
title: 'Crowdfunding',
description:
'Back crowdfunding projects you believe in and help them reach their goals on Boundless.',
path: '/crowdfunding',
});

export default function CrowdfundingPage() {
const pillar = getPillar('crowdfunding');
return (
Expand Down
10 changes: 10 additions & 0 deletions src/app/(discover)/explore/opengraph-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { EXPLORE } from '@/config/pillars';
import { OG_CONTENT_TYPE, OG_SIZE, renderOgImage } from '@/lib/og-image';

export const size = OG_SIZE;
export const contentType = OG_CONTENT_TYPE;
export const alt = EXPLORE.heading;

export default function Image() {
return renderOgImage({ title: EXPLORE.heading, subtitle: EXPLORE.subtext });
}
11 changes: 11 additions & 0 deletions src/app/(discover)/explore/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
import type { Metadata } from 'next';

import { EXPLORE } from '@/config/pillars';
import { DiscoverView } from '@/features/discover';

import { discoverMetadata } from '../seo';

export const metadata: Metadata = discoverMetadata({
title: 'Explore',
description:
'Browse bounties, hackathons, grants, and crowdfunding projects across the Boundless ecosystem on Stellar.',
path: '/explore',
});

export default function ExplorePage() {
return <DiscoverView heading={EXPLORE.heading} subtext={EXPLORE.subtext} />;
}
12 changes: 12 additions & 0 deletions src/app/(discover)/grants/opengraph-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { getPillar } from '@/config/pillars';
import { OG_CONTENT_TYPE, OG_SIZE, renderOgImage } from '@/lib/og-image';

const pillar = getPillar('grants');

export const size = OG_SIZE;
export const contentType = OG_CONTENT_TYPE;
export const alt = pillar.heading;

export default function Image() {
return renderOgImage({ title: pillar.heading, subtitle: pillar.subtext });
}
10 changes: 10 additions & 0 deletions src/app/(discover)/grants/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import type { Metadata } from 'next';

import { getPillar } from '@/config/pillars';
import { DiscoverView } from '@/features/discover';

import { discoverMetadata } from '../seo';

export const metadata: Metadata = discoverMetadata({
title: 'Grants',
description: 'Apply for grants to fund what matters and build on Boundless.',
path: '/grants',
});

export default function GrantsPage() {
const pillar = getPillar('grants');
return (
Expand Down
12 changes: 12 additions & 0 deletions src/app/(discover)/hackathons/opengraph-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { getPillar } from '@/config/pillars';
import { OG_CONTENT_TYPE, OG_SIZE, renderOgImage } from '@/lib/og-image';

const pillar = getPillar('hackathons');

export const size = OG_SIZE;
export const contentType = OG_CONTENT_TYPE;
export const alt = pillar.heading;

export default function Image() {
return renderOgImage({ title: pillar.heading, subtitle: pillar.subtext });
}
10 changes: 10 additions & 0 deletions src/app/(discover)/hackathons/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import type { Metadata } from 'next';

import { getPillar } from '@/config/pillars';
import { DiscoverView } from '@/features/discover';

import { discoverMetadata } from '../seo';

export const metadata: Metadata = discoverMetadata({
title: 'Hackathons',
description: 'Join hackathons on Boundless, team up, and ship to win.',
path: '/hackathons',
});

export default function HackathonsPage() {
const pillar = getPillar('hackathons');
return (
Expand Down
1 change: 1 addition & 0 deletions src/app/(discover)/seo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { buildPageMetadata as discoverMetadata } from '@/lib/seo';
13 changes: 13 additions & 0 deletions src/app/(public)/about/opengraph-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { OG_CONTENT_TYPE, OG_SIZE, renderOgImage } from '@/lib/og-image';

export const size = OG_SIZE;
export const contentType = OG_CONTENT_TYPE;
export const alt = 'About Boundless';

export default function Image() {
return renderOgImage({
title: 'About Boundless',
subtitle:
'Building the infrastructure for people to learn, collaborate, fund ideas, and create meaningful impact.',
});
}
6 changes: 4 additions & 2 deletions src/app/(public)/about/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import {
BrandKitCta,
CtaSection,
} from '@/features/marketing';
import { buildPageMetadata } from '@/lib/seo';

export const metadata: Metadata = {
export const metadata: Metadata = buildPageMetadata({
title: 'About',
description:
'Boundless is building the infrastructure for people to learn, collaborate, fund ideas, and create meaningful impact online.',
};
path: '/about',
});

export default function AboutPage() {
return (
Expand Down
23 changes: 23 additions & 0 deletions src/app/(public)/blog/[slug]/opengraph-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { getBlogPost } from '@/features/marketing';
import { OG_CONTENT_TYPE, OG_SIZE, renderOgImage } from '@/lib/og-image';

export const size = OG_SIZE;
export const contentType = OG_CONTENT_TYPE;
export const alt = 'Boundless Blog';

export default async function Image({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
const post = getBlogPost(slug);
const subtitle = post?.excerpt
? `${post.excerpt.slice(0, 140)}${post.excerpt.length > 140 ? '…' : ''}`
: undefined;

return renderOgImage({
title: post?.title ?? 'Boundless Blog',
subtitle,
});
}
34 changes: 32 additions & 2 deletions src/app/(public)/blog/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import type { Metadata } from 'next';
import { notFound } from 'next/navigation';

import { ArticleDetail, BLOG_POSTS, getBlogPost } from '@/features/marketing';
import { buildPageMetadata } from '@/lib/seo';
import { SITE_NAME, SITE_URL } from '@/lib/site';

export function generateStaticParams() {
return BLOG_POSTS.map(post => ({ slug: post.slug }));
Expand All @@ -17,7 +19,15 @@ export async function generateMetadata({

if (!post) return { title: 'Article' };

return { title: post.title, description: post.excerpt };
const metadata = buildPageMetadata({
title: post.title,
description: post.excerpt,
path: `/blog/${post.slug}`,
});
return {
...metadata,
openGraph: { ...metadata.openGraph, type: 'article' },
};
}

export default async function BlogArticlePage({
Expand All @@ -30,5 +40,25 @@ export default async function BlogArticlePage({

if (!post) notFound();

return <ArticleDetail post={post} />;
const articleJsonLd = {
'@context': 'https://schema.org',
'@type': 'BlogPosting',
headline: post.title,
description: post.excerpt,
image: `${SITE_URL}${post.cover}`,
datePublished: post.publishedDate,
author: { '@type': 'Person', name: post.author },
publisher: { '@type': 'Organization', name: SITE_NAME },
mainEntityOfPage: `${SITE_URL}/blog/${post.slug}`,
};

return (
<>
<script
type='application/ld+json'
dangerouslySetInnerHTML={{ __html: JSON.stringify(articleJsonLd) }}
/>
<ArticleDetail post={post} />
</>
);
}
12 changes: 12 additions & 0 deletions src/app/(public)/blog/opengraph-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { OG_CONTENT_TYPE, OG_SIZE, renderOgImage } from '@/lib/og-image';

export const size = OG_SIZE;
export const contentType = OG_CONTENT_TYPE;
export const alt = 'Boundless Blog';

export default function Image() {
return renderOgImage({
title: 'Boundless Blog',
subtitle: 'The latest news, stories, and opportunities from Boundless.',
});
}
6 changes: 4 additions & 2 deletions src/app/(public)/blog/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import type { Metadata } from 'next';

import { BlogHero, BlogList, BrandKitCta } from '@/features/marketing';
import { buildPageMetadata } from '@/lib/seo';

export const metadata: Metadata = {
export const metadata: Metadata = buildPageMetadata({
title: 'Blog',
description: 'The latest news, stories, and opportunities from Boundless.',
};
path: '/blog',
});

export default function BlogPage() {
return (
Expand Down
12 changes: 12 additions & 0 deletions src/app/(public)/brand-kit/opengraph-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { OG_CONTENT_TYPE, OG_SIZE, renderOgImage } from '@/lib/og-image';

export const size = OG_SIZE;
export const contentType = OG_CONTENT_TYPE;
export const alt = 'Boundless Brand Kit';

export default function Image() {
return renderOgImage({
title: 'Brand Kit',
subtitle: 'Logo lockups, mark variants, color palette, and product assets.',
});
}
6 changes: 4 additions & 2 deletions src/app/(public)/brand-kit/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import {
DownloadAssets,
LogoShowcase,
} from '@/features/marketing';
import { buildPageMetadata } from '@/lib/seo';

export const metadata: Metadata = {
export const metadata: Metadata = buildPageMetadata({
title: 'Brand Kit',
description:
'Download the latest Boundless brand assets: logo lockups, mark variants, color palette, and product assets.',
};
path: '/brand-kit',
});

export default function BrandKitPage() {
return (
Expand Down
12 changes: 12 additions & 0 deletions src/app/(public)/careers/opengraph-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { OG_CONTENT_TYPE, OG_SIZE, renderOgImage } from '@/lib/og-image';

export const size = OG_SIZE;
export const contentType = OG_CONTENT_TYPE;
export const alt = 'Careers at Boundless';

export default function Image() {
return renderOgImage({
title: 'Careers',
subtitle: 'Come build the future of digital opportunities with Boundless.',
});
}
6 changes: 4 additions & 2 deletions src/app/(public)/careers/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import type { Metadata } from 'next';

import { CareersHero, CtaSection, JobBoard } from '@/features/marketing';
import { buildPageMetadata } from '@/lib/seo';

export const metadata: Metadata = {
export const metadata: Metadata = buildPageMetadata({
title: 'Careers',
description: 'Come build the future of digital opportunities with Boundless.',
};
path: '/careers',
});

export default function CareersPage() {
return (
Expand Down
12 changes: 12 additions & 0 deletions src/app/(public)/faq/opengraph-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { OG_CONTENT_TYPE, OG_SIZE, renderOgImage } from '@/lib/og-image';

export const size = OG_SIZE;
export const contentType = OG_CONTENT_TYPE;
export const alt = 'Boundless FAQs';

export default function Image() {
return renderOgImage({
title: 'FAQs',
subtitle: 'Answers to common questions about Boundless.',
});
}
6 changes: 4 additions & 2 deletions src/app/(public)/faq/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import {
HeroBackground,
Section,
} from '@/features/marketing';
import { buildPageMetadata } from '@/lib/seo';

export const metadata: Metadata = {
export const metadata: Metadata = buildPageMetadata({
title: 'FAQs',
description: 'Answers to common questions about Boundless.',
};
path: '/faq',
});

export default function FaqPage() {
return (
Expand Down
10 changes: 10 additions & 0 deletions src/app/(public)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { Metadata } from 'next';
import Link from 'next/link';

import {
Expand All @@ -12,6 +13,15 @@ import {
Testimonials,
TrustBar,
} from '@/features/marketing';
import { buildPageMetadata } from '@/lib/seo';

export const metadata: Metadata = buildPageMetadata({
title: 'Boundless | Hackathons, Bounties, Grants & Crowdfunding on Stellar',
description:
'Boundless is where builders find hackathons, bounties, and grants, and where ideas get crowdfunded. Build, earn, and belong on Stellar.',
path: '/',
absoluteTitle: true,
});

export default function HomePage() {
return (
Expand Down
Loading
Loading