网站正在建设中...
;
NextDocs
Additional Features

Feedback

Receive feedback from your users

Overview

Feedback is crucial for knowing what your reader thinks, and help you to further improve documentation content.

Installation

Fumadocs CLI

npx @fumadocs/cli@latest add feedback

Shadcn CLI

npx shadcn@latest add https://fumadocs.dev/r/feedback.json

Usage

Now add the <Feedback /> component to your docs page:

import { DocsPage } from 'fumadocs-ui/page';
import { Feedback } from '@/components/feedback';
import posthog from 'posthog-js';

export default async function Page() {
  return (
    <DocsPage>
      {/* at the bottom of page */}
      <Feedback
        onRateAction={async (url, feedback) => {
          'use server';

          await posthog.capture('on_rate_docs', feedback);
        }}
      />
    </DocsPage>
  );
}
  • onRateAction: fired when user submit feedback.

You can specify a server action, or any function (in client component). Such as reporting user feedback as a on_rate_docs event on PostHog.

Integrating with GitHub Discussion

To report your feedback to GitHub Discussion, make a custom onRateAction.

You can copy this server action as a starting point:

import { App, Octokit } from 'octokit';
import type { ActionResponse, Feedback } from '@/components/feedback';

export const repo = 'fumadocs';
export const owner = 'fuma-nama';
export const DocsCategory = 'Docs Feedback';

let instance: Octokit | undefined;

async function getOctokit(): Promise<Octokit> {
  if (instance) return instance;
  const appId = process.env.GITHUB_APP_ID;
  const privateKey = process.env.GITHUB_APP_PRIVATE_KEY;

  if (!appId || !privateKey) {
    throw new Error(
      'No GitHub keys provided for Github app, docs feedback feature will not work.',
    );
  }

  const app = new App({
    appId,
    privateKey,
  });

  const { data } = await app.octokit.request(
    'GET /repos/{owner}/{repo}/installation',
    {
      owner,
      repo,
      headers: {
        'X-GitHub-Api-Version': '2022-11-28',
      },
    },
  );

  instance = await app.getInstallationOctokit(data.id);
  return instance;
}

interface RepositoryInfo {
  id: string;
  discussionCategories: {
    nodes: {
      id: string;
      name: string;
    }[];
  };
}

let cachedDestination: RepositoryInfo | undefined;
async function getFeedbackDestination() {
  if (cachedDestination) return cachedDestination;
  const octokit = await getOctokit();

  const {
    repository,
  }: {
    repository: RepositoryInfo;
  } = await octokit.graphql(`
  query {
    repository(owner: "${owner}", name: "${repo}") {
      id
      discussionCategories(first: 25) {
        nodes { id name }
      }
    }
  }
`);

  return (cachedDestination = repository);
}

// Client-side function for static export
export async function onRateAction(
  url: string,
  feedback: Feedback,
): Promise<ActionResponse> {
  const response = await fetch('/api/feedback', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ url, feedback }),
  });

  if (!response.ok) {
    throw new Error('Failed to submit feedback');
  }

  const result = await response.json();

  if (result.type === 'error') {
    throw new Error(result.message);
  }

  return {
    message: result.message,
  };
}
  • Create your own GitHub App and obtain its app ID and private key.
  • Fill required environment variables.
  • Replace constants like owner, repo, and DocsCategory.

这篇文章怎么样?

Last updated on