Framework examples
Minimal integration examples for every supported framework. In all cases you install the SDK and create a client; the only difference is how you hook it into the framework’s lifecycle and DOM.
Vanilla JS
import { TryMellon } from '@trymellon/js';
const clientResult = TryMellon.create({ appId: 'YOUR_APP_ID', publishableKey: 'cli_xxxx' });
if (!clientResult.ok) throw clientResult.error;
const client = clientResult.value;
document.getElementById('sign-in').addEventListener('click', async () => {
const result = await client.authenticate();
if (result.ok) {
const { sessionToken } = result.value;
await fetch('/api/auth/set-session', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ sessionToken }),
});
window.location.href = '/dashboard';
}
});
React
TryMellon provides official React hooks and a Context Provider in @trymellon/js/react.
- Wrap your app (or auth subtree) with
TryMellonProvider. - Use the
useAuthenticateanduseRegisterhooks in your components.
import { TryMellon } from '@trymellon/js';
import { TryMellonProvider, useAuthenticate } from '@trymellon/js/react';
const clientResult = TryMellon.create({ appId: 'YOUR_APP_ID', publishableKey: 'cli_xxxx' });
if (!clientResult.ok) throw clientResult.error;
const client = clientResult.value;
export function App() {
return (
<TryMellonProvider client={client}>
<LoginButton />
</TryMellonProvider>
);
}
function LoginButton() {
const { execute: authenticate, loading } = useAuthenticate();
const handleLogin = async () => {
const result = await authenticate({ externalUserId: 'user_123' });
if (result.ok) {
await fetch('/api/auth/set-session', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ sessionToken: result.value.sessionToken }),
});
window.location.href = '/dashboard';
}
};
return <button onClick={handleLogin} disabled={loading}>{loading ? 'Signing in...' : 'Sign in'}</button>;
}
Next.js (App Router)
The SDK works with Next.js App Router. Use 'use client' since WebAuthn is browser-only.
// lib/trymellon.ts — shared client instance
'use client';
import { TryMellon } from '@trymellon/js';
const clientResult = TryMellon.create({
appId: process.env.NEXT_PUBLIC_TRYMELLON_APP_ID!,
publishableKey: process.env.NEXT_PUBLIC_TRYMELLON_KEY!,
});
if (!clientResult.ok) throw clientResult.error;
export const mellonClient = clientResult.value;
// app/providers.tsx
'use client';
import { TryMellonProvider } from '@trymellon/js/react';
import { mellonClient } from '@/lib/trymellon';
export function Providers({ children }: { children: React.ReactNode }) {
return <TryMellonProvider client={mellonClient}>{children}</TryMellonProvider>;
}
// app/login/page.tsx
'use client';
import { useAuthenticate } from '@trymellon/js/react';
export default function LoginPage() {
const { execute: authenticate, loading, error } = useAuthenticate();
const handleLogin = async () => {
const result = await authenticate({ externalUserId: 'user_123' });
if (result.ok) {
await fetch('/api/auth/set-session', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ sessionToken: result.value.sessionToken }),
});
window.location.href = '/dashboard';
}
};
return (
<div>
<button onClick={handleLogin} disabled={loading}>
{loading ? 'Signing in...' : 'Sign in with Passkey'}
</button>
{error && <p>{error.message}</p>}
</div>
);
}
Vue
TryMellon provides Composition API composables and provide/inject helpers in @trymellon/js/vue.
<script setup lang="ts">
import { TryMellon } from '@trymellon/js'
import { provideTryMellon, useAuthenticate } from '@trymellon/js/vue'
const clientResult = TryMellon.create({ appId: 'YOUR_APP_ID', publishableKey: 'cli_xxxx' })
if (!clientResult.ok) throw clientResult.error
const client = clientResult.value;
// 1. Provide the instance to all child components
provideTryMellon(client)
// 2. Use the composable
const { execute: authenticate, loading } = useAuthenticate()
async function login() {
const result = await authenticate({ externalUserId: 'user_123' })
if (result.ok) {
await fetch('/api/auth/set-session', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ sessionToken: result.value.sessionToken }),
});
window.location.href = '/dashboard';
}
}
</script>
<template>
<button @click="login" :disabled="loading">{{ loading ? 'Signing in...' : 'Sign in' }}</button>
</template>
Angular
TryMellon provides a standalone service and configuration provider in @trymellon/js/angular.
In your app config (e.g. app.config.ts or root module):
import { provideTryMellonConfig } from '@trymellon/js/angular'
export const appConfig = {
providers: [
provideTryMellonConfig({
appId: 'YOUR_APP_ID',
publishableKey: 'cli_xxxx',
}),
],
}
In a component or service:
import { TryMellonService } from '@trymellon/js/angular'
import { Component, inject } from '@angular/core';
@Component({
selector: 'app-login',
template: `<button (click)="login()">Sign in</button>`,
})
export class LoginComponent {
private tryMellon = inject(TryMellonService)
async login() {
const result = await this.tryMellon.client.authenticate({ externalUserId: 'user_123' })
if (result.ok) {
// Send result.value.sessionToken to your backend
}
}
}
Svelte
Create the client at the top level and call from an async handler.
<script>
import { TryMellon } from '@trymellon/js';
const clientResult = TryMellon.create({ appId: 'YOUR_APP_ID', publishableKey: 'cli_xxxx' });
if (!clientResult.ok) throw clientResult.error;
const client = clientResult.value;
let loading = false;
async function login() {
loading = true;
const result = await client.authenticate();
loading = false;
if (result.ok) {
await fetch('/api/auth/set-session', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ sessionToken: result.value.sessionToken }),
});
window.location.href = '/dashboard';
}
}
</script>
<button on:click={login} disabled={loading}>{loading ? 'Signing in...' : 'Sign in'}</button>
Web Components
For a zero-framework, drop-in solution, use the pre-built Web Components. See Web Components for full documentation.
<script type="module">
import '@trymellon/js/ui';
</script>
<trymellon-auth
app-id="YOUR_APP_ID"
publishable-key="cli_xxxx"
mode="auto"
theme="light"
></trymellon-auth>
<script>
document.querySelector('trymellon-auth')
.addEventListener('mellon:success', (e) => {
console.log('Session token:', e.detail.token);
});
</script>
Next steps
- Use Events & Error handling to show spinners and handle errors.
- Use Fallback by email when WebAuthn is not available.
- Implement Backend validation to create your session and set cookies.
- Try the Web Components for drop-in auth UI.