Integrar uma app

Conecte sua aplicação ao Mira: origens, CSP, bridge, widget e verificação, com etapas opcionais para erros, source maps e contexto.

Esta trilha leva uma aplicação React 19 com Vite do zero até enviar reports pelo widget. Ela serve a duas pessoas: o admin do Mira, que configura o projeto no dashboard, e o dev da app, que mexe no código e no CI. Cada etapa diz quem faz.

O bridge (@mira/bridge) é o pacote que fica na app. Ele ativa a captura de console, erros e rede desde o carregamento, mostra o widget de report e expõe versão, usuário logado e estado da app. O widget funciona em desenvolvimento, QA e staging. Em produção, só a captura de erros roda, ativada pelo DSN.

Visão geral

Os três ambientes

Uma app costuma rodar em três lugares, e cada um ativa partes diferentes do bridge:

AmbienteWidgetCaptura de erros (DSN)Quem tem o ambiente no Mira
Desenvolvimento localSimOpcionalAmbiente develop, com a origem http://localhost:5173
Staging e QASimSimAmbiente staging ou qa, com a origem da app
ProduçãoNãoSimAmbiente production, só para erros

O Mira só aceita chamadas e logins vindos das origens cadastradas no ambiente. Por isso, cada ambiente da tabela precisa existir no projeto.

Núcleo da integração

Passos obrigatórios

Cadastrar o ambiente e as origens

Quem faz: admin.

  1. Abra o menu do projeto, clique em Configurações do projeto e entre em Ambientes. O ambiente criado com o projeto já tem a origem da URL do app.
  2. Clique em Novo ambiente.
  3. Dê um nome, como staging, e liste em Origens uma origem por linha. Cadastre a origem exata, com a porta quando houver, ou um padrão com *, como https://*.loja-demo.test.
  4. Salve. Repita para cada ambiente da tabela acima.
Lista de ambientes do projeto com as origens de cada um
Ambientes do projeto, cada um com suas origens.
Formulário de novo ambiente com o campo Origens preenchido
O campo Origens aceita uma origem por linha.

Anote também o ID do projeto, que está em Configurações, Geral, com um botão de copiar. Você usa esse valor na etapa B.

Liberar a CSP

Quem faz: dev.

Se a app define uma Content-Security-Policy, ela precisa deixar a página falar com o Mira. Adicione a URL da instância em connect-src:

connect-src 'self' https://mira.example.com;
script-src 'self' https://mira.example.com;

A interface do widget não vai no pacote: a página a importa da instância, em https://mira.example.com/widget/v1/widget.js, na primeira vez que o widget abre. Por isso a CSP também precisa de script-src para a instância. Se o módulo não carregar, o widget não abre e o console mostra [Mira] widget indisponível na instância.

O login do widget abre uma aba do dashboard, que não passa pela CSP da app. Se você ativar a captura de erros (etapa A), libere também o host do DSN em connect-src. Ele é o mesmo da instância.

Instalar o bridge

Quem faz: dev.

O Mira serve os pacotes do SDK pela própria URL, sem login. Instale o bridge pela URL da instância:

npm install https://mira.example.com/downloads/sdk/mira-bridge-0.15.0.tgz

O pacote pede React 19 e react-dom como peers, porque o ErrorBoundary e o widget usam o React da app. O lockfile fixa a integridade do arquivo. Uma versão publicada nunca muda, e as antigas continuam disponíveis. Para atualizar, troque a versão na URL.

Sem bundler, a instância também serve o widget como script. Cole no <head>, antes dos scripts da app, e pule o bootstrap.ts da próxima etapa:

<script src="https://mira.example.com/widget/v1/mira.js"></script>
<script>
  mira.init({ widget: { instanceUrl: "https://mira.example.com", trigger: "button" } });
</script>

O Guia de configuração do projeto mostra o mesmo trecho na aba Script, com a URL da instância preenchida. Pela tag de script, a CSP também bloqueia o mira.init inline: mova a chamada para um arquivo .js da app ou autorize-a com nonce.

Ativar o widget

Quem faz: dev.

Crie um bootstrap que inicializa o bridge antes da app e só então carrega o resto. Assim o bridge captura também os erros que acontecem durante o carregamento dos módulos.

// src/main.tsx
import "./bootstrap";

Escolha o ambiente na aba. Cada uma traz o .env e o bootstrap.ts correspondentes.

# .env.development
VITE_MIRA_URL=https://mira.example.com
// src/bootstrap.ts
import { mira } from "@mira/bridge";
import { widgetIntegration } from "@mira/bridge/widget";

