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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@feedget/widget

v1.3.0

Published

Widget de feedback integrado à API Feedget para coleta de feedback de usuários em aplicações web

Readme

@feedget/widget

Feedget Logo

Widget de feedback inteligente e multi-plataforma para aplicações web

npm version npm downloads License: MIT TypeScript

Demo · Documentação · Reportar Bug · Solicitar Feature


Sobre o Feedget Widget

O Feedget Widget é uma biblioteca JavaScript/TypeScript moderna e leve que permite coletar feedbacks de usuários diretamente em sua aplicação web. Com suporte nativo para React, Angular e Vanilla JavaScript, o widget oferece uma experiência de usuário fluida e profissional.

Por que escolher o Feedget Widget?

  • Multi-plataforma: Funciona com React, Angular e Vanilla JS
  • TypeScript First: Tipagem completa incluída
  • Captura de Screenshots: Integração automática com html2canvas
  • Análise Inteligente: Feedback enviado para análise de sentimento via API
  • Zero Configuração: Funciona out-of-the-box com configurações sensatas
  • Leve e Rápido: Bundle otimizado < 50KB gzipped
  • Totalmente Customizável: Posicionamento, tema e metadata personalizáveis
  • Acessível: Componentes acessíveis e responsivos

Demonstração

Nota: Adicione um GIF ou screenshot do widget em ação para melhor visualização.


Instalação

Via NPM

npm install @feedget/widget

Via Yarn

yarn add @feedget/widget

Via pnpm

pnpm add @feedget/widget

Início Rápido

React

import { FeedgetWidget } from "@feedget/widget/react";
import "@feedget/widget/styles.css";

function App() {
  return (
    <div>
      <h1>Minha Aplicação</h1>

      <FeedgetWidget
        apiKey="feedget_pk_live_abc123..."
        apiUrl="https://api.feedget.io"
      />
    </div>
  );
}

export default App;

Angular

// app.component.ts
import { Component, OnInit, OnDestroy } from "@angular/core";
import {
  createFeedgetWidget,
  FeedgetWidgetAngular,
} from "@feedget/widget/angular";
import "@feedget/widget/styles.css";

@Component({
  selector: "app-root",
  template: '<div id="app">Minha Aplicação</div>',
})
export class AppComponent implements OnInit, OnDestroy {
  private widget: FeedgetWidgetAngular | null = null;

  ngOnInit() {
    this.widget = createFeedgetWidget({
      apiKey: "feedget_pk_live_abc123...",
      apiUrl: "https://api.feedget.io",
    });

    this.widget.mount();
  }

  ngOnDestroy() {
    this.widget?.unmount();
  }
}

Vanilla JavaScript

import { Feedget } from "@feedget/widget/vanilla";
import "@feedget/widget/styles.css";

Feedget.init({
  apiKey: "feedget_pk_live_abc123...",
  apiUrl: "https://api.feedget.io",
});

Funcionalidades

Core Features

  • Tipos de Feedback: Suporte para BUG, IDEA e OTHER
  • Captura de Screenshots: Captura automática da tela com html2canvas
  • Validação de Entrada: Comentários entre 10-1000 caracteres
  • Metadata Automática: Coleta automática de URL, User Agent e Viewport
  • Rate Limiting: Proteção contra spam (100 req/min por API key)
  • Tratamento de Erros: Mensagens de erro específicas e amigáveis
  • Loading States: Indicadores de carregamento durante envio

Segurança

  • API Key Authentication: Autenticação segura via API keys
  • HTTPS Only: Comunicação criptografada obrigatória
  • Input Sanitization: Proteção contra XSS e injeção
  • CORS Support: Configuração adequada de CORS

UI/UX

  • Interface Responsiva: Funciona perfeitamente em desktop e mobile
  • Posicionamento Fixo: Widget sempre visível no canto da tela
  • Animações Suaves: Transições e animações fluidas
  • Dark Mode Ready: Suporte a temas claro e escuro (em breve)
  • Acessibilidade: Seguindo padrões WCAG 2.1

Configuração Detalhada

Propriedades do Widget

