npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@86d-app/faq

v0.0.25

Published

FAQ and knowledge base module for 86d commerce platform

Downloads

825

Readme

[!WARNING] This project is under active development and is not ready for production use. Please proceed with caution. Use at your own risk.

FAQ Module

Self-service FAQ and knowledge base module. Organize questions into categories, enable full-text search, and let customers vote on helpfulness.

Installation

npm install @86d-app/faq

Usage

import faq from "@86d-app/faq";

const module = faq({
  maxSearchResults: 20,
});

Configuration

| Option | Type | Default | Description | |---|---|---|---| | maxSearchResults | number | 20 | Maximum results returned per search query |

Store Endpoints

| Method | Path | Description | |---|---|---| | GET | /faq/categories | List all visible FAQ categories | | GET | /faq/categories/:slug | Get a category with its visible items | | GET | /faq/items/:slug | Get a single FAQ item by slug | | GET | /faq/search?q=... | Search FAQs by query string | | POST | /faq/items/:id/vote | Vote on helpfulness ({ helpful: boolean }) |

Admin Endpoints

| Method | Path | Description | |---|---|---| | GET | /admin/faq/categories | List all categories with item counts | | POST | /admin/faq/categories/create | Create a new category | | PUT | /admin/faq/categories/:id | Update a category | | DELETE | /admin/faq/categories/:id/delete | Delete a category (cascades to items) | | GET | /admin/faq/items | List all items (optional ?categoryId=) | | POST | /admin/faq/items/create | Create a new FAQ item | | GET | /admin/faq/items/:id | Get a FAQ item by ID | | PUT | /admin/faq/items/:id/update | Update a FAQ item | | DELETE | /admin/faq/items/:id/delete | Delete a FAQ item | | GET | /admin/faq/stats | Get FAQ statistics |

Controller API

The FaqController interface is exported for inter-module use.

interface FaqController {
  createCategory(params: {
    name: string;
    slug: string;
    description?: string;
    icon?: string;
    position?: number;
  }): Promise<FaqCategory>;

  getCategory(id: string): Promise<FaqCategory | null>;
  getCategoryBySlug(slug: string): Promise<FaqCategory | null>;
  listCategories(opts?: { visibleOnly?: boolean }): Promise<FaqCategory[]>;
  updateCategory(id: string, data: Partial<FaqCategory>): Promise<FaqCategory>;
  deleteCategory(id: string): Promise<void>;

  createItem(params: {
    categoryId: string;
    question: string;
    answer: string;
    slug: string;
    position?: number;
    tags?: string[];
  }): Promise<FaqItem>;

  getItem(id: string): Promise<FaqItem | null>;
  getItemBySlug(slug: string): Promise<FaqItem | null>;
  listItems(opts?: { categoryId?: string; visibleOnly?: boolean }): Promise<FaqItem[]>;
  updateItem(id: string, data: Partial<FaqItem>): Promise<FaqItem>;
  deleteItem(id: string): Promise<void>;

  search(query: string, opts?: { categoryId?: string; limit?: number }): Promise<FaqItem[]>;
  vote(itemId: string, helpful: boolean): Promise<FaqItem>;
  getStats(): Promise<{ totalCategories; totalItems; totalHelpful; totalNotHelpful }>;
}

Types

interface FaqCategory {
  id: string;
  name: string;
  slug: string;
  description?: string;
  icon?: string;
  position: number;
  isVisible: boolean;
  metadata?: Record<string, unknown>;
  createdAt: Date;
  updatedAt: Date;
}

interface FaqItem {
  id: string;
  categoryId: string;
  question: string;
  answer: string;
  slug: string;
  position: number;
  isVisible: boolean;
  tags?: string[];
  helpfulCount: number;
  notHelpfulCount: number;
  metadata?: Record<string, unknown>;
  createdAt: Date;
  updatedAt: Date;
}

Admin Pages

| Path | Component | Group | Description | |------|-----------|-------|-------------| | /admin/faq | FaqList | Content | Stats dashboard (categories, questions, helpful/not helpful votes), category filter, FAQ item list with visibility badges, inline create form with category select and auto-slug | | /admin/faq/categories | FaqCategories | Content | Category list with visibility badges, inline create form with name, slug, description, icon, and position fields | | /admin/faq/:id | FaqDetail | — | Edit form for question, answer, category, slug, tags, position, and visibility toggle with helpful/not helpful counts | | /admin/faq/categories/:id | FaqCategoryDetail | — | Edit form for name, slug, description, icon, position, and visibility toggle |

Store Components

FaqAccordion

Collapsible accordion of FAQ items. When given a categorySlug, displays items from that category. Otherwise shows a category navigation bar. Includes helpfulness voting on each expanded item.

Props

| Prop | Type | Default | Description | |---|---|---|---| | categorySlug | string? | — | Slug of category to display. If omitted, shows category list. | | title | string? | "FAQ" | Section heading (used when no category is loaded) |

Usage in MDX

{/* Show all categories as navigation */}
<FaqAccordion />

{/* Show items from a specific category */}
<FaqAccordion categorySlug="shipping" title="Shipping FAQ" />

Typically placed on a dedicated /faq page or embedded in relevant product/category pages. Each item expands to show the answer and a "Was this helpful?" voting widget.

FaqSearch

Live search widget with debounced input and result display. Searches across all visible FAQ items by question text, answer text, and tags.

Props

| Prop | Type | Default | Description | |---|---|---|---| | placeholder | string? | "Search frequently asked questions..." | Input placeholder text |

Usage in MDX

<FaqSearch />

<FaqSearch placeholder="How can we help?" />

Place at the top of the FAQ page for instant search. Results link to individual FAQ item pages at /faq/item/:slug. Input is debounced (300ms) to avoid excessive API calls.

Notes

  • Categories and items are ordered by position (ascending). Use position to control display order.
  • Store endpoints only return visible items/categories (isVisible: true). Admin endpoints return all.
  • Search uses weighted scoring: question matches (10pts) > tag matches (8pts) > answer matches (5pts), with word-level bonuses.
  • Deleting a category cascades to all its items.
  • Helpfulness votes are anonymous and cumulative — no per-user tracking.