Install Flawsnap in a Nuxt app

Declare the widget script in nuxt.config so Nuxt renders it into every page’s head, then identify users from a client-only plugin.

Steps

  1. 1

    Allow your hosts

    In Flawsnap, add your production and staging domains and localhost:3000 under the project’s Security → Allowed domains.

  2. 2

    Add the script to nuxt.config

    Add the widget to app.head.script in nuxt.config.ts with async: true and your data-key.

  3. 3

    Add a client-only plugin

    Create plugins/flawsnap.client.ts to identify the signed-in user in the browser.

  4. 4

    Declare the global type

    Add a flawsnap.d.ts so window.Flawsnap type-checks.

  5. 5

    Run and test

    Run nuxi dev, open the app and send a test report.

Add the script in nuxt.config.ts

app.head is rendered into the HTML on the server, so the tag is already in the page when it reaches the browser, before your app hydrates. That is the earliest point the widget can start capturing.

nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      script: [
        { src: 'https://backend.flawsnap.com/widget.js', async: true, 'data-key': 'pk_…' },
      ],
    },
  },
})

app.head values are fixed at build time. To use a different key per environment from runtime config, add the script with useHead in app.vue instead (below).

Or with useHead and runtime config

Set runtimeConfig.public.flawsnapKey in nuxt.config.ts and override it with NUXT_PUBLIC_FLAWSNAP_KEY in each environment. Use app.vue, not a page or layout, so the script is declared once for the whole app.

app.vue
<script setup lang="ts">
const config = useRuntimeConfig()
useHead({
  script: [
    { src: 'https://backend.flawsnap.com/widget.js', async: true, 'data-key': config.public.flawsnapKey },
  ],
})
</script>

<template>
  <NuxtLayout><NuxtPage /></NuxtLayout>
</template>

Route changes are handled for you

Nuxt pages switch with the Vue Router's history mode. Flawsnap watches the History API, so each navigation updates the URL on reports and counts as a screen in Insights (Pro). Do not re-add the script in pages or middleware.

Identify users in a client-only plugin

The .client suffix makes Nuxt run the plugin in the browser only, where window exists. With a useUserSession-style composable from your auth module:

plugins/flawsnap.client.ts
export default defineNuxtPlugin(() => {
  const { user } = useUserSession()
  watch(
    user,
    (u) => {
      if (u?.email) window.Flawsnap?.identify({ name: u.name, email: u.email })
    },
    { immediate: true },
  )
})

Swap useUserSession for whatever your auth module provides. The point is a watcher in a client plugin.

The window type

types/flawsnap.d.ts
// flawsnap.d.ts (anywhere your tsconfig includes)
export {}

declare global {
  interface Window {
    Flawsnap?: {
      open(): void
      identify(reporter: { name?: string; email?: string }): void
      setMetadata(details: Record<string, unknown>): void
      screen(name: string): void
      track(name: string): void
      resetUser(): void
    }
  }
}

Troubleshooting

  • window is not defined during server rendering: code that calls window.Flawsnap is running on the server. Move it into a .client plugin or onMounted.
  • [flawsnap] widget disabled:: the host is not on the allowed list. nuxi dev uses localhost:3000 unless you changed the port.
  • Statically generated sites (nuxi generate): the head tag is baked into each page, so rebuild after changing the key.
  • If you set a CSP through a security module, allow https://backend.flawsnap.com in script-src and connect-src.

Questions

Is there a Nuxt module for Flawsnap?
No. The script tag in app.head or useHead is the whole install, and it works with server rendering and static generation.
Will reports show the server-rendered HTML or what the user saw?
What the user saw. The screenshot is drawn from the page in their browser at the moment they click the button.

Try it on your own site

7-day free trial, then $9 a month for Starter or $19 for Pro, per organization, with unlimited team members.

Updated