Skip to main content

Vue.js integration: getting started

This guide covers integrating Weavr Web SDK UI components with Vue.js 3 using the Composition API. You'll learn the correct patterns for script loading, lifecycle management, and the four distinct component integration patterns.

Overview and quick start​

Prerequisites​

  • Vue.js 3.x with Composition API
  • A Weavr account with an active UI key
  • Basic understanding of Vue.js reactivity and lifecycle hooks

5-minute minimal example​

This example demonstrates a working password input component:

1. Add the SDK to your index.html:

<!doctype html>
<html>
<head>
<script src="https://sandbox.weavr.io/app/secure/static/client.1.js"></script>
</head>
<body>
<div id="app"></div>
</body>
</html>

2. Create a Vue component:

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from "vue";

const containerRef = ref<HTMLElement | null>(null);
let form: any = null;
let input: any = null;

onMounted(() => {
if (!window.OpcUxSecureClient) {
console.error("Weavr SDK not loaded - check index.html script tag");
return;
}

window.OpcUxSecureClient.init("your_ui_key_here");
form = window.OpcUxSecureClient.form();
input = form.input("password", "password", {
placeholder: "Enter password",
});
input.mount(containerRef.value);
});

onUnmounted(() => {
// Defensive cleanup to prevent errors if SDK component wasn't initialized
try {
if (input && typeof input.unmount === "function") {
input.unmount();
}
} catch (e) {
console.error("Error unmounting component:", e);
}
});

const handleSubmit = () => {
form.tokenize((tokens: Record<string, string>) => {
console.log("Password token:", tokens.password);
// Send tokens.password to your server
});
};
</script>

<template>
<form @submit.prevent="handleSubmit">
<div ref="containerRef"></div>
<button type="submit">Submit</button>
</form>
</template>

Script loading​

Critical requirement

The Weavr SDK must be loaded via a <script> tag in index.html. Do not import it through Vite or any bundler.

See Framework Integration Overview for details on why this is required.

Vite configuration​

Add the SDK to index.html in your project root:

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Your App</title>

<!-- Weavr SDK - MUST be loaded here, not via import -->
<script src="https://sandbox.weavr.io/app/secure/static/client.1.js"></script>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

Webpack-based configuration (legacy)​

Webpack toolchain in maintenance mode

The Vue command-line tool (the webpack-based toolchain) is in maintenance mode. For new projects, use Vite (shown in the preceding section).

For existing projects using the legacy webpack toolchain, add the SDK to public/index.html:

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title><%= htmlWebpackPlugin.options.title %></title>

<!-- Weavr SDK -->
<script src="https://sandbox.weavr.io/app/secure/static/client.1.js"></script>
</head>
<body>
<div id="app"></div>
</body>
</html>

Environment-based SDK URLs​

For production deployments, use different SDK URLs per environment:

<script>
// Determine SDK URL based on environment
const sdkUrl = import.meta.env.PROD
? 'https://secure.weavr.io/app/secure/static/client.1.js'
: 'https://sandbox.weavr.io/app/secure/static/client.1.js';

const script = document.createElement('script');
script.src = sdkUrl;
document.head.appendChild(script);
</script>

Or use separate HTML files for each environment.

SDK initialization​

Create a Vue plugin to initialize the SDK once when your app starts:

// src/plugins/weavr.ts
import type { App } from "vue";

declare global {
interface Window {
OpcUxSecureClient: {
init: (
uiKey: string,
options?: { fonts?: Array<{ cssSrc: string }> }
) => void;
form: () => WeavrForm;
span: (type: string, token: string, options?: object) => WeavrSpan;
associate: (
token: string,
onSuccess: () => void,
onError?: (e: Error) => void
) => void;
kyb: () => { init: (...args: any[]) => void };
kyc: () => { init: (...args: any[]) => void };
consumer_kyc: () => { init: (options: object) => void };
};
}
}

interface WeavrForm {
input: (name: string, type: string, options?: object) => WeavrInput;
tokenize: (callback: (tokens: Record<string, string>) => void) => void;
}

interface WeavrInput {
mount: (element: HTMLElement | null) => void;
unmount: () => void;
on: (event: string, callback: () => void) => void;
}

interface WeavrSpan {
mount: (element: HTMLElement | null) => void;
unmount: () => void;
}

export const weavrPlugin = {
install(
app: App,
options: { uiKey: string; fonts?: Array<{ cssSrc: string }> }
) {
// Check SDK is loaded
if (!window.OpcUxSecureClient) {
console.error("Weavr SDK not loaded. Add script tag to index.html.");
return;
}

// Initialize SDK
window.OpcUxSecureClient.init(options.uiKey, {
fonts: options.fonts,
});

// Make available globally
app.config.globalProperties.$weavr = window.OpcUxSecureClient;
},
};

Register the plugin in your main entry:

// src/main.ts
import { createApp } from "vue";
import App from "./App.vue";
import { weavrPlugin } from "./plugins/weavr";

const app = createApp(App);

app.use(weavrPlugin, {
uiKey: import.meta.env.VITE_WEAVR_UI_KEY,
fonts: [
{ cssSrc: "https://fonts.googleapis.com/css?family=Inter:400,500,600" },
],
});

app.mount("#app");

Per-component initialization​

For simpler setups, initialize in each component:

<script setup lang="ts">
import { onMounted } from "vue";

onMounted(() => {
if (window.OpcUxSecureClient) {
window.OpcUxSecureClient.init("your_ui_key");
}
});
</script>
Avoid repeated init() calls

Calling init() multiple times is safe, but wasteful. Prefer the plugin pattern for larger apps.

Next steps​