@fumh_terol/payload-plugin-wiki
v1.0.3
Published
Wiki plugin for Payload CMS - FAQs and Guides with visibility-based access control and modular frontend components
Maintainers
Readme
@fumh_terol/payload-plugin-wiki
Wiki plugin for Payload CMS — FAQs and Guides with visibility-based access control and modular frontend components.
Installation
npm install @fumh_terol/payload-plugin-wikiQuick Start
// payload.config.ts
import { wikiPlugin } from '@fumh_terol/payload-plugin-wiki'
import { buildConfig } from 'payload'
export default buildConfig({
plugins: [
wikiPlugin({
userSlug: 'users',
mediaSlug: 'media',
roleOptions: [
{ label: 'Admin', value: 'admin' },
{ label: 'Editor', value: 'editor' },
{ label: 'Premium', value: 'premium' },
],
}),
],
})Configuration
interface WikiConfig {
enabled?: boolean // Enable/disable entire plugin (default: true)
userSlug?: string // Users collection slug (default: 'users')
mediaSlug?: string // Media collection slug (default: 'media')
roleOptions?: Array<{ // Roles for visibility filtering
label: string
value: string
}>
faqs?: {
enabled?: boolean // Enable FAQs collection (default: true)
slug?: string // Collection slug (default: 'wiki-faqs')
overrides?: Partial<CollectionConfig>
}
guides?: {
enabled?: boolean // Enable Guides collection (default: true)
slug?: string // Collection slug (default: 'wiki-guides')
overrides?: Partial<CollectionConfig>
}
}Collections
FAQs (wiki-faqs)
| Field | Type | Description |
|-------|------|-------------|
| question | text (required) | The FAQ question |
| answer | richText (required) | Rich text answer |
| visibility | select | everyone / specific_users / specific_roles |
| visibleUsers | relationship (hasMany) | Users who can view (when specific_users) |
| visibleRoles | select (hasMany) | Roles who can view (when specific_roles) |
| category | text | Group FAQs by category |
| order | number | Sort order |
| slug | text | Auto-generated from question |
Guides (wiki-guides)
| Field | Type | Description |
|-------|------|-------------|
| title | text (required) | Guide title |
| excerpt | textarea | Short summary for listings |
| content | richText (required) | Full content with Lexical editor |
| attachments | array | File attachments with labels |
| visibility | select | everyone / specific_users / specific_roles |
| visibleUsers | relationship (hasMany) | Users who can view |
| visibleRoles | select (hasMany) | Roles who can view |
| category | text | Group guides by category |
| order | number | Sort order |
| status | select | draft / published |
| slug | text | Auto-generated from title |
Access Control
Each FAQ and Guide has three visibility modes:
| Mode | Behavior |
|------|----------|
| everyone | Public — no authentication required |
| specific_users | Only selected users can view |
| specific_roles | Only users with a matching role can view |
Admin users can always create, update, and delete content.
Frontend Components
Import from @fumh_terol/payload-plugin-wiki/client:
import {
WikiLayout,
WikiFAQList,
WikiFAQItem,
WikiGuideList,
WikiGuideCard,
WikiGuideContent,
WikiSidebar,
WikiSearchBar,
WikiEmptyState,
} from '@fumh_terol/payload-plugin-wiki/client'WikiLayout
Main wrapper with sidebar support.
<WikiLayout
sidebar={<WikiSidebar categories={cats} onCategoryChange={setCat} />}
sidebarPosition="left" // 'left' | 'right'
maxWidth="xl" // 'sm' | 'md' | 'lg' | 'xl' | 'full'
className="py-12"
>
{/* content */}
</WikiLayout>WikiFAQList
<WikiFAQList
faqs={faqData}
layout="accordion" // 'accordion' | 'list' | 'simple'
category="billing" // Filter by category
searchQuery={query} // Filter by search term
className="rounded-lg shadow"
renderAnswer={(faq) => <CustomRenderer data={faq.answer} />}
/>WikiGuideList
<WikiGuideList
guides={guideData}
layout="grid" // 'grid' | 'list' | 'compact'
columns={3} // 1 | 2 | 3 | 4 (grid mode)
category="tutorials"
searchQuery={query}
showExcerpt={true}
onGuideClick={(guide) => router.push(`/guides/${guide.slug}`)}
/>WikiGuideCard
<WikiGuideCard
guide={guide}
layout="grid"
showExcerpt={true}
href={`/guides/${guide.slug}`}
onClick={(guide) => handleClick(guide)}
/>WikiGuideContent
<WikiGuideContent
guide={guide}
showAttachments={true}
showCategory={true}
showMeta={true}
renderContent={(guide) => <LexicalRenderer data={guide.content} />}
onBack={() => router.back()}
/>WikiSidebar
<WikiSidebar
categories={['Getting Started', 'Billing', 'API']}
activeCategory={currentCategory}
onCategoryChange={setCategory}
onSearch={handleSearch}
showSearch={true}
showCategories={true}
title="Knowledge Base"
/>WikiSearchBar
<WikiSearchBar
onSearch={(query) => fetchResults(query)}
placeholder="Search guides..."
debounceMs={300}
/>WikiEmptyState
<WikiEmptyState
title="No guides yet"
description="Check back soon for new content."
action={<a href="/admin">Create a guide</a>}
/>Data Fetching
Fetch data server-side and pass as props:
// app/guides/page.tsx
import { getPayload } from 'payload'
import config from '@payload-config'
import { WikiGuideList, WikiLayout } from '@fumh_terol/payload-plugin-wiki/client'
export default async function GuidesPage() {
const payload = await getPayload({ config })
const { docs: guides } = await payload.find({
collection: 'wiki-guides',
where: { status: { equals: 'published' } },
sort: '-updatedAt',
overrideAccess: false, // Enforces visibility rules per user
})
const data = JSON.parse(JSON.stringify(guides))
return (
<WikiLayout maxWidth="xl">
<WikiGuideList guides={data} layout="grid" columns={3} />
</WikiLayout>
)
}TypeScript
import type {
WikiConfig,
WikiFAQ,
WikiGuide,
VisibilityMode,
} from '@fumh_terol/payload-plugin-wiki/types'License
MIT
