vitepress-plugin-feedback-tracker
v0.1.1-alpha.0
Published
Low-friction feedback widget for VitePress — thumbs up/down, category, optional comment
Maintainers
Readme
vitepress-plugin-feedback-tracker
VitePress plugin that adds a low-friction feedback widget to documentation pages. Readers vote helpful / not helpful, pick a category, and optionally leave a comment or email.
Pairs with @vitepress-feedback/api — a Void-powered API that stores submissions.
Install
vp add vitepress-plugin-feedback-trackerPeer dependencies: vitepress ^2.0.0-alpha.1, vue ^3.4.
Setup
Wire the plugin into your theme and mount the widgets in your layout.
.vitepress/theme/index.ts
import DefaultTheme from "vitepress/theme";
import type { Theme } from "vitepress";
import { feedbackPlugin } from "vitepress-plugin-feedback-tracker";
import "vitepress-plugin-feedback-tracker/style.css";
import Layout from "./Layout.vue";
const theme: Theme = {
extends: DefaultTheme,
Layout,
enhanceApp(ctx) {
const feedback = feedbackPlugin({
siteId: "my-docs",
apiUrl: "https://feedback.example.com",
});
feedback.enhanceApp?.(ctx);
},
};
export default theme;.vitepress/theme/Layout.vue
<script setup lang="ts">
import DefaultTheme from "vitepress/theme";
import { useData } from "vitepress";
import { computed } from "vue";
const { Layout } = DefaultTheme;
const { frontmatter } = useData();
const isDoc = computed(
() => frontmatter.value.layout === undefined || frontmatter.value.layout === "doc",
);
</script>
<template>
<Layout>
<template v-if="isDoc" #doc-after>
<FeedbackWidget />
</template>
<template v-if="isDoc" #aside-outline-after>
<FeedbackWidgetCompact />
</template>
</Layout>
</template>siteId must be registered in the API's ALLOWED_ORIGINS map, otherwise submissions are rejected.
Configuration
interface FeedbackConfig {
/** Site identifier — must match a key in the API's ALLOWED_ORIGINS */
siteId: string;
/** Base URL of the deployed feedback API */
apiUrl: string;
}Components
Both are auto-registered globally by feedbackPlugin(); no props.
<FeedbackWidget />
Full widget — thumbs up/down → category chips → optional comment + email → submit. Meant for the bottom of doc content (e.g. VitePress #doc-after slot).
<FeedbackWidgetCompact />
Compact variant — thumbs up/down → category chips only. Meant for the sidebar (e.g. #aside-outline-after slot). If the reader picks "Other", the compact widget hands off to the full widget (scrolling into view and pre-selecting the category) so they can add a required comment.
Both widgets share per-page state: voting on one updates the other, and a page only ever asks once.
Submission flow
- Reader clicks 👍 or 👎 →
POST /api/submit— rating is recorded immediately and the widget gets back a single-useupdateToken. - Widget expands to show category chips (positive or negative set, depending on the vote).
- Reader picks a category (required). "Other" requires a comment; everything else makes the comment + email fields optional.
- Reader submits →
PATCH /api/submit/:idupdates the entry with category / comment / email. Abandoning at this step is fine — the rating is already saved.
If the API is unreachable the widget hides itself rather than rendering in a broken state.
Composable
For custom UIs, useFeedback exposes the same state and actions the built-in widgets use:
import { useFeedback } from "vitepress-plugin-feedback-tracker";
import { useData } from "vitepress";
const { page: pageData } = useData();
const { state, vote, submitDetails, submitError, fieldErrors, skip, retry, restart } = useFeedback(
() => pageData.value.relativePath,
);state—"idle" | "voting" | "voted" | "submitting" | "submitted" | "error"vote(helpful: boolean)— initial POSTsubmitDetails({ category, comment?, email? })— PATCH with detailsfieldErrors— reactive map of server-side validation errors keyed by field
Styling
Import vitepress-plugin-feedback-tracker/style.css once (see setup). All styles are scoped under .vf-* class names so they won't leak into your theme.
Accessibility
- Thumbs buttons have descriptive
aria-labels. - Category chips are keyboard-navigable.
- Focus is moved into the category chips after voting so keyboard users aren't stranded.
License
MIT
