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

@suggesto/nuxt

v1.0.5

Published

Nuxt 3 & 4 module for Suggesto feedback widget integration

Readme

@suggesto/nuxt

Nuxt 3 module for Suggesto feedback widget integration. Provides zero-configuration setup with automatic widget loading and optimal performance.

Installation

npm install @suggesto/nuxt

Quick Setup

Add the module to your nuxt.config.ts:

export default defineNuxtConfig({
  modules: [
    '@suggesto/nuxt'
  ],
  suggesto: {
    boardId: 'your-board-id', // Required
    baseUrl: 'https://suggesto.io' // Optional
  }
});

That's it! The widget will be automatically loaded on all pages.

Usage

Automatic Widget Loading

With the module configured, the widget loads automatically on all pages without any additional code:

<template>
  <div>
    <h1>My Nuxt App</h1>
    <!-- Widget loads automatically -->
  </div>
</template>

Programmatic Control

Access the widget programmatically using the provided composable:

<template>
  <div>
    <h1>My App</h1>
    <button @click="openFeedback" :disabled="isLoading">
      {{ isLoading ? 'Loading...' : 'Give Feedback' }}
    </button>
    <div v-if="error" class="error">
      Error loading widget: {{ error }}
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, watch } from 'vue';

// Reactive state
const isLoading = ref(true);
const error = ref(null);
let openModal = ref(() => {});

const openFeedback = () => {
  openModal.value();
};

// Client-side only initialization
onMounted(() => {
  // Access the suggesto composable through Nuxt app (client-side only)
  const { $suggesto, $suggestoConfig } = useNuxtApp();

  if ($suggesto && $suggestoConfig) {
    const suggestoInstance = $suggesto($suggestoConfig);

    // Use the global reactive references directly
    isLoading.value = suggestoInstance.isLoading.value;
    error.value = suggestoInstance.error.value;
    openModal.value = suggestoInstance.openModal;

    // Watch for changes in the global state
    watch(suggestoInstance.isLoading, (newValue) => {
      isLoading.value = newValue;
    }, { immediate: true });

    watch(suggestoInstance.error, (newValue) => {
      error.value = newValue;
    }, { immediate: true });

    // Listen for events
    suggestoInstance.on('ready', (data) => {
      console.log('Widget ready:', data);
    });

    suggestoInstance.on('feedbackSubmitted', (data) => {
      console.log('Feedback submitted:', data);
      // Track analytics, show toast, etc.
    });

    suggestoInstance.on('error', (errorData) => {
      console.error('Widget error:', errorData);
    });
  }
});
</script>

Custom Configuration Per Page

Override default configuration for specific pages:

<template>
  <div>
    <h1>Special Page</h1>
    <!-- Custom widget instance -->
  </div>
</template>

<script setup>
// Use custom config for this page
const { $suggesto } = useNuxtApp();
const { openModal, on } = $suggesto({
  boardId: 'special-board-id',
  baseUrl: 'https://custom.domain.com'
});

on('ready', (data) => {
  console.log('Custom widget ready:', data);
});
</script>

Configuration

Module Options

Configure the module in your nuxt.config.ts:

export default defineNuxtConfig({
  modules: ['@suggesto/nuxt'],
  suggesto: {
    // Required: Your feedback board UUID
    boardId: 'your-board-id',
    
    // Optional: Custom server URL (default: 'https://suggesto.io')
    baseUrl: 'https://your-custom-domain.com'
  }
});

Environment Variables

Use environment variables for different environments:

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@suggesto/nuxt'],
  suggesto: {
    boardId: process.env.NUXT_SUGGESTO_BOARD_ID,
    baseUrl: process.env.NUXT_SUGGESTO_BASE_URL || 'https://suggesto.io'
  }
});
# .env
NUXT_SUGGESTO_BOARD_ID=your-production-board-id
NUXT_SUGGESTO_BASE_URL=https://suggesto.io

Runtime Config

Access configuration at runtime:

<script setup>
const config = useRuntimeConfig();
console.log('Board ID:', config.public.suggesto.boardId);
</script>

API Reference

Composable: $suggesto(config)

The module provides the same composable from @suggesto/vue through the Nuxt app context.

Parameters

  • config?: SuggestoConfig - Optional config override

Returns

{
  isLoading: Ref<boolean>;         // Widget loading state
  error: Ref<string | null>;       // Error message if loading failed
  openModal: () => void;           // Open feedback modal
  closeModal: () => void;          // Close feedback modal
  on: (event, callback) => void;   // Register event listener
}

Global Properties

The module adds these properties to the Nuxt app:

  • $suggesto - The useSuggesto composable from @suggesto/vue
  • $suggestoConfig - The module configuration

