TryMellon

Framework examples

React, Vue, Angular, Svelte, Next.js, and Web Components integration examples.

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.

  1. Wrap your app (or auth subtree) with TryMellonProvider.
  2. Use the useAuthenticate and useRegister hooks 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