mira.init({
  integrations: [widgetIntegration({ instanceUrl: import.meta.env.VITE_MIRA_URL, trigger: "button" })],
});

await import("./app");

Rode a app em http://localhost:5173 (ou na porta que você cadastrou) e use essa origem.

Em src/app.tsx, fica o conteúdo do antigo main.tsx: o createRoot e a renderização.

O parâmetro trigger escolhe como o widget abre:

triggerEfeito
"button" (padrão)Botão flutuante com o símbolo do Mira e o atalho Alt+Shift+M
"shortcut"Só o atalho. Troque a combinação com shortcut: "Ctrl+Shift+M"
"manual"Nenhuma entrada visível. Chame mira.open() a partir de um item de menu da app

O widget sempre abre num painel junto do botão. Sem botão ("shortcut" e "manual"), o painel fica no canto inferior direito. A opção mode das versões antigas é ignorada.

Para o widget copiar o link do report depois do envio, a página precisa permitir clipboard-write. Se a app roda o widget num iframe, declare allow="clipboard-write" nele. Sem a permissão, o painel mostra o link para copiar à mão.

Verificar

Quem faz: dev e admin.

  1. Abra a app no ambiente configurado. O botão do Mira aparece no canto da página.
Botão flutuante do Mira no canto de uma página
O botão do widget no canto da app.
  1. Clique no botão. Na primeira vez, o widget pede o login. Clique em Entrar: o painel mostra um código, e Aprovar no Mira abre o dashboard numa aba nova. Entre, confira que o código é o do painel e aprove o projeto e o ambiente que o Mira resolveu para a origem da app.
Painel do widget pedindo para entrar
Sem sessão, o widget pede para entrar.
  1. Faça uma captura pelo menu do botão, ou escolha Novo report. O report abre num diálogo: o tipo começa em Bug (troque para Melhoria ou Sugestão se for o caso), preencha o título e a descrição (em Markdown) e clique em Criar.
Formulário de bug no widget com título e descrição preenchidos
O formulário de um bug, com as evidências automáticas embaixo.
  1. O painel troca o formulário por Report enviado.
Confirmação Report enviado no widget
O Mira confirmou o recebimento.
  1. O admin abre o dashboard e confere que o report chegou à triagem do ambiente.
Report novo na lista de triagem
O report enviado pelo widget na triagem do projeto.

Se o botão não aparece ou o login falha, confira nesta ordem: a origem cadastrada bate com a da barra de endereço (incluindo a porta), a CSP libera a instância, o navegador não bloqueou a aba de aprovação e nenhum <dialog> modal está aberto por cima da página.

Etapas opcionais

A. Capturar erros com o DSN

Quem faz: admin gera a chave, dev configura a app. Vale para staging, QA e produção.

O DSN ativa o SDK de erros. Ele tem o formato https://<chave>@<host-do-mira>/<id-do-ambiente>, e a chave define o ambiente. Ela é pública e só escreve ocorrências daquele ambiente, então pode ir no bundle.

Gerar a chave

Quem faz: admin.

  1. Em Configurações do projeto, Erros, escolha o ambiente no seletor. A seção mostra o nível de dados e as chaves de ingestão.
  2. Dê um nome à chave, como web, e clique em Gerar chave.
  3. Copie o DSN pelo botão da linha.
Painel Erros do ambiente com nível de dados e chaves de ingestão
O painel Erros de um ambiente.
Chave de ingestão gerada com o DSN e o botão de copiar
A chave gerada e o botão que copia o DSN.

Cada chave vale só para o ambiente em que foi gerada. Revogar não tem volta e faz as apps com aquele DSN pararem de enviar.

Configurar a app

Quem faz: dev.

Coloque o DSN em VITE_MIRA_DSN e use o bootstrap.ts da aba de staging ou de produção da etapa 4 (Ativar o widget). A release identifica a versão (1.4.0+abc1234), e o buildTime permite ao Mira reabrir sozinho um erro resolvido quando um build novo volta a falhar.

Libere o host do DSN em connect-src. A origem da app precisa estar cadastrada no ambiente, porque a ingestão confere a origem dos envios do navegador.

Conferir

Quem faz: dev e admin.

Provoque um erro na app e abra Erros no projeto. A ocorrência aparece agrupada em um erro novo.

Lista de erros com um erro novo da app de teste
O erro enviado pela app, agrupado na lista.

O que o SDK captura, as opções de init, a captura manual e a redação estão em SDK.

B. Enviar source maps no CI

Quem faz: admin cria a credencial, dev configura o build.

