Next.js SDK
Next.js integration for TheFAQApp — @faq/nextjs
Next.js SDK (@faq/nextjs)
React hooks, components, SSR/SSG helpers, and SEO utilities for Next.js.
Re-exports everything from @faq/sdk, so you only need one package.
Install
npm install @faq/nextjsHooks
useFaq — List & Filter Questions
'use client';
import { useFaq } from '@faq/nextjs';
export function FAQList() {
const { data, loading, error, updateFilters } = useFaq({
config: {
apiKey: process.env.NEXT_PUBLIC_FAQ_API_KEY!,
organizationSlug: 'my-org',
},
initialFilters: { limit: 10, category: 'getting-started' },
});
if (loading) return <div>Loading...</div>;
return (
<div>
<input onChange={e => updateFilters({ search: e.target.value })} />
{data.questions.map(q => (
<article key={q.id}>
<h3>{q.question}</h3>
<div dangerouslySetInnerHTML={{ __html: q.answer }} />
</article>
))}
</div>
);
}useQuestion — Single Question with Feedback
'use client';
import { useQuestion } from '@faq/nextjs';
export function QuestionPage({ slug }: { slug: string }) {
const { data, loading, submitFeedback } = useQuestion({
config: { apiKey: '...', organizationSlug: 'my-org' },
questionSlug: slug,
});
if (loading || !data.question) return null;
return (
<div>
<h1>{data.question.question}</h1>
<div dangerouslySetInnerHTML={{ __html: data.question.answer }} />
<button onClick={() => submitFeedback({ helpful: true })}>👍</button>
<button onClick={() => submitFeedback({ helpful: false })}>👎</button>
</div>
);
}useSearch — Search with Debouncing
'use client';
import { useSearch } from '@faq/nextjs';
export function SearchBar() {
const { data, loading, search } = useSearch({
config: { apiKey: '...', organizationSlug: 'my-org' },
});
return (
<div>
<input onChange={e => search(e.target.value)} placeholder="Search FAQ..." />
{data.questions.map(q => (
<a key={q.id} href={`/faq/${q.slug}`}>{q.question}</a>
))}
</div>
);
}Server Components
Use @faq/sdk directly in Server Components:
import { createFaqClient } from '@faq/nextjs';
export default async function FAQPage() {
const client = createFaqClient({
apiKey: process.env.FAQ_API_KEY!,
organizationSlug: 'my-org',
});
const { questions } = await client.getFaq({ limit: 50 });
return (
<ul>
{questions.map(q => <li key={q.id}>{q.question}</li>)}
</ul>
);
}SEO Utilities
FAQ Structured Data (JSON-LD)
import { generateFaqSeoData } from '@faq/nextjs';
export async function generateMetadata() {
const client = createFaqClient({ ... });
const { questions } = await client.getFaq();
return generateFaqSeoData(questions, organization);
}Question Structured Data
import { generateQuestionSeoData } from '@faq/nextjs';
const metadata = generateQuestionSeoData(question, organization);Sitemap Generation
import { generateFaqSitemap, generateSitemapXml } from '@faq/nextjs';
const entries = generateFaqSitemap(questions, categories, {
baseUrl: 'https://example.com',
organizationSlug: 'my-org',
});
const xml = generateSitemapXml(entries);Pre-built Components
<FaqList />
Full FAQ list with search, category filtering, and pagination.
import { FaqList } from '@faq/nextjs/components';
<FaqList
config={{ apiKey: '...', organizationSlug: 'my-org' }}
showSearch
showCategories
/><QuestionDetail />
Question view with feedback buttons.
import { QuestionDetail } from '@faq/nextjs/components';
<QuestionDetail
config={{ apiKey: '...', organizationSlug: 'my-org' }}
questionSlug="how-to-cancel"
/>