Events

The module supports all events from @suggesto/core:

ready

{
  boardId: string;
  boardSlug: string;
  position: string;
  theme: string;
  color: string;
  widget: any;
}

feedbackSubmitted

{
  boardId: string;
  category: string;
  title: string;
  body: string;
  feedbackId: string;
  success: boolean;
}

error

{
  type: string;
  error: string;
  boardId: string;
  context: string;
}

Advanced Usage

Conditional Loading

Load the widget only on specific pages:

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@suggesto/nuxt'],
  suggesto: {
    boardId: 'your-board-id'
  }
});
<!-- pages/contact.vue -->
<template>
  <div>
    <h1>Contact Us</h1>
    <!-- Widget only loads on this page -->
  </div>
</template>

<script setup>
// Only initialize widget on this specific page
const { $suggesto, $suggestoConfig } = useNuxtApp();

onMounted(() => {
  if (process.client) {
    $suggesto($suggestoConfig);
  }
});
</script>

Multiple Widgets

Use different widgets for different sections:

<script setup>
const { $suggesto } = useNuxtApp();

// Main product feedback
const mainWidget = $suggesto({
  boardId: 'main-product-board-id'
});

// Beta feature feedback
const betaWidget = $suggesto({
  boardId: 'beta-features-board-id'
});
</script>

Analytics Integration

Track widget events with your analytics:

<script setup>
const { $suggesto, $suggestoConfig } = useNuxtApp();
const { on } = $suggesto($suggestoConfig);

on('feedbackSubmitted', (data) => {
  // Google Analytics
  gtag('event', 'feedback_submitted', {
    category: data.category,
    board_id: data.boardId
  });
  
  // Plausible
  plausible('Feedback Submitted', {
    props: {
      category: data.category,
      board: data.boardId
    }
  });
});
</script>

Performance

Server-Side Rendering

The widget is client-side only and won't affect your SSR performance. It loads after hydration is complete.

Singleton Pattern

Version 1.0.4+ implements a singleton pattern to prevent widget instance conflicts:

  • Auto-loading creates a single global widget instance
  • Manual composable usage reuses the same instance
  • Events and state are shared across the application
  • No duplicate widget loading or conflicts

Code Splitting

The widget script is loaded dynamically, keeping your main bundle size minimal.

Caching

Widget configurations are cached on the server for optimal performance.

TypeScript Support

Full TypeScript support with auto-completion:

// types/suggesto.d.ts
import type { SuggestoEvents } from '@suggesto/nuxt';

// Extend Nuxt app type
declare module '#app' {
  interface NuxtApp {
    $suggesto: typeof import('@suggesto/vue').useSuggesto;
    $suggestoConfig: import('@suggesto/core').SuggestoConfig;
  }
}

Troubleshooting

Module not loading

  1. Ensure you've added the module to nuxt.config.ts
  2. Check that boardId is correctly configured
  3. Verify your domain is whitelisted in Suggesto dashboard

Widget not appearing

The widget loads client-side only. Check browser console for errors and ensure JavaScript is enabled.

Widget button stuck on "Loading..."

Fixed in v1.0.4: The singleton pattern ensures proper state management.

If you're still having issues:

  1. Ensure you're using v1.0.4 or later
  2. Check that you're using the updated programmatic control pattern shown above
  3. Events should now register correctly in the console

"$suggesto is not a function" error

This occurs when trying to access the composable during SSR. Always wrap composable usage in onMounted():

<script setup>
onMounted(() => {
  const { $suggesto } = useNuxtApp();
  // Use composable here
});
</script>

Auto-loading conflicts with manual control

Fixed in v1.0.4: The singleton pattern prevents conflicts between auto-loading and manual usage.

Events not firing

Events are automatically handled by the singleton instance. All events will be properly fired and can be listened to via the composable.

TypeScript errors

Install the required types:

npm install @types/node

Make sure your nuxt.config.ts has proper TypeScript configuration.

Migration

From Vue Plugin

If migrating from the Vue plugin:

- import { SuggestoWidget } from '@suggesto/vue';
+ // Remove manual import, widget loads automatically

// nuxt.config.ts
export default defineNuxtConfig({
+  modules: ['@suggesto/nuxt'],
+  suggesto: {
+    boardId: 'your-board-id'
+  }
});

From Script Tag

If migrating from script tag installation:

// Remove from app.html or layouts
- <script src="https://suggesto.io/widget/your-board-id"></script>

// Add to nuxt.config.ts
+ modules: ['@suggesto/nuxt'],
+ suggesto: {
+   boardId: 'your-board-id'
+ }

Examples

Check the playground directory for a complete working example.

License

MIT