@mounaji_npm/forum-landing
v0.1.0
Published
Landing page template for community forums — hero, features, post preview, and CTA sections
Maintainers
Readme
@mounaji_npm/forum-landing
Landing page template for community forums. Drop-in hero section, features grid, stats strip, recent posts preview, and sign-up CTA — all token-driven, no external dependencies.
Pair with @mounaji_npm/forum for a complete community platform.
Install
npm install @mounaji_npm/tokens @mounaji_npm/forum-landingWhat's included
| Export | Description |
|---|---|
| ForumLandingPage | Full landing page (hero + features + stats + posts + CTA) |
| HeroSection | Gradient headline + two CTA buttons + background glow |
| FeaturesGrid | Responsive grid of feature cards |
| StatsRow | Full-width stats strip (3–4 numbers) |
| PostsPreview | Recent discussions list |
| CTASection | Final gradient call-to-action block |
All sections are individually exported so you can compose a custom layout.
Quick Start
Drop-in full page
import { ForumLandingPage } from '@mounaji_npm/forum-landing';
export default function HomePage() {
return (
<ForumLandingPage
name="DevHub Community"
tagline="Where developers ask questions, share knowledge, and build together."
primaryCTA={{ label: 'Join the Community', onClick: () => router.push('/signup') }}
secondaryCTA={{ label: 'Browse Discussions', onClick: () => router.push('/forum') }}
ctaAction={{ label: 'Get Started Free', onClick: () => router.push('/signup') }}
/>
);
}Next.js App Router
// app/page.js
'use client';
import { useRouter } from 'next/navigation';
import { ForumLandingPage } from '@mounaji_npm/forum-landing';
export default function HomePage() {
const router = useRouter();
return (
<ForumLandingPage
name="My Community"
tagline="Ask questions. Share knowledge. Build together."
primaryCTA={{ label: 'Join Free', onClick: () => router.push('/signup') }}
secondaryCTA={{ label: 'Browse Discussions', onClick: () => router.push('/forum') }}
ctaAction={{ label: 'Get Started', onClick: () => router.push('/signup') }}
/>
);
}Vite + React
import { useNavigate } from 'react-router-dom';
import { TokensProvider } from '@mounaji_npm/tokens';
import { ForumLandingPage } from '@mounaji_npm/forum-landing';
export default function HomeRoute() {
const navigate = useNavigate();
return (
<TokensProvider>
<ForumLandingPage
name="My Community"
tagline="Ask questions. Share knowledge. Build together."
primaryCTA={{ label: 'Join Free', onClick: () => navigate('/signup') }}
secondaryCTA={{ label: 'Browse Discussions', onClick: () => navigate('/forum') }}
ctaAction={{ label: 'Get Started', onClick: () => navigate('/signup') }}
/>
</TokensProvider>
);
}ForumLandingPage Props
| Prop | Type | Default | Description |
|---|---|---|---|
| name | string | 'Your Community' | Brand name — displayed as gradient headline |
| tagline | string | built-in | One-liner below the headline |
| description | string | — | Optional body text below tagline |
| primaryCTA | { label, onClick } | { label: 'Join the Community' } | Primary hero button |
| secondaryCTA | { label, onClick } | { label: 'Browse Discussions' } | Ghost hero button |
| features | Feature[] | 6 built-in features | Feature cards in the grid |
| stats | Stat[] | 3 built-in stats | Numbers in the stats strip |
| previewPosts | Post[] | 4 demo posts | Posts shown in the preview section |
| ctaTitle | string | built-in | CTA section headline |
| ctaSubtitle | string | built-in | CTA section subtext |
| ctaAction | { label, onClick } | built-in | CTA section button |
| isDark | boolean | true | Dark / light theme |
| style | CSSProperties | — | Root element style override |
Individual Sections
Import and compose sections independently:
import {
HeroSection,
FeaturesGrid,
StatsRow,
PostsPreview,
CTASection,
} from '@mounaji_npm/forum-landing';HeroSection
<HeroSection
name="DevHub"
tagline="Where developers connect."
primaryCTA={{ label: 'Get Started', onClick: () => {} }}
secondaryCTA={{ label: 'Learn More', onClick: () => {} }}
isDark
/>| Prop | Type | Description |
|---|---|---|
| name | string | Brand name (gradient text) |
| tagline | string | Subtitle text |
| description | string | Optional body paragraph |
| primaryCTA | { label, onClick } | Gradient fill button |
| secondaryCTA | { label, onClick } | Ghost outline button |
| isDark | boolean | Theme |
FeaturesGrid
<FeaturesGrid
features={[
{ icon: '💬', title: 'Threaded Discussions', description: 'Organized replies keep conversations readable.' },
{ icon: '▲', title: 'Community Voting', description: 'Best answers rise to the top automatically.' },
{ icon: '🔍', title: 'Full-text Search', description: 'Find any post or reply in seconds.' },
{ icon: '🏷', title: 'Tags & Categories', description: 'Structured navigation for any topic.' },
]}
isDark
/>Each feature:
| Field | Type | Description |
|---|---|---|
| icon | string | Emoji icon |
| title | string | Feature name |
| description | string | One-sentence description |
StatsRow
<StatsRow
stats={[
{ icon: '💬', value: '12,400+', label: 'Posts published' },
{ icon: '👥', value: '3,200+', label: 'Community members' },
{ icon: '✓', value: '89%', label: 'Questions answered' },
]}
isDark
/>PostsPreview
Shows a compact list of recent discussions. Pass your live post data from an API:
import useSWR from 'swr';
import { PostsPreview } from '@mounaji_npm/forum-landing';
function RecentDiscussions() {
const { data } = useSWR('/api/posts?limit=5', fetcher);
return (
<PostsPreview
posts={(data ?? []).map(p => ({
title: p.title,
category: p.category.label,
icon: p.category.icon,
votes: p.votes,
replies: p.replyCount,
solved: p.isSolved,
}))}
onViewAll={() => router.push('/forum')}
isDark
/>
);
}Post shape for PostsPreview (simplified — no full Post object needed):
| Field | Type | Description |
|---|---|---|
| title | string | Post title |
| category | string | Category label |
| icon | string | Category emoji |
| votes | number | Vote count |
| replies | number | Reply count |
| solved | boolean | Show "Solved" badge |
CTASection
<CTASection
title="Ready to join the conversation?"
subtitle="Ask questions, share knowledge, and connect with your community."
action={{ label: 'Get Started Free', onClick: () => router.push('/signup') }}
isDark
/>Combining with @mounaji_npm/forum
The recommended full setup puts the landing page at / and the forum at /forum:
// Next.js: two separate page files
// app/page.js → ForumLandingPage
// app/forum/page.js → ForumPage
// Vite: two routes
<Routes>
<Route path="/" element={<HomeRoute />} />
<Route path="/forum" element={<ForumRoute />} />
</Routes>Customizing content
Override any section's built-in copy:
<ForumLandingPage
name="Acme Developers"
tagline="Build faster. Ask smarter. Ship together."
features={[
{ icon: '🚀', title: 'Fast Answers', description: 'Get replies from the community within minutes.' },
{ icon: '📚', title: 'Knowledge Base', description: 'Every solved thread becomes a searchable resource.' },
{ icon: '🔒', title: 'Private Channels', description: 'Create invite-only spaces for your team.' },
]}
stats={[
{ icon: '💬', value: '500+', label: 'Active discussions' },
{ icon: '👥', value: '200+', label: 'Team members' },
{ icon: '⚡', value: '< 2h', label: 'Avg. response time' },
]}
ctaTitle="Your community is waiting."
ctaSubtitle="Join 200+ engineers already on the platform."
ctaAction={{ label: 'Request Access', onClick: handleSignup }}
/>Theming
import { TokensProvider } from '@mounaji_npm/tokens';
import { ForumLandingPage } from '@mounaji_npm/forum-landing';
// Custom brand colors
<TokensProvider initialTokens={{
colorPrimary: '#7C3AED',
colorAccent: '#06B6D4',
}}>
<ForumLandingPage name="MyBrand" />
</TokensProvider>
// Light mode
<ForumLandingPage isDark={false} name="MyBrand" />