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

wafir

v0.1.0

Published

A powerful, framework-agnostic UI widget library built with Lit & TypeScript.

Readme

Wafir - The Web App Feedback and Issue Reporter

Wafir is a lightweight feedback and issue reporting tool that seamlessly connects input from users and testers to your GitHub-based development workflow. It captures user input, screenshots, console logs, and essential browser telemetry to accelerate debugging. See details at https://bps-consulting.github.io/wafir/.

What's in this Repo

This repository contains everything needed to build, use, and support Wafir. You don't need to clone the repo to use Wafir: simply get the widget code and add it to your web application as described in the Quickstart Guide.

The repo includes source code for the following:

  • Wafir Widget (packages/wafir): A web component built with Lit that you can embed in any web application to collect user feedback.
  • Bridge Service (apps/bridge): A Fastify-based backend service that handles feedback submissions, file uploads, and GitHub integration. See the wafir-infrastructure repo for deployment and infrastructure details.
  • Test Web Page (packages/wafir/index.html): A simple HTML page to test the Wafir widget in isolation.
  • Public Documentation Site (apps/www): An Astro-based website for public documentation deployed on GitHub Pages.
  • Configuration Examples (examples/): Sample YAML files showing how to configure the Wafir widget.

🚀 Tech Stack

Wafir (Widget)

  • Lit: Simple, fast Web Components.
  • Nanostores: A tiny state manager for React, Preact, Vue, Svelte, and vanilla JS.
  • Modern Screenshot: Accurate DOM-to-Canvas rendering for feedback context.
  • OpenAPI Fetch: Type-safe API fetching.

Bridge (Backend/API)

  • Fastify: Fast and low overhead web framework for Node.js.
  • Multi-destination Feedback Routing: Route user feedback, bug reports, and suggestions to multiple projects or repositories using the new targets key in your configuration. Screenshots and assets are routed via targets instead of a storage key.- Octokit: Integration with GitHub for automated issue creation.
  • Swagger/OpenAPI: Automated API documentation.

Monorepo Tooling

📂 Project Structure

  • wafir/: The client-side widget built with Lit. It's designed to be embedded in any web application as a standard web component.
  • bridge/: The backend server built with Fastify. It handles submissions, file uploads (to S3), and integrations (like GitHub).

🛠️ Installation

This project is a monorepo managed by pnpm and Turborepo.

  1. Clone the repository:
git clone https://github.com/BPS-Consulting/wafir.git
cd wafir
  1. Install dependencies:
pnpm install

Configuration (Targets-based)

The Wafir widget now routes feedback with a flexible targets: config block—allowing routing to multiple destinations (projects/repos).

Migration from legacy storage config:

The legacy storage key configuration has been removed. All routing is now handled using the targets array and form-level targets references. To migrate, define each destination under the targets key, and update your forms to reference the appropriate target via targets: [targetId].

📋 JSON Schema for IDE Support

Wafir provides a JSON Schema for configuration files to enable autocomplete, validation, and documentation in your IDE. See docs/schema/README.md for detailed setup instructions.

Quick setup for JSON files:

{
  "$schema": "https://raw.githubusercontent.com/BPS-Consulting/wafir/refs/heads/main/wafir-config.schema.json",
  "title": "Contact Us",
  "targets": [...]
}

Quick setup for YAML files:

# yaml-language-server: $schema=https://raw.githubusercontent.com/BPS-Consulting/wafir/refs/wafir-config.schema.json
title: Contact Us
targets: [...]

Example (see /examples/default/wafir.yaml for full template)

title: "Contact Us"
targets:
  - id: default
    type: github/issues
    target: your-username/your-repo
    authRef: "YOUR_INSTALLATION_ID"
  - id: project
    type: github/project
    target: your-username/your-project-id
    authRef: "YOUR_INSTALLATION_ID"
forms:
  - id: feedback
    label: Feedback
    icon: 👍
    targets: [project] # Routes feedback to 'project' target
    fields:
      - id: rating
        type: rating
        attributes:
          label: "How satisfied are you with our website?"
        validations:
          required: true
      - id: description
        type: textarea
        attributes:
          label: "What is the main reason for this rating?"
        validations:
          required: false
  - id: issue
    label: Issue
    icon: 🐞
    targets: [default] # Routes feedback to 'default' target
    fields:
      - id: title
        type: input
        attributes:
          label: "What issue did you encounter?"
        validations:
          required: true
      - id: description
        type: textarea
        attributes:
          label: "Additional information:"
        validations:
          required: true

See /examples for reference configs using the new targets paradigm.


🏃‍♂️ Running Locally

To start the development environment:

pnpm dev

This command runs turbo run dev, which spins up:

  • The Wafir Widget in watch mode.
  • The Bridge API server.

🏗️ Building

To build all packages for production:

pnpm build

To build the browser version of the Wafir widget and copy it to the www site:

cd packages/wafir && pnpm run build:browser
cd apps/www && pnpm run build

🔧 Configuration

Bridge Environment Variables