| Propriedade | Tipo | Obrigatório | Descrição | | ----------- | -------- | ----------- | ---------------------------------------------- | | apiKey | string | Sim | API Key obtida no dashboard Feedget | | apiUrl | string | Não | URL da API (default: https://api.feedget.io) | | metadata | object | Não | Metadata customizada para enviar com feedbacks |

Exemplo com Todas as Opções

<FeedgetWidget
  apiKey="feedget_pk_live_abc123..."
  apiUrl="https://api.feedget.io"
  metadata={{
    // Identificação do usuário
    userId: "user-123",
    userEmail: "[email protected]",

    // Informações da aplicação
    version: "1.0.0",
    environment: "production",

    // Dados customizados
    custom: {
      plan: "premium",
      feature: "checkout",
      sessionId: "sess_xyz789",
    },
  }}
/>

Guia de Integração por Framework

React (Create React App / Vite / Next.js)

Create React App

// src/App.tsx
import { FeedgetWidget } from "@feedget/widget/react";
import "@feedget/widget/styles.css";

function App() {
  return (
    <>
      {/* Seu conteúdo */}
      <FeedgetWidget
        apiKey={process.env.REACT_APP_FEEDGET_API_KEY!}
        apiUrl={process.env.REACT_APP_FEEDGET_API_URL}
      />
    </>
  );
}

Next.js (App Router)

// app/layout.tsx
"use client";

import { FeedgetWidget } from "@feedget/widget/react";
import "@feedget/widget/styles.css";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="pt-BR">
      <body>
        {children}
        <FeedgetWidget
          apiKey={process.env.NEXT_PUBLIC_FEEDGET_API_KEY!}
          apiUrl={process.env.NEXT_PUBLIC_FEEDGET_API_URL}
        />
      </body>
    </html>
  );
}

Next.js (Pages Router)

// pages/_app.tsx
import type { AppProps } from "next/app";
import { FeedgetWidget } from "@feedget/widget/react";
import "@feedget/widget/styles.css";

export default function App({ Component, pageProps }: AppProps) {
  return (
    <>
      <Component {...pageProps} />
      <FeedgetWidget
        apiKey={process.env.NEXT_PUBLIC_FEEDGET_API_KEY!}
        apiUrl={process.env.NEXT_PUBLIC_FEEDGET_API_URL}
      />
    </>
  );
}

Vite

// src/main.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import "@feedget/widget/styles.css";

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
// src/App.tsx
import { FeedgetWidget } from "@feedget/widget/react";

function App() {
  return (
    <>
      {/* Seu conteúdo */}
      <FeedgetWidget
        apiKey={import.meta.env.VITE_FEEDGET_API_KEY}
        apiUrl={import.meta.env.VITE_FEEDGET_API_URL}
      />
    </>
  );
}

Angular

Módulo Principal

// app.module.ts
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { AppComponent } from "./app.component";

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}

Componente

// app.component.ts
import { Component, OnInit, OnDestroy } from "@angular/core";
import {
  createFeedgetWidget,
  FeedgetWidgetAngular,
  FeedgetConfig,
} from "@feedget/widget/angular";

@Component({
  selector: "app-root",
  template: `
    <div id="app">
      <h1>Minha Aplicação Angular</h1>
    </div>
  `,
  styleUrls: ["./app.component.scss"],
})
export class AppComponent implements OnInit, OnDestroy {
  private widget: FeedgetWidgetAngular | null = null;

  ngOnInit() {
    const config: FeedgetConfig = {
      apiKey: "feedget_pk_live_abc123...",
      apiUrl: "https://api.feedget.io",
      metadata: {
        userId: "user-123",
        version: "1.0.0",
      },
    };

    this.widget = createFeedgetWidget(config);
    this.widget.mount();
  }

  ngOnDestroy() {
    if (this.widget) {
      this.widget.unmount();
    }
  }
}

Estilos Globais

// styles.scss
@import "@feedget/widget/styles.css";

Vanilla JavaScript

Com Módulos ES6

// main.js
import { Feedget } from "@feedget/widget/vanilla";
import "@feedget/widget/styles.css";

// Inicializar quando o DOM estiver pronto
document.addEventListener("DOMContentLoaded", () => {
  Feedget.init({
    apiKey: "feedget_pk_live_abc123...",
    apiUrl: "https://api.feedget.io",
    metadata: {
      userId: getUserId(), // Função customizada
      version: "1.0.0",
    },
  });
});

// Para destruir o widget (cleanup)
window.addEventListener("beforeunload", () => {
  Feedget.destroy();
});

Via CDN (Experimental)

