# Help Center Template for React: Search, Topics, Articles

> A React help center template with live highlighted search, topic cards, popular articles, contact options and status, plus when Fumadocs or Nextra fit better.

- Author: [Serban Rusu](https://wingo-ui.com/blog/authors/serban), Founder of Wingo UI
- Published: Nov 6, 2026
- Category: [Build it: screens and apps](https://wingo-ui.com/blog/category/build)
- Reading time: 9 min
- Canonical: https://wingo-ui.com/blog/help-center-template

## TL;DR

A help center template needs a support home whose search answers as you type, topic cards, a short list of popular articles, contact options and a status line, plus an article page with steps, callouts, contents and a Was this helpful? box. Wingo UI's Help Center Page and Help Article Page are those two screens as React components you feed with your own article index and Markdown. For large developer docs with versioning and full-text search, a docs engine such as Nextra or Fumadocs fits better.

Most people who open a help center want one answer and want it before they give up and write to support. A good help center template is built around that: a search that answers while you type, topics for people who browse, the articles everyone reads, and a clear way to a person when the article is not enough. This guide walks through the two screens that make up a React help center, a support home and an article page, with our [Help Center Page](https://wingo-ui.com/templates/help-center-page) and [Help Article Page](https://wingo-ui.com/templates/help-article-page) templates as the example. We sell them, so we are not neutral, but the structure and the pitfalls apply to any React knowledge base template. The last section says when a docs engine or a CMS-backed template is the better tool.

## What does a help center home page need?

Six parts, in this order: a search with live results, a row of common questions, a status line, topic cards, popular articles and a way to reach a person. The help center templates that ranked for this search in November 2026 (ThemeForest kits, the BaseHub template, Notion collections and vendor posts on help center page design) agree on search first and clear categories. Few of them show what happens after the first keystroke, which is where a visitor either finds the answer or opens a ticket. Here is each part in our support home:

- **A big search with live results.** Results appear under the field as you type, grouped by topic, with the matched words marked in each title and summary. The field shows how many articles match.
- **Popular chips under the field.** One tap fills the search with a common question (Invite teammates, Invoices, SSO).
- **A status pill above the title.** A green, amber or red dot with one line of text, linked to your status page. During an outage, that line answers the question most visitors came with.
- **Topic cards** with an article count each, for people who browse.
- **Popular articles**, numbered, the six questions you answer every day.
- **Still need help?** Chat, email and community, each with a fact such as the reply time.

> Live demo (Help Center Page): Type invite, then press Arrow Down and walk the results; type spreadsheet formulas to see the empty state with Contact support. Try it at [Help Center Page](https://wingo-ui.com/templates/help-center-page) and install it with `npx wingo-ui@latest add help-center-page`.

Press `/` anywhere on the page to focus the search. Arrow Down moves into the results, Home and End jump, Enter opens one, and Escape returns to the field. More than five results fold behind Show all (`maxResults`). When nothing matches, the empty state offers Clear search and Contact support, so a failed search ends at a person, never a dead end.

## How do you install the help center template?

Both screens are Pro templates. The CLI copies them with every component they import:

```bash
npx wingo-ui@latest add help-center-page help-article-page
```

The files land in `components/templates/`: `help-center-page.tsx`, `help-article-page.tsx` and a data file each with typed sample content (24 articles in six topics for a fictional product called Acme). You replace that data with yours.

## How do you wire it into a Next.js route?

The page takes plain data: categories, an article index, popular articles and contact options. Several labels, the contact icons and the router link are functions or components, which cannot cross from a server component, and the templates are client components anyway. The clean split is a server route that reads the URL and a small client file that owns the data and the callbacks.

Start with the index. Keep article bodies out of it, since the index ships to the browser for the live search:

```ts
// app/help/content.ts
import { createElement } from "react"
import { CreditCard, Mail, MessageCircle, Rocket } from "lucide-react"
import type {
  HelpCenterArticle,
  HelpCenterCategory,
  HelpCenterContactOption,
} from "@/components/templates/help-center-page-data"

export const CATEGORIES: HelpCenterCategory[] = [
  { value: "getting-started", label: "Getting started", description: "Set up a workspace and invite your team.", icon: createElement(Rocket) },
  { value: "billing", label: "Billing", description: "Plans, invoices, refunds and taxes.", icon: createElement(CreditCard) },
]

export const ARTICLES: HelpCenterArticle[] = [
  {
    slug: "invite-teammates",
    title: "Invite teammates and guests",
    excerpt: "Send invites by email or share a join link. Guests only see the projects you add them to.",
    category: "getting-started",
    minutes: 2,
    updated: "2026-10-30",
    keywords: ["add user", "seat", "join link"],
  },
  {
    slug: "download-an-invoice",
    title: "Download an invoice",
    excerpt: "Every payment has a PDF invoice under Settings, Billing. You can add a company name and tax ID.",
    category: "billing",
    minutes: 1,
    updated: "2026-10-12",
    keywords: ["receipt", "vat", "pdf", "tax id"],
  },
]

export const POPULAR = ARTICLES.slice(0, 6)

export const CONTACT: HelpCenterContactOption[] = [
  { icon: MessageCircle, title: "Chat with us", description: "Talk to the support team from this page.", meta: "Weekdays 9 to 6 ET", action: "Start a chat", href: "/contact?topic=chat" },
  { icon: Mail, title: "Email support", description: "Send the details and a screenshot.", meta: "Replies within one business day", action: "support@example.com", href: "mailto:support@example.com" },
]
```

The client file passes the data, `next/link` and an `onSearch` handler:

```tsx
// app/help/help-center.tsx
"use client"

import Link from "next/link"
import { HelpCenterPage, type HelpCenterPageStatus } from "@/components/templates/help-center-page"
import { ARTICLES, CATEGORIES, CONTACT, POPULAR } from "./content"

export function HelpCenter({ query, status }: { query: string; status: HelpCenterPageStatus }) {
  return (
    <HelpCenterPage
      linkComponent={Link}
      header={false}
      footer={false}
      categories={CATEGORIES}
      articles={ARTICLES}
      popularArticles={POPULAR}
      topics={["Invite teammates", "Invoices", "SSO"]}
      contactOptions={CONTACT}
      defaultQuery={query}
      status={status}
      statusHref="/status"
      labels={{ description: "Guides and answers from the Example support team." }}
      onSearch={(q) => {
        if (q) navigator.sendBeacon("/api/help-search", JSON.stringify({ q }))
      }}
    />
  )
}
```

The route reads `?q=` (in Next.js 16 `searchParams` is a promise) so a link like `/help?q=invoice` opens with results showing:

```tsx
// app/help/page.tsx
import { HelpCenter } from "./help-center"

export default async function HelpRoute({ searchParams }: { searchParams: Promise<{ q?: string }> }) {
  const { q = "" } = await searchParams
  return <HelpCenter query={q} status="operational" />
}
```

Set `header={false}` and `footer={false}` when the route sits inside your site layout; leave them on for a standalone support site. `design` switches the whole look between `classic`, `bold` and `minimal`.

## How does the search decide what matches?

This is the part worth understanding before you write articles. Every typed word must appear in the article's title, excerpt, topic name or `keywords`, and title matches rank first. Case and accents do not matter. The body is never searched.

That has two consequences. First, the `keywords` field is where you win or lose a search. Customers type "receipt" when your article says "invoice", and "add user" when it says "invite teammates". Put those words in `keywords`. Second, log what people search for. `onSearch` fires once typing pauses, on Enter and when a chip is picked, so the beacon above gives you a list of real queries. Because it also fires on every pause, the log holds partial words such as "inv" next to "invoice": keep the longest query per visitor session before you count them. The queries that end in a contact click are the articles you have not written yet.

The local search is fine for a few hundred articles, since the index is small. When you need full-text search over bodies or thousands of articles, put a server search behind the [Global Search](https://wingo-ui.com/components/global-search) component, which takes `loadResults(query, { signal, scope })`, debounces it, aborts stale requests and groups the answers. The smaller [Search Input](https://wingo-ui.com/components/search-input) is the field on its own. For an app-wide palette, see our [React command palette guide](https://wingo-ui.com/blog/react-command-palette).

## What goes on a help article page?

A help article template has one job: get the reader through the steps and catch them when they get stuck. The article page renders one Markdown article: a breadcrumb back to the help center and the topic, a search bar, a sidebar with the topic's other articles, the body, a table of contents, Was this article helpful?, a contact card and related articles.

> Live demo (Help Article Page): Scroll the article: the contents rail marks the section you are reading. Press No under Was this article helpful? to open the comment box. Try it at [Help Article Page](https://wingo-ui.com/templates/help-article-page) and install it with `npx wingo-ui@latest add help-article-page`.

The body goes through the [Markdown](https://wingo-ui.com/components/markdown) component with two additions. A GitHub-style alert quote becomes a callout, and inline code that starts with `kbd:` becomes a key cap that shows the right modifier for the device:

```md
1. Open the task, or create one with `kbd:c`.
2. Click **Repeat** next to the due date.

> [!TIP]
> Already on the task? Press `kbd:shift+r` to open the Repeat menu.
```

The [Table of Contents](https://wingo-ui.com/components/table-of-contents) builds itself from the body's `##` and `###` headings. It sticks on the right from 1280px and becomes a pill under the header below that. The topic sidebar becomes a bottom sheet below 1024px.

Wire it with a static route that reads the Markdown on the server:

```tsx
// app/help/[slug]/page.tsx
import { readFile } from "node:fs/promises"
import path from "node:path"
import { notFound, redirect } from "next/navigation"
import { ARTICLES, CATEGORIES } from "../content"
import { HelpArticleView } from "./help-article"

export const dynamicParams = false

export function generateStaticParams() {
  return [...ARTICLES.map((a) => ({ slug: a.slug })), ...CATEGORIES.map((c) => ({ slug: c.value }))]
}

export default async function Page({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params
  const topic = CATEGORIES.find((c) => c.value === slug)
  if (topic) redirect(`/help?q=${encodeURIComponent(topic.label)}`)
  const meta = ARTICLES.find((a) => a.slug === slug)
  if (!meta) notFound()
  const body = await readFile(path.join(process.cwd(), "content/help", `${slug}.md`), "utf8")
  return <HelpArticleView article={{ ...meta, body }} />
}
```

```tsx
// app/help/[slug]/help-article.tsx
"use client"

import Link from "next/link"
import { HelpArticlePage } from "@/components/templates/help-article-page"
import type { HelpArticle } from "@/components/templates/help-article-page-data"
import { ARTICLES, CATEGORIES } from "../content"

export function HelpArticleView({ article }: { article: HelpArticle }) {
  const related = ARTICLES.filter((a) => a.category === article.category && a.slug !== article.slug).slice(0, 3)
  return (
    <HelpArticlePage
      linkComponent={Link}
      header={false}
      footer={false}
      article={article}
      articles={ARTICLES}
      categories={CATEGORIES}
      relatedArticles={related}
      supportEmail="support@example.com"
      onFeedback={(helpful, comment) =>
        fetch("/api/help-feedback", {
          method: "POST",
          body: JSON.stringify({ slug: article.slug, helpful, comment }),
        })
      }
    />
  )
}
```

## Which pitfalls should you avoid?

- **Topics and articles share one URL space.** Topic cards link to `/help/<value>` and articles to `/help/<slug>`, so a topic called `billing` and an article called `billing` collide. Keep them distinct. The kit has no topic listing screen; the redirect above sends a topic to the search, which matches the topic name and lists its articles grouped.
- **`onFeedback` runs twice on No.** Once when the reader presses No and again with the comment. Store one row per reader and article, and update it.
- **A status pill that lies is worse than none.** Pass the real state from your monitor, or set `showStatus={false}`. Our [Next.js status page tutorial](https://wingo-ui.com/blog/nextjs-status-page) and the [Status Page template](https://wingo-ui.com/templates/status-page) cover the page it links to.
- **Long excerpts bury the results.** One or two sentences, written as the answer, not as a teaser.

On phones the topic chips scroll sideways, cards stack to one column, and every target is 44px on touch screens.

## When is Nextra, Fumadocs or a ready-made kit a better fit?

A help center template answers support questions. Developer documentation is a different job, usually better served by a docs website template or framework, and the tools below were checked on November 6, 2026:

| Option | What it is | Search | Fits when |
|---|---|---|---|
| Wingo UI Help Center + Help Article | Two React screens, your data as props | Live, over titles, excerpts, topics, keywords | Customer support for a SaaS product |
| [Nextra 4](https://the-guild.dev/blog/nextra-4) | Docs and blog framework on Next.js, App Router only | [Pagefind](https://nextra.site/docs/guide/search), indexed after the build, full text | MDX docs on Next.js |
| [Fumadocs](https://fumadocs.dev/docs) | Docs framework for Next.js, React Router, TanStack Start, Waku and Astro | Built into its core | Large docs, any React framework |
| [BaseHub Help Center Template](https://docs.basehub.com/templates-and-examples/templates/help-center-template) | Next.js help center whose articles you edit in the BaseHub CMS | Full text, per its docs | Support writers want a CMS editor instead of Markdown files |
| [Docy on ThemeForest](https://themeforest.net/item/docy-react-documentation-knowledge-base-site-template/61091004) | Next.js docs, knowledge base and forum template on Bootstrap 5 | Not described on the listing | A one-off site; $29 regular license, last updated December 29, 2025 |
| [Frontkit Help Desk Kit](https://thefrontkit.com/docs/help-desk-kit/getting-started) | 110 agent-side screens (tickets, chat, knowledge base editor), UI only | Not described on the docs page | You are building the help desk itself |

Pick Nextra or Fumadocs when you have hundreds of MDX pages, an API reference or versions; they search the whole text and give you navigation for free. Pick the BaseHub template when non-developers write the articles and full-text search matters more than owning the data layer. Pick a help desk kit when your product is the support tool. For a docs portal home in front of your docs, our [Docs Home Page](https://wingo-ui.com/templates/docs-home-page) has a search palette, quick starts and API samples. For fewer than about 30 questions, a single [FAQ Page](https://wingo-ui.com/templates/faq-page) is enough, and it is free.

More screens like this are in [Build it: screens and apps](https://wingo-ui.com/blog/category/build), and the [SaaS website template guide](https://wingo-ui.com/blog/saas-website-template) shows where the help center sits among the other pages of a product site. Its closest neighbor is the [changelog page template](https://wingo-ui.com/blog/changelog-page-template), which answers "is this fixed yet?" before anyone opens a ticket.

## Where do you start?

Open the [Help Center Page](https://wingo-ui.com/templates/help-center-page) and type a few searches, then swap its sample data for ten of your own articles with honest keywords. Both screens are part of Wingo UI Pro, from $8 a month ([pricing](https://wingo-ui.com/pricing)); if a single support page is enough for now, start with the free FAQ Page.

## Components in this post

- [Help Center Page](https://wingo-ui.com/templates/help-center-page) (Pro): A support home: live search with grouped, highlighted results, topic chips, category cards, popular articles, contact options and status. Install: `npx wingo-ui@latest add help-center-page`
- [Help Article Page](https://wingo-ui.com/templates/help-article-page) (Pro): One support article: search, a topic sidebar, a Markdown body with steps and callouts, contents and helpful feedback. Install: `npx wingo-ui@latest add help-article-page`
- [Global Search](https://wingo-ui.com/components/global-search) (Pro): A React global search bar for an app header: grouped results from every entity as you type, scopes, recents and suggestions, full screen on phones. Install: `npx wingo-ui@latest add global-search`
- [FAQ Page](https://wingo-ui.com/templates/faq-page) (Free): A React FAQ page template: a big search, topic cards with counts, 21 answers in five categories, help options and a call to action. Install: `npx wingo-ui@latest add faq-page`

## FAQ

### What should a help center home page include?

A search field that shows results as you type, topic cards with article counts, the five or six most read articles, ways to reach a person (chat, email, community) and the current system status. Anything else pushes the search down the page.

### What is the difference between a help center, a knowledge base and an FAQ page?

A knowledge base is the set of articles; a help center is the public site around it, with search, topics and contact options. An FAQ page is one page of short answers, and it is enough while you have fewer than about 30 questions.

### Does the Wingo UI help center search the full article text?

No. It matches every typed word against the title, excerpt, topic name and keywords of each article, and ranks title matches first. For full-text search across bodies, use a server search behind the Global Search component or a docs engine with a build-time index such as Pagefind.

### Should I use Nextra or Fumadocs instead of a help center template?

Use one of them when the content is developer documentation: hundreds of MDX pages, an API reference, versions and search over the whole text. A help center template fits customer support content where the job is to answer a question fast and offer a person when the article does not.

### Is the Wingo UI help center template free?

No, the Help Center Page and the Help Article Page are part of Wingo UI Pro. The FAQ Page template is free and covers a smaller support page with search, topics and contact cards.

---

Source: https://wingo-ui.com/blog/help-center-template
