Vue Integration
⚡ 12 min readVite + Vue 3 with redirect-based Transcodes auth — CDN script, composable auth state, Vue Router guards.
Canonical walkthrough: Signin · API: Redirect API
Browser only. Call SDK APIs in onMounted or event handlers — not during SSR.
Before you start
| Requirement | Where |
|---|---|
| Project ID | Console → Installation Guide |
| CDN snippet | Installation Guide → index.html |
transcodes.d.ts | Console → Project Setup |
| SDK Redirect Origins | Step 1 |
| Members | Console → RBAC → Users |
Load the SDK (CDN)
index.html
<script
src="https://cdn.transcodes.link/%VITE_TRANSCODES_PROJECT_ID%/webworker.js"
defer
></script>.env
VITE_TRANSCODES_PROJECT_ID=proj_abc123xyzDownload transcodes.d.ts from Console Project Setup.
App setup
Call useAuth() once at the app root (provide/inject) so every child shares the same session state.
Composable + provide
src/composables/useAuth.ts
import { inject, onMounted, onUnmounted, provide, ref, type InjectionKey } from 'vue';
type AuthStore = {
isAuthenticated: ReturnType<typeof ref<boolean>>;
isLoading: ReturnType<typeof ref<boolean>>;
signIn: () => void;
signOut: () => Promise<void>;
};
const AuthKey: InjectionKey<AuthStore> = Symbol('auth');
function createAuthStore(): AuthStore {
const isAuthenticated = ref(false);
const isLoading = ref(true);
let off: (() => void) | undefined;
onMounted(async () => {
await transcodes.handleSignInCallback();
isAuthenticated.value = await transcodes.token.isAuthenticated();
isLoading.value = false;
off = transcodes.on('AUTH_STATE_CHANGED', ({ isAuthenticated: authed }) => {
isAuthenticated.value = authed;
});
});
onUnmounted(() => off?.());
return {
isAuthenticated,
isLoading,
signIn: () => transcodes.redirectToSignIn(),
signOut: () => transcodes.token.signOut(),
};
}
export function provideAuth() {
const store = createAuthStore();
provide(AuthKey, store);
return store;
}
export function useAuth() {
const store = inject(AuthKey);
if (!store) throw new Error('useAuth() requires provideAuth() on an ancestor');
return store;
}src/App.vue
<script setup lang="ts">
import { provideAuth } from '@/composables/useAuth';
provideAuth();
</script>
<template>
<RouterView />
</template>Sign-in button
src/components/SignInButton.vue
<script setup lang="ts">
import { useAuth } from '@/composables/useAuth';
const { signIn } = useAuth();
</script>
<template>
<button type="button" @click="signIn">Sign in</button>
</template>Step 3: Redirect · Step 4: Events
Route guard (Vue Router)
src/router/index.ts
router.beforeEach(async (to) => {
if (!to.meta.requiresAuth) return true;
const authed = await transcodes.token.isAuthenticated();
return authed ? true : { name: 'login' };
});Mark protected routes with meta: { requiresAuth: true }.
Step-up and Console
Member must be signed in first.
const res = await transcodes.redirectToStepUp({
resource: 'billing',
action: 'update',
});
const gate = res.payload[0];
const ok =
res.success &&
(gate?.decision === 'allow' ||
(gate?.decision === 'stepup' && gate?.status === 'verified'));
transcodes.redirectToConsole();Backend API calls
const token = await transcodes.token.getAccessToken();
await fetch('/api/me', {
headers: { Authorization: `Bearer ${token}` },
});Common mistakes
| Mistake | Fix |
|---|---|
Calling useAuth() in every component without provideAuth() | Single root provideAuth() |
isAuthenticated() without await | Always async |
| Missing SDK Redirect Origins | Console → Domains |
| Step-up before sign-in | Active SDK session required |
Other frameworks
Last updated on