<!DOCTYPE html>
<html lang="pt-BR">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Meu Site</title>

    <!-- Estilos do Widget -->
    <link
      rel="stylesheet"
      href="https://unpkg.com/@feedget/widget@latest/dist/style.css"
    />
  </head>
  <body>
    <h1>Meu Site</h1>

    <!-- Widget Script -->
    <script type="module">
      import { Feedget } from "https://unpkg.com/@feedget/widget@latest/dist/vanilla.js";

      Feedget.init({
        apiKey: "feedget_pk_live_abc123...",
        apiUrl: "https://api.feedget.io",
      });
    </script>
  </body>
</html>

API Reference

React Component Props

interface FeedgetWidgetProps {
  apiKey: string;
  apiUrl?: string;
  metadata?: {
    userId?: string;
    userEmail?: string;
    version?: string;
    environment?: string;
    custom?: Record<string, any>;
  };
}

Angular Config

interface FeedgetConfig {
  apiKey: string;
  apiUrl?: string;
  metadata?: FeedgetMetadata;
}

interface FeedgetWidgetAngular {
  mount(container?: HTMLElement): void;
  unmount(): void;
  updateConfig(config: Partial<FeedgetConfig>): void;
}

Vanilla JS API

interface FeedgetVanilla {
  init(config: FeedgetConfig): void;
  destroy(): void;
  updateConfig(config: Partial<FeedgetConfig>): void;
}

Integração com a API Feedget

Endpoint do Widget

O widget envia feedbacks para:

POST https://api.feedget.io/public/feedbacks

Headers:

X-API-Key: feedget_pk_live_abc123...
Content-Type: application/json

Payload:

{
  "type": "BUG" | "IDEA" | "OTHER",
  "comment": "Descrição do feedback...",
  "screenshot": "data:image/png;base64,iVBOR...",
  "metadata": {
    "url": "https://meusite.com/page",
    "userAgent": "Mozilla/5.0...",
    "viewport": {
      "width": 1920,
      "height": 1080
    },
    "custom": {
      "userId": "user-123",
      "version": "1.0.0"
    }
  }
}

Códigos de Status HTTP

| Código | Descrição | | ------ | ---------------------------------------------- | | 200 | Feedback enviado com sucesso | | 400 | Dados inválidos (comentário muito curto/longo) | | 401 | API key inválida ou expirada | | 403 | Assinatura necessária ou inativa | | 429 | Rate limit excedido (100 req/min) | | 500 | Erro interno do servidor |


Customização Avançada

Posicionamento do Widget

Por padrão, o widget fica fixo no canto inferior esquerdo da tela.

CSS Customizado:

/* Ajustar posicionamento */
.feedget-widget-container {
  bottom: 32px;
  left: 32px;
  /* ou right: 32px para canto direito */
}

/* Mobile */
@media (max-width: 768px) {
  .feedget-widget-container {
    bottom: 16px;
    left: 16px;
  }
}

Temas

/* Customizar cores do widget */
:root {
  --feedget-primary: #8257e6;
  --feedget-secondary: #996dff;
  --feedget-text: #27272a;
  --feedget-bg: #ffffff;
  --feedget-border: #e4e4e7;
}

/* Dark mode */
[data-theme="dark"] {
  --feedget-text: #fafafa;
  --feedget-bg: #18181b;
  --feedget-border: #3f3f46;
}

Troubleshooting

Widget não aparece na tela

Problema: Widget não é renderizado

Soluções:

  1. Certifique-se de importar o CSS:

    import "@feedget/widget/styles.css";
  2. Verifique se a API Key está configurada:

    apiKey = "feedget_pk_live_..."; // não vazio
  3. Verifique o console do navegador para erros

  4. Confirme que a assinatura está ativa

Erro 401: Unauthorized

Problema: API key inválida ou expirada

Soluções:

  1. Gere uma nova API key no dashboard Feedget
  2. Verifique se a key começa com feedget_pk_
  3. Confirme se a key não está expirada
  4. Verifique se a assinatura está ativa

Erro 403: Forbidden

Problema: Assinatura inativa ou limite excedido

Soluções:

  1. Verifique status da assinatura no dashboard
  2. Confirme método de pagamento
  3. Verifique se o limite mensal foi atingido
  4. Entre em contato com o suporte

Erro 429: Too Many Requests

Problema: Rate limit excedido (100 req/min)

Soluções:

  1. Aguarde 1 minuto antes de tentar novamente
  2. Implemente debounce no lado do cliente
  3. Para produção, considere upgrade do plano
  4. Entre em contato para ajuste de limites