Sem source maps, a stack de uma ocorrência chega minificada. O plugin Vite do @mira/sourcemaps gera os maps, injeta um Debug ID em cada script, envia os maps ao Mira e apaga os .map do dist. Os maps nunca vão para o servidor da app.

Criar a credencial de serviço

Quem faz: admin.

  1. Abra Admin, Serviços de API, e crie um serviço com os projetos da app.
  2. Ative só a permissão Permitir envio de source maps e desative as consultas.
  3. Em Chaves, informe nome e validade e use Emitir chave. O segredo (mira_svc_...) aparece uma vez; salve no gerenciador de segredos do CI.

Veja os detalhes em Tokens.

Instalar o plugin

Quem faz: dev.

npm install --save-dev https://mira.example.com/downloads/sdk/mira-sourcemaps-0.1.1.tgz
// vite.config.ts
import { miraSourceMaps } from "@mira/sourcemaps/vite";
import react from "@vitejs/plugin-react";
import { defineConfig, loadEnv } from "vite";

export default defineConfig(({ mode }) => {
  // Lê os `.env` do modo (`.env.production`, `.env.staging`) junto com o ambiente do CI.
  const env = loadEnv(mode, process.cwd(), "VITE_");

  return {
    plugins: [
      react(),
      miraSourceMaps({
        release: `${env.VITE_VERSION}+${env.VITE_BUILD_SHA}`,
        buildTime: env.VITE_BUILD_TIME,
      }),
    ],
  };
});

Use a mesma release e o mesmo buildTime do mira.init, que lê os mesmos valores de import.meta.env.

Configurar o CI

Quem faz: dev.

O plugin lê três variáveis de ambiente:

VariávelValor
MIRA_URLhttps://mira.example.com. Precisa de https, porque o token vai num header; http só vale para localhost
MIRA_PROJECT_IDO ID do projeto, de Configurações, Geral
MIRA_SOURCEMAPS_TOKENA credencial mira_svc_ da etapa anterior
# .github/workflows/deploy.yml
- run: pnpm build
  env:
    MIRA_URL: https://mira.example.com
    MIRA_PROJECT_ID: ${{ vars.MIRA_PROJECT_ID }}
    MIRA_SOURCEMAPS_TOKEN: ${{ secrets.MIRA_SOURCEMAPS_TOKEN }}
- run: pnpm exec mira-sourcemaps check dist

O check falha se sobrar um .map no diretório ou se um .js ou .css tiver map inline (sourceMappingURL=data:). Rode antes de publicar.

Fora do Vite, o mesmo pacote traz o comando mira-sourcemaps upload <dir> --release <release> para um dist já gerado.

O que o Mira armazena do código depende do nível de código do projeto, em Configurações, Geral: sem código, só mapeamento (padrão) ou completo.

C. Expor usuário e estado da app

Quem faz: dev.

Versão e ambiente. O contexto vai junto de cada report:

mira.setContext({
  version: import.meta.env.VITE_BUILD_SHA,
  env: import.meta.env.MODE,
});

setContext substitui o contexto inteiro. Para o usuário, chame as duas funções no login e no logout:

mira.setContext({ version, env, appUser: { id: user.id, email: user.email } });
mira.setUser({ id: user.id, email: user.email });

// no logout
mira.setUser(null);

setContext vai para os reports e setUser para as ocorrências de erro. Depois do logout, o SDK volta ao id anônimo.

Estado. Registre um provider por fonte de estado. Ele só roda quando alguém envia um report e marca o contexto e estado da app entre as evidências.

import { dehydrate } from "@tanstack/react-query";

mira.register("tanstack-query", () => dehydrate(queryClient));
mira.register("router", () => router.state.location);

Um provider que lança erro ou demora mais de 2 segundos é ignorado, e o report segue sem aquele snapshot.

Problemas comuns

SintomaCausa provável
O botão não apareceO bridge não foi inicializado nessa build, ou a app roda com a variável VITE_MIRA_URL vazia
O login do widget diz que não há ambiente para a origemA origem da barra de endereço não está cadastrada no ambiente
A aprovação do login não terminaO código expira em 10 minutos. Clique em Entrar de novo e aprove o código novo, na mesma instância
O widget não recebe focoUm <dialog> modal da app está aberto, ou uma biblioteca de focus trap bloqueia o foco. Feche o modal ou crie uma exceção para o host <mira-widget>
Os envios do SDK falham com erro de CSPO host do Mira não está em connect-src
A stack das ocorrências chega minificadaOs source maps não foram enviados para essa release, ou a release do build difere da do init

Próximos passos

Nesta página