Skip to content

Install guide · SvelteKit

Add the Quackback widget to SvelteKit

SvelteKit runs your root layout on every page, and onMount only fires in the browser. That makes the layout the right home for the widget, with a server endpoint to sign identify tokens.

Get your widget snippet

  • 14-day Pro trial, no card needed
  • Your workspace URL and snippet, ready to copy
  • The widget is on every plan, including Free

The widget your customers see inside your app.

Your team’s viewYour customers’ view
Feedback
Review
Status
Board
Tags

Install the widget in SvelteKit

First, in Quackback, open Settings, then Widget, and turn on Show on your website. Until it's on, the snippet loads but the launcher stays hidden. Every snippet uses your-workspace.quackback.io as a placeholder. Swap in your workspace URL, or your custom domain, from Settings, under Widget, then Install.

Read the full install docs

Install the package

Add @quackback/widget with your package manager.

Terminal
npm install @quackback/widget

Init in the root layout

Read the workspace URL from a PUBLIC_ env variable. Returning destroy from onMount cleans up if the layout ever unmounts.

src/routes/+layout.svelte
<script lang="ts">
  import { onMount } from "svelte";
  import { Quackback } from "@quackback/widget";
  import { PUBLIC_QUACKBACK_URL } from "$env/static/public";

  let { children } = $props();

  onMount(() => {
    Quackback.init({ instanceUrl: PUBLIC_QUACKBACK_URL });
    return () => Quackback.destroy();
  });
</script>

{@render children()}

<!-- .env: PUBLIC_QUACKBACK_URL=https://your-workspace.quackback.io -->

Open it from your own button

Call Quackback.open from any component, straight to a view.

src/lib/FeedbackButton.svelte
<script lang="ts">
  import { Quackback } from "@quackback/widget";
</script>

<button onclick={() => Quackback.open({ view: "new-post" })}>
  Send feedback
</button>

Identify signed-in users

A +server.ts endpoint signs a five-minute token for the signed-in user. The layout fetches it once and passes it to identify.

How identify works

Add an endpoint that signs the token

Copy the signing secret from Settings, under Widget, then Install, into WIDGET_SIGNING_SECRET. $env/static/private keeps it out of the client bundle. This assumes your auth hook sets locals.user.

src/routes/api/widget-sso/+server.ts
import { error, json } from "@sveltejs/kit";
import { SignJWT } from "jose";
import { WIDGET_SIGNING_SECRET } from "$env/static/private";
import type { RequestHandler } from "./$types";

const secret = new TextEncoder().encode(WIDGET_SIGNING_SECRET);

export const GET: RequestHandler = async ({ locals }) => {
  const user = locals.user; // set by your auth hook
  if (!user) error(401);

  const ssoToken = await new SignJWT({
    sub: String(user.id), // stable user id, never the email
    email: user.email,
    name: user.name,
  })
    .setProtectedHeader({ alg: "HS256" })
    .setExpirationTime("5m")
    .sign(secret);

  return json({ ssoToken });
};

Identify from the layout

Fetch once on mount. Call Quackback.logout() in your sign-out action.

src/routes/+layout.svelte
onMount(() => {
  Quackback.init({ instanceUrl: PUBLIC_QUACKBACK_URL });

  fetch("/api/widget-sso")
    .then((res) => (res.ok ? res.json() : null))
    .then((data) => data && Quackback.identify({ ssoToken: data.ssoToken }));

  return () => Quackback.destroy();
});

Good to know on SvelteKit

Widget events and methods
Not in the script bodyCode at the top of a component's script runs during server rendering too. Keep init inside onMount.
Svelte 4The init code is the same. Swap $props and {@render children()} for <slot />, and on:click for onclick.
Plain SvelteWithout SvelteKit, init in your root component's onMount and use your bundler's env variables for the URL.

Common questions

Is there a Svelte store or adapter?

Not yet. Svelte apps import Quackback from @quackback/widget and call it directly. Subscribe to events such as vote with Quackback.on, which returns an unsubscribe function you can return from onMount.

Does it work with prerendered pages?

Yes. The widget inits in the browser after the page loads. Identify needs the endpoint, which only runs where SvelteKit has a server.

Do visitors have to sign in to use the widget?

No. Once Show on your website is on in your widget settings, the launcher appears for every visitor after init. Anonymous visitors can still post, vote and chat, and can leave an email inline. When you identify them later, what they did before signing in moves onto their account.

Is the Quackback widget free?

Yes. The widget is on every plan, including Free, with feedback, live chat, help articles and your changelog inside it. Every signup starts with a 14-day Pro trial.

Have another question? Talk to the team.

Put feedback inside your SvelteKit app