Screenshots não são capturados

Problema: html2canvas não funciona

Soluções:

  1. Verifique CORS das imagens externas
  2. Confirme que html2canvas foi instalado:
    npm list html2canvas
  3. Algumas imagens podem não ser capturadas por política CORS
  4. Teste em diferentes navegadores

Problemas de TypeScript

Problema: Erros de tipagem

Soluções:

// tsconfig.json
{
  "compilerOptions": {
    "moduleResolution": "bundler", // ou "node"
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "skipLibCheck": true
  }
}

Widget conflita com outros componentes

Problema: z-index ou posicionamento

Soluções:

/* Ajuste o z-index do widget */
.feedget-widget-container {
  z-index: 9999 !important;
}

/* Ou dos elementos conflitantes */
.seu-modal {
  z-index: 10000;
}

FAQ

Quanto custa usar o Feedget?

O Feedget oferece planos gratuitos e pagos. Visite feedget.io/pricing para mais detalhes.

O widget funciona em todos os navegadores?

Sim, o widget é compatível com:

  • Chrome/Edge (últimas 2 versões)
  • Firefox (últimas 2 versões)
  • Safari 13+
  • Opera (última versão)

Posso usar em aplicações mobile?

Sim, o widget é totalmente responsivo. Para apps mobile nativos, aguarde nosso SDK React Native.

Os dados dos feedbacks ficam onde?

Os feedbacks são armazenados de forma segura nos servidores da Feedget, com criptografia em repouso e em trânsito. Conformidade com GDPR e LGPD.

Posso self-host a API?

Atualmente não oferecemos versão self-hosted. Entre em contato para planos enterprise.

O widget afeta a performance do site?

Não. O widget é carregado de forma assíncrona e tem um bundle otimizado < 50KB gzipped. Impacto mínimo na performance.

Posso customizar o visual do widget?

Sim, você pode customizar cores, posicionamento e tema via CSS. Suporte a temas customizados completos em breve.


Segurança

Relatando Vulnerabilidades

Se você encontrar uma vulnerabilidade de segurança, por favor NÃO abra uma issue pública.

Envie um email para: [email protected]

Práticas de Segurança

  • ✅ Use HTTPS em produção
  • ✅ Armazene API keys em variáveis de ambiente
  • ✅ Nunca commite API keys no código
  • ✅ Rotacione API keys periodicamente
  • ✅ Use diferentes keys para dev/staging/prod
  • ✅ Configure CSP headers adequadamente

Content Security Policy:

Content-Security-Policy:
  connect-src 'self' https://api.feedget.io;
  img-src 'self' data: https://api.feedget.io;

Contribuindo

Contribuições são bem-vindas! Por favor, leia nosso Guia de Contribuição antes de submeter PRs.

Como Contribuir

  1. Fork o repositório
  2. Clone seu fork:
    git clone https://github.com/seu-usuario/widget.git
  3. Crie uma branch para sua feature:
    git checkout -b feature/minha-feature
  4. Commit suas mudanças:
    git commit -m 'feat: adiciona minha feature'
  5. Push para a branch:
    git push origin feature/minha-feature
  6. Abra um Pull Request

Padrão de Commits

Usamos Conventional Commits:

  • feat: Nova funcionalidade
  • fix: Correção de bug
  • docs: Mudanças na documentação
  • style: Formatação, ponto-e-vírgula, etc
  • refactor: Refatoração de código
  • test: Adição de testes
  • chore: Manutenção

Roadmap

  • [x] Suporte React
  • [x] Suporte Angular
  • [x] Suporte Vanilla JS
  • [x] Captura de screenshots
  • [x] TypeScript completo
  • [ ] Dark mode nativo
  • [ ] Temas customizáveis
  • [ ] Suporte Vue.js
  • [ ] Suporte Svelte
  • [ ] React Native SDK
  • [ ] Flutter SDK
  • [ ] Internacionalização (i18n)
  • [ ] Acessibilidade WCAG 2.1 AA
  • [ ] Webhooks customizáveis

Licença

Este projeto está licenciado sob a Licença MIT.


Suporte

Documentação

Comunidade

Contato Direto


Créditos

Desenvolvido e mantido por Feedget Team

Tecnologias Utilizadas


Feito com ❤️ pela equipe Feedget

Website · Blog · Status