Skip to content

About

In-app feedback collection npm module

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

KokFeedback

English | 한국어

A lightweight npm module to collect user feedback and bug reports with visual context (screenshot, DOM selector, comments).

KokFeedback mounts as a sandboxed widget on your web application, allowing users to report issues by capturing screen areas, selecting DOM elements, and adding inline comments.


🚀 Features

  • 🎯 Intuitive DOM Targeting: Highlight and select problem areas via hover (desktop) or touch (mobile).
  • 📸 Automatic Screen Capture: Automatically encodes selected screen areas to Base64 images.
  • 💬 Inline Comments: Add text feedback directly over captured screen areas.
  • 🎨 Style Isolation (Shadow DOM): Rendered inside Shadow DOM, strictly isolated from host app CSS.
  • ⚡ Performance Optimized: Utilizes Debounce and RequestAnimationFrame to minimize reflows (~63KB gzipped).
  • 🌐 Automatic i18n & Localization: Auto-detects browser language (en / ko) or supports explicit override via lang config.
  • ♿ Accessibility: Focus Trap and ESC key shortcuts supported.
  • 📱 Responsive: Native support for PC (mouse) and Mobile (touch) interactions.
  • 🔧 Highly Customizable: Theme, colors, positioning, z-index, and text labels are fully configurable.

📦 Installation

# npm
npm install kok-feedback

# yarn
yarn add kok-feedback

# pnpm
pnpm add kok-feedback

🔧 Usage

Quick Start (Supabase Backend - Recommended)

Connect seamlessly with a Supabase backend without building a custom server.

import KokFeedback from 'kok-feedback';

KokFeedback.init({
  projectId: process.env.NEXT_PUBLIC_PROJECT_ID, // Unique project key
  supabaseUrl: process.env.NEXT_PUBLIC_SUPABASE_URL,
  supabasePublishableKey: process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY
});

Environment Variables Example (.env)

# Next.js
NEXT_PUBLIC_PROJECT_ID=MY-SERVICE-WEB
NEXT_PUBLIC_SUPABASE_URL=https://xxxx.supabase.co
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=sb_publishable_...

# Vite
VITE_PROJECT_ID=MY-SERVICE-WEB
VITE_SUPABASE_URL=https://xxxx.supabase.co
VITE_SUPABASE_PUBLISHABLE_KEY=sb_publishable_...

💡 Why is projectId required?

  • Multi-project Identification: Serves as a unique identifier when sharing a single Supabase backend across multiple web applications.
  • Storage Folder Segmentation: Automatically categorizes uploaded screenshot images into subfolders named after the projectId.

Custom API Server

If using your own backend API, specify the endpoint URL.

KokFeedback.init({
  projectId: 'MY-SERVICE-WEB',
  endpoint: 'https://api.example.com/v1/feedback',
  
  // Customization Options (Optional)
  theme: 'dark',                  // 'light' | 'dark'
  zIndex: 9999,                   // Widget z-index
  buttonPosition: 'bottom-right', // 'bottom-right' | 'bottom-left'
  buttonColor: '#FF6B6B',         // Button accent color
  buttonText: 'Feedback',         // Button label
});

🚀 Backend Setup (Supabase)

👉 [Click to Expand] Supabase SQL Tables, RLS Security Policies & Storage Setup Script

Execute the following script inside the SQL Editor in your Supabase Dashboard:

-- 1. Create feedbacks table
CREATE TABLE public.feedbacks (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL,
    project_id TEXT NOT NULL,
    type TEXT NOT NULL,
    priority TEXT NOT NULL,
    message TEXT NOT NULL,
    status TEXT DEFAULT 'new',
    image_url TEXT,
    page_url TEXT,
    selector TEXT,
    viewport TEXT,
    user_agent TEXT
);

-- 2. Enable RLS and setup policies
ALTER TABLE public.feedbacks ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Enable insert feedback for all" 
ON public.feedbacks FOR INSERT TO anon, authenticated WITH CHECK (true);

CREATE POLICY "Enable select feedback for authenticated users only" 
ON public.feedbacks FOR SELECT TO authenticated USING (true);

CREATE POLICY "Enable update feedback for authenticated users only" 
ON public.feedbacks FOR UPDATE TO authenticated USING (true) WITH CHECK (true);

-- 3. Create feedback comments table & RLS
CREATE TABLE IF NOT EXISTS public.feedback_comments (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    created_at TIMESTAMPTZ DEFAULT now(),
    feedback_id UUID REFERENCES public.feedbacks(id) ON DELETE CASCADE,
    user_id UUID DEFAULT auth.uid(),
    message TEXT NOT NULL
);

ALTER TABLE public.feedback_comments ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Allow select comments" ON public.feedback_comments FOR SELECT TO authenticated, anon USING (true);
CREATE POLICY "Allow insert comments" ON public.feedback_comments FOR INSERT TO authenticated, anon WITH CHECK (true);

-- 4. Create View for feedback comments with user email
CREATE OR REPLACE VIEW public.feedback_comments_with_email AS
SELECT fc.id, fc.created_at, fc.feedback_id, fc.user_id, fc.message, au.email AS user_email
FROM public.feedback_comments fc
LEFT JOIN auth.users au ON fc.user_id = au.id;

GRANT SELECT ON public.feedback_comments_with_email TO authenticated, anon;

-- 5. Create storage bucket & policies
INSERT INTO storage.buckets (id, name, public) 
VALUES ('feedbacks', 'feedbacks', true)
ON CONFLICT (id) DO NOTHING;

CREATE POLICY "Enable upload for anonymous users" 
ON storage.objects FOR INSERT TO public WITH CHECK (bucket_id = 'feedbacks');

CREATE POLICY "Enable public read access" 
ON storage.objects FOR SELECT TO public USING (bucket_id = 'feedbacks');

📖 API Reference

KokFeedback.init(config)

Initializes the feedback widget on the DOM.

interface Config {
  projectId: string;              // Required: Unique project identifier
  endpoint?: string;              // Custom API endpoint URL
  supabaseUrl?: string;           // Supabase URL (Recommended)
  supabasePublishableKey?: string;// Supabase Publishable Key (Recommended)
  theme?: 'light' | 'dark';       // Default: 'light'
  lang?: 'auto' | 'en' | 'ko';    // Default: 'auto'
  zIndex?: number;                // Default: 9999
  buttonPosition?: string;        // Default: 'bottom-right'
  buttonColor?: string;           // Default: '#007BFF'
  buttonText?: string;            // Default: 'Feedback'
}

KokFeedback.destroy()

Unmounts the widget and cleans up all event listeners.

KokFeedback.destroy();

📨 Data Payload Schema

{
  "type": "bug",
  "priority": "p1",
  "message": "The login button is unresponsive.",
  "imageData": "data:image/png;base64,iVBORw0KGgoAAAAN...",
  "metadata": {
    "url": "https://example.com/login",
    "selector": "body > div.container > button#login",
    "viewport": "1920x1080",
    "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)..."
  }
}

🔗 Links & Resources


📝 License

MIT License © postforty

About

In-app feedback collection npm module

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages