docs: Add Community Content section to Community Page (#4964)
Co-authored-by: Tania Chakraborty <tchakraborty@block.xyz>
This commit is contained in:
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"title": "🎃 Community Content Contributions",
|
||||||
|
"description": "Amazing blog posts, videos, and tutorials created by our community for goose!",
|
||||||
|
"lastUpdated": "2025-10-02",
|
||||||
|
"hacktoberfestYear": 2025,
|
||||||
|
"submissionUrl": "https://github.com/block/goose/issues/new?template=hacktoberfest-content-submission.yml",
|
||||||
|
"submissions": [
|
||||||
|
{
|
||||||
|
"title": "Configuring goose for Team Environments and Shared Workflows",
|
||||||
|
"author": {
|
||||||
|
"name": "Community Contributor",
|
||||||
|
"handle": "teamgoose"
|
||||||
|
},
|
||||||
|
"type": "blog",
|
||||||
|
"url": "https://teamgoose.dev/goose-team-setup",
|
||||||
|
"thumbnail": "https://images.unsplash.com/photo-1522071820081-009f0129c71c?w=400&h=225&fit=crop&crop=entropy&auto=format",
|
||||||
|
"submittedDate": "2025-10-20",
|
||||||
|
"tags": ["team-setup", "configuration", "collaboration"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ import may2025Data from "./data/may-2025.json";
|
|||||||
import june2025Data from "./data/june-2025.json";
|
import june2025Data from "./data/june-2025.json";
|
||||||
import july2025Data from "./data/july-2025.json";
|
import july2025Data from "./data/july-2025.json";
|
||||||
import august2025Data from "./data/august-2025.json";
|
import august2025Data from "./data/august-2025.json";
|
||||||
|
import communityContentData from "./data/community-content.json";
|
||||||
|
|
||||||
// Create a data map for easy access
|
// Create a data map for easy access
|
||||||
const communityDataMap = {
|
const communityDataMap = {
|
||||||
@@ -211,6 +212,174 @@ function CommunityAllStarsSection() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function CommunityContentSpotlightSection() {
|
||||||
|
const [contentFilter, setContentFilter] = React.useState('all');
|
||||||
|
|
||||||
|
const filteredSubmissions = React.useMemo(() => {
|
||||||
|
if (contentFilter === 'all') return communityContentData.submissions;
|
||||||
|
if (contentFilter === 'hacktoberfest') {
|
||||||
|
return communityContentData.submissions.filter(content =>
|
||||||
|
content.hacktoberfest || content.tags?.includes('hacktoberfest')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return communityContentData.submissions.filter(content => content.type === contentFilter);
|
||||||
|
}, [contentFilter]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="w-full flex flex-col items-center gap-8 my-8">
|
||||||
|
<div className="text-center">
|
||||||
|
<Heading as="h1">{communityContentData.title}</Heading>
|
||||||
|
<p>{communityContentData.description}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Filter Tabs */}
|
||||||
|
<div className="flex justify-center gap-2 flex-wrap">
|
||||||
|
{[
|
||||||
|
{ id: 'all', label: 'All Content' },
|
||||||
|
{ id: 'hacktoberfest', label: '🎃 Hacktoberfest 2025' },
|
||||||
|
{ id: 'blog', label: '📝 Blog Posts' },
|
||||||
|
{ id: 'video', label: '🎥 Videos' }
|
||||||
|
].map((filter) => (
|
||||||
|
<button
|
||||||
|
key={filter.id}
|
||||||
|
className="button button--secondary"
|
||||||
|
onClick={() => setContentFilter(filter.id)}
|
||||||
|
style={contentFilter === filter.id ? {
|
||||||
|
backgroundColor: 'var(--ifm-color-primary)',
|
||||||
|
color: 'white',
|
||||||
|
border: '2px solid var(--ifm-color-primary-dark)'
|
||||||
|
} : {}}
|
||||||
|
>
|
||||||
|
{filter.label}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Content Grid */}
|
||||||
|
<div className="w-full max-w-6xl">
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
|
{/* Persistent Hacktoberfest CTA Card */}
|
||||||
|
<HacktoberfestCTACard />
|
||||||
|
|
||||||
|
{filteredSubmissions.map((content, index) => (
|
||||||
|
<ContentCard key={index} content={content} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{filteredSubmissions.length === 0 && (
|
||||||
|
<div className="text-center py-8">
|
||||||
|
<p className="text-textSubtle">No content found for this filter.</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function HacktoberfestCTACard(): ReactNode {
|
||||||
|
return (
|
||||||
|
<div className="card h-full transition-all duration-200 hover:shadow-lg hover:-translate-y-1 bg-gradient-to-br from-orange-100 to-purple-100 border-2 border-orange-300">
|
||||||
|
{/* Thumbnail placeholder */}
|
||||||
|
<div className="card__image relative">
|
||||||
|
<div className="w-full h-48 bg-gradient-to-br from-orange-200 to-purple-200 flex items-center justify-center">
|
||||||
|
<span className="text-6xl">🎃</span>
|
||||||
|
</div>
|
||||||
|
<div className="absolute top-2 left-2 bg-orange-500 text-white px-2 py-1 rounded-full text-xs font-bold flex items-center gap-1">
|
||||||
|
🎃 Hacktoberfest
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
|
<div className="card__body">
|
||||||
|
{/* CTA Button as Title */}
|
||||||
|
<div className="mb-3">
|
||||||
|
<Link
|
||||||
|
href={communityContentData.submissionUrl}
|
||||||
|
className="button button--primary button--block button--lg"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
🚀 Submit Your Content!
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Description */}
|
||||||
|
<div className="text-sm text-textSubtle mb-2">
|
||||||
|
<p>Share your goose blog posts or videos with the community.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="text-xs text-textSubtle text-center">
|
||||||
|
Must be hosted on your own website
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ContentCard({ content }): ReactNode {
|
||||||
|
const getTypeIcon = (type: string) => {
|
||||||
|
switch (type) {
|
||||||
|
case 'blog': return '📝';
|
||||||
|
case 'video': return '🎥';
|
||||||
|
case 'tutorial': return '📚';
|
||||||
|
case 'case-study': return '📊';
|
||||||
|
default: return '📄';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatDate = (dateString: string) => {
|
||||||
|
return new Date(dateString).toLocaleDateString('en-US', {
|
||||||
|
month: 'short',
|
||||||
|
day: 'numeric'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="card h-full transition-all duration-200 hover:shadow-lg hover:-translate-y-1">
|
||||||
|
{/* Thumbnail */}
|
||||||
|
<div className="card__image relative">
|
||||||
|
<img
|
||||||
|
src={content.thumbnail || 'https://images.unsplash.com/photo-1516321318423-f06f85e504b3?w=400&h=225&fit=crop&crop=entropy&auto=format'}
|
||||||
|
alt={content.title}
|
||||||
|
className="w-full h-48 object-cover"
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
|
<div className="card__body">
|
||||||
|
<div className="flex items-start gap-2 mb-2">
|
||||||
|
<span className="text-lg">{getTypeIcon(content.type)}</span>
|
||||||
|
<h3 className="text-lg font-semibold line-clamp-2 flex-1">
|
||||||
|
<Link href={content.url} className="text-inherit hover:text-primary">
|
||||||
|
{content.title}
|
||||||
|
</Link>
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Author and Date */}
|
||||||
|
<div className="flex items-center justify-between text-sm text-textSubtle mb-3">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<img
|
||||||
|
src={`https://github.com/${content.author.handle}.png`}
|
||||||
|
alt={content.author.name}
|
||||||
|
className="w-6 h-6 rounded-full"
|
||||||
|
/>
|
||||||
|
<Link href={`https://github.com/${content.author.handle}`} className="hover:text-primary">
|
||||||
|
@{content.author.handle}
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<span>📅 {formatDate(content.submittedDate)}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function StarsCard({contributor}): ReactNode {
|
export function StarsCard({contributor}): ReactNode {
|
||||||
return (
|
return (
|
||||||
<div className={`col ${contributor.totalCount <= 3 ? 'col--4' : 'col--2'} mb-8`}>
|
<div className={`col ${contributor.totalCount <= 3 ? 'col--4' : 'col--2'} mb-8`}>
|
||||||
@@ -260,11 +429,12 @@ export default function Community(): ReactNode {
|
|||||||
return (
|
return (
|
||||||
<Layout
|
<Layout
|
||||||
title="Community"
|
title="Community"
|
||||||
description="Join the Goose community - connect with developers, contribute to the project, and help shape the future of AI-powered development tools."
|
description="Join the goose community - connect with developers, contribute to the project, and help shape the future of AI-powered development tools."
|
||||||
>
|
>
|
||||||
<main className="container">
|
<main className="container">
|
||||||
<UpcomingEventsSection />
|
<UpcomingEventsSection />
|
||||||
<CommunityAllStarsSection />
|
<CommunityAllStarsSection />
|
||||||
|
<CommunityContentSpotlightSection />
|
||||||
</main>
|
</main>
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user