Documentação
Comece a construirQuickstarts por frameworkHTML

HTML

Uma tela de entrada funcionando em um arquivo só. Sem bundler, sem framework, sem build.

O SDK é um módulo ES, então o navegador carrega direto. Útil para uma landing page, um protótipo ou uma aplicação que não tem bundler.

Carregue de uma CDN

<script type="module">
  import { createClient, Storage } from 'https://cdn.nulvless.com/js@1/index.min.js';
</script>

Fixe a versão maior. O @1 recebe correções sem mudanças que quebrem.

O arquivo inteiro

index.html
<!doctype html>
<html lang="pt-BR">
  <body>
    <form id="sign-in">
      <input name="email" type="email" placeholder="[email protected]" required />
      <input name="password" type="password" required />
      <button type="submit">Entrar</button>
      <p id="error" role="alert" hidden></p>
    </form>

    <div id="signed-in" hidden>
      <p id="who"></p>
      <button id="sign-out">Sair</button>
    </div>

    <script type="module">
      import { createClient, Storage } from 'https://cdn.nulvless.com/js@1/index.min.js';

      const nulvless = createClient(
        'https://<project>.nulvless.co',
        'pk-…',
        { storage: Storage.Local },
      );

      const form = document.getElementById('sign-in');
      const signedIn = document.getElementById('signed-in');
      const error = document.getElementById('error');

      async function render() {
        const { data: session } = await nulvless.auth.getSession();

        form.hidden = Boolean(session);
        signedIn.hidden = !session;

        if (session) {
          document.getElementById('who').textContent = session.user.email;
        }
      }

      form.addEventListener('submit', async (event) => {
        event.preventDefault();
        error.hidden = true;

        const body = new FormData(form);
        const { data, error: signInError } = await nulvless.auth.signIn({
          email: body.get('email'),
          password: body.get('password'),
        });

        if (signInError) {
          error.textContent = 'Confira o e-mail e a senha.';
          error.hidden = false;
          return;
        }

        if (data.challenge) {
          // Colete o código e chame auth.verifyChallenge({ token, code })
          return;
        }

        render();
      });

      document.getElementById('sign-out').addEventListener('click', async () => {
        await nulvless.auth.signOut();
        render();
      });

      render();
    </script>
  </body>
</html>

Login social

document.getElementById('google').addEventListener('click', () => {
  nulvless.auth.authorize('google', {
    redirect_uri: window.location.origin + '/callback.html',
  });
});

No callback.html:

const code = new URLSearchParams(location.search).get('code');
if (code) {
  await nulvless.auth.exchangeCodeForToken(code);
  location.href = '/';
}

A URI de redirecionamento precisa estar na lista permitida do projeto, senão a plataforma rejeita antes de qualquer token existir.

Pontos de atenção

Somente chave publicável

Tudo nesta página roda no navegador, então só uma chave pk- cabe aqui. Uma chave sk- dentro de uma tag script pode ser lida por qualquer pessoa que abrir a página.

Sem um framework, nada re-renderiza sozinho. Então assine os eventos se a sessão puder mudar enquanto a página está aberta:

nulvless.auth.on('signed-out', render);
nulvless.auth.on('unauthorized', render);

Nesta página