@faqapp/react
React hooks and SSR helpers. Wraps @faqapp/core with cache + suspense.
Updated 2026-10-10
bun add @faqapp/react @faqapp/core
@faqapp/react adds React hooks and SSR helpers on top of @faqapp/core. Same auth, same envelope, same types.
Provider
Wrap your tree once:
import { createFAQClient, FAQClientProvider } from "@faqapp/react";
const faq = createFAQClient({
organizationSlug: "acme",
apiKey: import.meta.env.VITE_FAQAPP_PUBLISHABLE_KEY
});
export function App({ children }) {
return <FAQClientProvider client={faq}>{children}</FAQClientProvider>;
}
In browser code, use a publishable key. It reads published FAQs and search only, so useSearch works and nothing private can leak. useFaq and useQuestion read the questions endpoint, which needs a server key: call them only where the key stays on a server, or render published FAQs with faq.faqs.list() instead. Never ship a read key to the browser; it reads drafts.
Hooks
import { useFaq } from "@faqapp/react";
function QuestionList() {
const { data, loading, error } = useFaq({ limit: 20 });
if (loading) return <div>Loading…</div>;
if (error) return <div>{error.message}</div>;
return data?.map((q) => (
<article key={q.id}>
<h2>{q.question}</h2>
<p>{q.answer}</p>
</article>
));
}
Hooks return { data, loading, error, refetch }. Calls are cached per-arg-shape; identical calls in the same render reuse the response.
Shipped components
For drop-in surfaces:
import { FaqList } from "@faqapp/react";
<FaqList limit={20} className="my-faq" />
<FaqList> is unstyled markup with className hooks; bring your own styles. Useful when you want the data flow but not the visual decisions.
Migration from @faqapp/nextjs
@faqapp/nextjs is deprecated. The migration path:
- import { useFaq } from "@faqapp/nextjs/hooks";
+ import { useFaq } from "@faqapp/react";
API surface is identical. The Next-specific server helpers map 1:1 to TanStack Start server functions or a thin server-only wrapper around @faqapp/core.