Create a .env file in the bridge/ directory based on the usage requirements. You typically need:

  • AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY: For S3 access.
  • GITHUB_TOKEN: For GitHub issue creation integration.

Widget Configuration

The widget can be configured via attributes or JavaScript initialization. See the wafir/ directory for specific implementation details.

CSS Customization

Wafir uses Shadow DOM for isolation but exposes CSS custom properties for theming. Set these on the wafir-widget element:

Reporter Variables

| Variable | Default | Description | | --------------------------------- | ----------------------------- | ------------------- | | --wafir-font-family | System fonts | Font stack | | --wafir-font-size | 14px | Base font size | | --wafir-text-color | #111827 | Primary text color | | --wafir-text-secondary | #6b7280 | Muted text color | | --wafir-primary-color | #2563eb | Brand color | | --wafir-primary-hover | #1d4ed8 | Hover state | | --wafir-border-color | #e5e7eb | Border color | | --wafir-button-size | 48px | Trigger button size | | --wafir-button-border-radius | 50% | Button shape | | --wafir-button-offset | 20px | Edge distance | | --wafir-button-icon-size | 24px | Icon size | | --wafir-button-shadow | 0 4px 12px rgba(0,0,0,0.15) | Button shadow | | --wafir-button-shadow-hover | 0 6px 16px rgba(0,0,0,0.2) | Hover shadow | | --wafir-tooltip-bg | #1f2937 | Tooltip background | | --wafir-backdrop-color | rgba(0,0,0,0.5) | Modal backdrop | | --wafir-modal-bg | white | Modal background | | --wafir-modal-border-radius | 12px | Modal corners | | --wafir-modal-max-width | 800px | Modal width | | --wafir-modal-padding | 20px | Modal spacing | | --wafir-modal-shadow | 0 20px 60px rgba(0,0,0,0.3) | Modal shadow | | --wafir-modal-title-font-size | 18px | Title size | | --wafir-modal-title-font-weight | 600 | Title weight | | --wafir-modal-title-color | --wafir-text-color | Title color |

Form Variables

| Variable | Default | Description | | ------------------------------- | ------------- | ---------------- | | --wafir-form-text-color | #374151 | Form text | | --wafir-form-bg | transparent | Form background | | --wafir-form-padding | 20px | Form padding | | --wafir-form-border-color | #d1d5db | Input borders | | --wafir-form-border-radius | 6px | Input corners | | --wafir-form-input-padding | 10px 12px | Input spacing | | --wafir-form-input-color | #111827 | Input text | | --wafir-form-input-bg | #ffffff | Input background | | --wafir-form-primary-color | #2563eb | Submit button | | --wafir-form-primary-hover | #1d4ed8 | Submit hover | | --wafir-form-disabled-color | #9ca3af | Disabled state | | --wafir-form-bg-secondary | #f3f4f6 | Secondary bg | | --wafir-form-bg-tertiary | #f9fafb | Tertiary bg | | --wafir-form-text-secondary | #6b7280 | Secondary text | | --wafir-form-telemetry-bg | #f9fafb | Telemetry bg | | --wafir-form-telemetry-border | #e5e7eb | Telemetry border | | --wafir-form-logs-bg | #111827 | Logs background | | --wafir-form-logs-text | #f3f4f6 | Logs text | | --wafir-form-log-warn | #fde047 | Warning color | | --wafir-form-log-error | #f87171 | Error color |

Highlighter Variables

| Variable | Default | Description | | ----------------------------------- | --------------------- | ------------ | | --wafir-highlighter-overlay-bg | rgba(0,0,0,0.1) | Overlay bg | | --wafir-highlighter-primary-color | #2563eb | Border color | | --wafir-highlighter-highlight-bg | rgba(37,99,235,0.1) | Fill color |

Example

wafir-widget {
  --wafir-primary-color: #6366f1;
  --wafir-primary-hover: #818cf8;
  --wafir-modal-bg: #ffffff;
  --wafir-text-color: #1f2937;
  --wafir-form-border-radius: 8px;
}

🤝 Contributing

  1. Fork the repo
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Credits

Distribution & Usage

📦 Using via NPM (Module, ESM)

Install:

npm install wafir

Import and use in your project:

import "wafir";

// The web component is now registered and ready to use in your HTML

Then add the widget to your HTML:

<wafir-widget
  config-url="/wafir.yaml"
  bridge-url="https://your-bridge.example.com"
></wafir-widget>

You can also import styles if needed:

import "wafir/styles/widget.css";

🌐 Using via CDN/IIFE (Browser Global)

Add to your HTML:

<script
  type="module"
  src="https://cdn.jsdelivr.net/npm/wafir/dist/browser/wafir.browser.js"
></script>

This automatically registers the <wafir-widget> custom element. You can then use it anywhere in your HTML:

<wafir-widget
  config-url="/wafir.yaml"
  bridge-url="https://your-bridge.example.com"
></wafir-widget>

Optionally include styles from the CDN:

<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/wafir/dist/browser/styles/wafir-widget.css"
/>

See full docs at GitHub Pages.