- Vue 3 with Vite: a client-rendered app, usually with Vue Router.
- Nuxt 3 or 4: server-rendered, with a client-only plugin and a Nitro server route for user tokens.
ClaimrWidget component renders the container, and a useClaimr() composable gives components access to state and methods.
Read How the loader works for the reasoning behind this layout. In short: the script loads once for the whole app, and the widget attaches to whichever
ClaimrWidget is currently mounted.Vue 3 with Vite
1
Add environment variables
.env
2
Add the shared loader module
Create
src/lib/claimr.ts with the contents of the shared loader module.3
Create the plugin
src/plugins/claimr.ts
4
Create the composable
src/composables/useClaimr.ts
5
Create the widget component
src/components/ClaimrWidget.vue
6
Install the plugin
src/main.ts
createClaimr({ language: 'fr', platform: 'dapp' }).7
Render the widget
src/views/QuestsView.vue
Use the SDK from components
src/components/LessonVideo.vue
complete_task only works for tasks configured as front-end tasks in the campaign. See SDK tasks.
Sign users in with your own accounts
Generate the token on your backend with your secret API token. Never call the token endpoint from Vue code.server/claimr-token.ts
src/App.vue
Nuxt
This setup works with Nuxt 3 and Nuxt 4. Paths are relative to your source directory: the project root in Nuxt 3, orapp/ in Nuxt 4. Server files always live in server/ at the project root.
1
Add runtime config
nuxt.config.ts
.env
2
Add the shared loader module
Create
lib/claimr.ts with the contents of the shared loader module. It guards every window access, so importing it during server rendering is safe.3
Create the composable
useState gives you state that is shared across components and safe to use during server rendering.composables/useClaimr.ts
4
Create the client plugin
The
.client suffix keeps the plugin out of server rendering. onNuxtReady delays loading until hydration is finished, so the loader never adds its iframe to server-rendered markup that Vue is still hydrating.plugins/claimr.client.ts
5
Create the widget component
components/ClaimrWidget.vue
<ClientOnly>. The empty <div> renders on the server, and the widget attaches to it in the browser.6
Render the widget on a page
pages/quests.vue
<NuxtLink> to a page without ClaimrWidget detaches the widget. Coming back attaches it again.Sign users in with your own accounts (Nuxt)
1
Create the server route
The route reads your secret API token from server-only runtime config. This example uses The token never expires. Store it with your user record to avoid calling Claimr on every request.
nuxt-auth-utils; replace requireUserSession with your auth library’s equivalent.server/api/claimr/token.get.ts
2
Pass the token to the widget
plugins/claimr-auth.client.ts
Wallets and Telegram
- dApp with its own wallet: pass
platform: 'dapp'in the loader config and assignwindow.claimr.on_wallet_requestonce your wallet library is ready. The handler receives{ op, ...params }forconnect,sign_message,send_transaction, anddisconnect, and must return a result or throw. Seeon_wallet_requestand the React wallet bridge, which translates directly to a Vue component using@wagmi/vue. - Telegram Mini App: pass
platform: 'telegram'. See Telegram Mini App.
Verify the integration
- Open the page with
ClaimrWidget. The campaign renders inside the container. - In the browser console,
window.claimr.is_claimr_readyreturnstrue. - Navigate to another route and back. The widget comes back, and
document.querySelectorAll('#claimr-script').lengthis still1. - In Nuxt, the server log and browser console show no hydration mismatch warnings for the widget container.
- If you use user tokens, sign in to your app and confirm the widget shows the same user without a second sign-in.