Taggor

Rascunho · Recursos

O que o Taggor faz hoje

Cada linha abaixo está construída e tem uma página da documentação ou um caminho testado por trás. Nada aqui é plano.

01

Recursos

Fig. 1 · Recursos, cada um com a página que o explica
RecursoO que fazSaiba mais
SDKSeu agente escreve um componente em TypeScript com um contrato tipado: props, eventos, slots e os dados que ele pode coletar.Docs
Verificação na sua máquinaOs portões da publicação (tipos, tamanho, segurança) rodam localmente, sem rede, antes de qualquer envio.Docs
EstilosCSS, SCSS e Tailwind (configurado só em CSS), isolados no componente.Docs
AcessibilidadeO comportamento por teclado e leitor de tela dentro do Shadow DOM, inclusive em campos de formulário, é testado nos modelos.Docs
Build em sandboxO código-fonte é construído num contêiner isolado, longe da sua máquina e dos servidores do próprio Taggor.Docs
Versões imutáveisCada publicação é uma nova versão endereçada pelo conteúdo. Uma versão não muda; uma mudança é uma nova versão.Docs
CanaisUm canal (staging, production) aponta para uma versão. Promover o move; os sites que usam o canal o acompanham.Docs
RollbackAponte um canal de volta para a versão anterior pela CLI ou pelo portal. Nada é reconstruído.Docs
Prévia privadaCada build pode ser visto num link privado e temporário antes de chegar a um canal.Docs
Um snippet por siteUma tag de script assíncrona por site carrega um loader pequeno que busca só os componentes que aquele site usa.Docs
Domínios permitidosO site lista os domínios onde seus componentes montam. Isso impede que um snippet copiado funcione em outro lugar; não é controle de acesso.Docs
Valores por siteO mesmo componente pode ter valores padrão diferentes em cada site, definidos sem uma nova versão.Docs
Dados coletadosO componente declara coleções no manifesto; os envios são validados contra o schema, checados contra spam e guardados para você.Docs
ConsentimentoQuando o componente declara dado pessoal, ele mostra a caixa de consentimento do Taggor e cada envio leva a prova do que o visitante aceitou.Docs
ExportaçãoOs envios aparecem no portal e são exportados em CSV ou NDJSON pelo portal e pela CLI.Docs
PortalSites, componentes, versões, prévias, props e promover ou reverter, sem a linha de comando.
Feito para agentesllms.txt, uma página de configuração para agentes e uma skill para agentes de código.
Hospedeiros e navegadoresOs componentes rodam numa matriz de HTML puro, Content-Security-Policy estrita, Next.js, um app React de página única e WordPress, no Chromium, no Firefox e no WebKit.

02

Experimente

Três componentes reais, um de cada vez. Mexa nos controles: o componente e o código do seu framework mudam juntos.

Demonstração
<contact-form>
Visão

Props

Destaque
Cantos
contact-form: um formulário que guarda contatos com o consentimento do visitante. Uma imagem do componente real, desenhada a partir do próprio código. Os controles mudam a imagem e o código ao lado; nada aqui é enviado nem guardado.

Gerado a partir do manifesto do componente e dos valores acima.

Código para

index.html

<contact-form
  headline="Ask about your site"
  privacy-policy="https://example.com/privacy"
></contact-form>

<script>
  const element = document.querySelector("contact-form");
  element.addEventListener("contact-form:submitted", (event) => {
    console.log(event.detail);
  });
</script>
  • Adicione o script do Taggor do site uma vez; o componente aparece quando ele carrega.

taggor-component.js

const element = document.createElement("contact-form");
element.setAttribute("headline", "Ask about your site");
element.setAttribute("privacy-policy", "https://example.com/privacy");
element.addEventListener("contact-form:submitted", (event) => {
  console.log(event.detail);
});
document.body.append(element);
  • Adicione o script do Taggor do site uma vez; o componente aparece quando ele carrega.

ContactForm.tsx

import { useEffect, useRef } from "react";

export function ContactForm() {
  const ref = useRef<HTMLElement>(null);

  useEffect(() => {
    const element = ref.current;
    if (!element) return;
    const onSubmitted = (event: Event) => {
      console.log((event as CustomEvent).detail);
    };
    element.addEventListener("contact-form:submitted", onSubmitted);
    return () => {
      element.removeEventListener("contact-form:submitted", onSubmitted);
    };
  }, []);

  return <contact-form
      ref={ref}
      headline="Ask about your site"
      privacy-policy="https://example.com/privacy"
    />;
}
  • Adicione o script do Taggor do site uma vez; o componente aparece quando ele carrega.
  • O React 18 manda toda prop de um custom element como atributo de texto.
  • O evento é ouvido com addEventListener, dentro de um efeito.

ContactForm.tsx

import { useEffect, useRef } from "react";

export function ContactForm() {
  const ref = useRef<HTMLElement>(null);

  useEffect(() => {
    const element = ref.current;
    if (!element) return;
    const onSubmitted = (event: Event) => {
      console.log((event as CustomEvent).detail);
    };
    element.addEventListener("contact-form:submitted", onSubmitted);
    return () => {
      element.removeEventListener("contact-form:submitted", onSubmitted);
    };
  }, []);

  return <contact-form
      ref={ref}
      headline="Ask about your site"
      privacy-policy="https://example.com/privacy"
    />;
}
  • Adicione o script do Taggor do site uma vez; o componente aparece quando ele carrega.
  • O React 19 define uma propriedade quando o elemento já a tem e um atributo no resto.
  • O evento é ouvido com addEventListener, dentro de um efeito.

src/ContactForm.vue

<script setup lang="ts">
function onSubmitted(event: Event) {
  console.log((event as CustomEvent).detail);
}
</script>

<template>
  <contact-form
    headline="Ask about your site"
    privacy-policy="https://example.com/privacy"
    @contact-form:submitted="onSubmitted"
  />
</template>

vite.config.ts

import vue from "@vitejs/plugin-vue";
import { defineConfig } from "vite";

export default defineConfig({
  plugins: [
    vue({
      template: {
        compilerOptions: {
          isCustomElement: (tag) => tag === "contact-form",
        },
      },
    }),
  ],
});
  • Adicione o script do Taggor do site uma vez; o componente aparece quando ele carrega.
  • O vite.config.ts avisa o Vue de que esta tag não é um componente Vue.

src/app/contact-form.component.ts

import { afterNextRender, Component, CUSTOM_ELEMENTS_SCHEMA, DestroyRef, ElementRef, inject } from "@angular/core";

@Component({
  selector: "app-contact-form",
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  template: `
    <contact-form
      headline="Ask about your site"
      privacy-policy="https://example.com/privacy"
    ></contact-form>
  `,
})
export class ContactFormComponent {
  constructor() {
    const host = inject<ElementRef<HTMLElement>>(ElementRef);
    const element = () => host.nativeElement.querySelector("contact-form");
    const onSubmitted = (event: Event) => {
      console.log((event as CustomEvent).detail);
    };
    afterNextRender(() => element()?.addEventListener("contact-form:submitted", onSubmitted));
    inject(DestroyRef).onDestroy(() => element()?.removeEventListener("contact-form:submitted", onSubmitted));
  }
}
  • Adicione o script do Taggor do site uma vez; o componente aparece quando ele carrega.
  • O componente declara CUSTOM_ELEMENTS_SCHEMA.
  • O evento é ouvido com addEventListener, dentro de um efeito.

src/TaggorComponent.svelte

<script>
  function onSubmitted(event) {
    console.log(event.detail);
  }
</script>

<contact-form
  headline="Ask about your site"
  privacy-policy="https://example.com/privacy"
  oncontact-form:submitted={onSubmitted}
></contact-form>
  • Adicione o script do Taggor do site uma vez; o componente aparece quando ele carrega.

Como um agente leva um componente assim a um site:

taggor checktaggor publish

As variáveis CSS que o componente expõe, definidas como a página de um cliente faria.

styles.css

contact-form {
  --cf-accent: #0a7d5a;
  --cf-radius: 6px;
}

O que este formulário coleta

Cada envio vira uma linha no seu workspace, com o consentimento que o visitante deu.

Coleção: contacts
CampoTipoRegra
namestringobrigatório
emailemailobrigatório
messagestringopcional

Declarado como dado pessoal: o formulário mostra a caixa de consentimento e guarda a prova.

Uma linha, como é guardada

{
  "name": "Ada Example",
  "email": "ada@example.com",
  "message": "Can the form email me every new lead?"
}

Dados de exemplo inventados (endereço reservado example.com). Nada desta página é guardado. Este painel é uma descrição: a imagem não envia nada.

<quote-wizard>
Visão

Props

Destaque
Cantos
Um por linha, assim: nome, preço. A imagem mostra três.
Moeda
quote-wizard: quatro passos, uma estimativa ao vivo e um pedido de orçamento. Uma imagem do componente real, desenhada a partir do próprio código. Os controles mudam a imagem e o código ao lado; nada aqui é enviado nem guardado.

Gerado a partir do manifesto do componente e dos valores acima.

Código para

index.html

<quote-wizard currency="USD" locale="en"></quote-wizard>

<script>
  const element = document.querySelector("quote-wizard");
  element.addEventListener("quote-wizard:step", (event) => {
    console.log(event.detail);
  });
  element.addEventListener("quote-wizard:submitted", (event) => {
    console.log(event.detail);
  });
</script>
  • Adicione o script do Taggor do site uma vez; o componente aparece quando ele carrega.

taggor-component.js

const element = document.createElement("quote-wizard");
element.setAttribute("currency", "USD");
element.setAttribute("locale", "en");
element.addEventListener("quote-wizard:step", (event) => {
  console.log(event.detail);
});
element.addEventListener("quote-wizard:submitted", (event) => {
  console.log(event.detail);
});
document.body.append(element);
  • Adicione o script do Taggor do site uma vez; o componente aparece quando ele carrega.

QuoteWizard.tsx

import { useEffect, useRef } from "react";

export function QuoteWizard() {
  const ref = useRef<HTMLElement>(null);

  useEffect(() => {
    const element = ref.current;
    if (!element) return;
    const onStep = (event: Event) => {
      console.log((event as CustomEvent).detail);
    };
    element.addEventListener("quote-wizard:step", onStep);
    const onSubmitted = (event: Event) => {
      console.log((event as CustomEvent).detail);
    };
    element.addEventListener("quote-wizard:submitted", onSubmitted);
    return () => {
      element.removeEventListener("quote-wizard:step", onStep);
      element.removeEventListener("quote-wizard:submitted", onSubmitted);
    };
  }, []);

  return <quote-wizard ref={ref} currency="USD" locale="en" />;
}
  • Adicione o script do Taggor do site uma vez; o componente aparece quando ele carrega.
  • O React 18 manda toda prop de um custom element como atributo de texto.
  • O evento é ouvido com addEventListener, dentro de um efeito.

QuoteWizard.tsx

import { useEffect, useRef } from "react";

export function QuoteWizard() {
  const ref = useRef<HTMLElement>(null);

  useEffect(() => {
    const element = ref.current;
    if (!element) return;
    const onStep = (event: Event) => {
      console.log((event as CustomEvent).detail);
    };
    element.addEventListener("quote-wizard:step", onStep);
    const onSubmitted = (event: Event) => {
      console.log((event as CustomEvent).detail);
    };
    element.addEventListener("quote-wizard:submitted", onSubmitted);
    return () => {
      element.removeEventListener("quote-wizard:step", onStep);
      element.removeEventListener("quote-wizard:submitted", onSubmitted);
    };
  }, []);

  return <quote-wizard ref={ref} currency="USD" locale="en" />;
}
  • Adicione o script do Taggor do site uma vez; o componente aparece quando ele carrega.
  • O React 19 define uma propriedade quando o elemento já a tem e um atributo no resto.
  • O evento é ouvido com addEventListener, dentro de um efeito.

src/QuoteWizard.vue

<script setup lang="ts">
function onStep(event: Event) {
  console.log((event as CustomEvent).detail);
}

function onSubmitted(event: Event) {
  console.log((event as CustomEvent).detail);
}
</script>

<template>
  <quote-wizard
    currency="USD"
    locale="en"
    @quote-wizard:step="onStep"
    @quote-wizard:submitted="onSubmitted"
  />
</template>

vite.config.ts

import vue from "@vitejs/plugin-vue";
import { defineConfig } from "vite";

export default defineConfig({
  plugins: [
    vue({
      template: {
        compilerOptions: {
          isCustomElement: (tag) => tag === "quote-wizard",
        },
      },
    }),
  ],
});
  • Adicione o script do Taggor do site uma vez; o componente aparece quando ele carrega.
  • O vite.config.ts avisa o Vue de que esta tag não é um componente Vue.

src/app/quote-wizard.component.ts

import { afterNextRender, Component, CUSTOM_ELEMENTS_SCHEMA, DestroyRef, ElementRef, inject } from "@angular/core";

@Component({
  selector: "app-quote-wizard",
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  template: `
    <quote-wizard currency="USD" locale="en"></quote-wizard>
  `,
})
export class QuoteWizardComponent {
  constructor() {
    const host = inject<ElementRef<HTMLElement>>(ElementRef);
    const element = () => host.nativeElement.querySelector("quote-wizard");
    const onStep = (event: Event) => {
      console.log((event as CustomEvent).detail);
    };
    afterNextRender(() => element()?.addEventListener("quote-wizard:step", onStep));
    inject(DestroyRef).onDestroy(() => element()?.removeEventListener("quote-wizard:step", onStep));
    const onSubmitted = (event: Event) => {
      console.log((event as CustomEvent).detail);
    };
    afterNextRender(() => element()?.addEventListener("quote-wizard:submitted", onSubmitted));
    inject(DestroyRef).onDestroy(() => element()?.removeEventListener("quote-wizard:submitted", onSubmitted));
  }
}
  • Adicione o script do Taggor do site uma vez; o componente aparece quando ele carrega.
  • O componente declara CUSTOM_ELEMENTS_SCHEMA.
  • O evento é ouvido com addEventListener, dentro de um efeito.

src/TaggorComponent.svelte

<script>
  function onStep(event) {
    console.log(event.detail);
  }

  function onSubmitted(event) {
    console.log(event.detail);
  }
</script>

<quote-wizard
  currency="USD"
  locale="en"
  onquote-wizard:step={onStep}
  onquote-wizard:submitted={onSubmitted}
></quote-wizard>
  • Adicione o script do Taggor do site uma vez; o componente aparece quando ele carrega.

Como um agente leva um componente assim a um site:

taggor checktaggor publish

As variáveis CSS que o componente expõe, definidas como a página de um cliente faria.

styles.css

quote-wizard {
  --qw-radius: 10px;
}
<quiz-result>
Visão

Props

Destaque
Cantos
A pergunta primeiro, depois uma resposta por linha.
quiz-result: uma pergunta por tela e um resultado escolhido pelas respostas. Uma imagem do componente real, desenhada a partir do próprio código. Os controles mudam a imagem e o código ao lado; nada aqui é enviado nem guardado.

Gerado a partir do manifesto do componente e dos valores acima.

Código para

index.html

<quiz-result locale="en"></quiz-result>

<script>
  const element = document.querySelector("quiz-result");
  element.addEventListener("quiz-result:answered", (event) => {
    console.log(event.detail);
  });
  element.addEventListener("quiz-result:completed", (event) => {
    console.log(event.detail);
  });
</script>
  • Adicione o script do Taggor do site uma vez; o componente aparece quando ele carrega.

taggor-component.js

const element = document.createElement("quiz-result");
element.setAttribute("locale", "en");
element.addEventListener("quiz-result:answered", (event) => {
  console.log(event.detail);
});
element.addEventListener("quiz-result:completed", (event) => {
  console.log(event.detail);
});
document.body.append(element);
  • Adicione o script do Taggor do site uma vez; o componente aparece quando ele carrega.

QuizResult.tsx

import { useEffect, useRef } from "react";

export function QuizResult() {
  const ref = useRef<HTMLElement>(null);

  useEffect(() => {
    const element = ref.current;
    if (!element) return;
    const onAnswered = (event: Event) => {
      console.log((event as CustomEvent).detail);
    };
    element.addEventListener("quiz-result:answered", onAnswered);
    const onCompleted = (event: Event) => {
      console.log((event as CustomEvent).detail);
    };
    element.addEventListener("quiz-result:completed", onCompleted);
    return () => {
      element.removeEventListener("quiz-result:answered", onAnswered);
      element.removeEventListener("quiz-result:completed", onCompleted);
    };
  }, []);

  return <quiz-result ref={ref} locale="en" />;
}
  • Adicione o script do Taggor do site uma vez; o componente aparece quando ele carrega.
  • O React 18 manda toda prop de um custom element como atributo de texto.
  • O evento é ouvido com addEventListener, dentro de um efeito.

QuizResult.tsx

import { useEffect, useRef } from "react";

export function QuizResult() {
  const ref = useRef<HTMLElement>(null);

  useEffect(() => {
    const element = ref.current;
    if (!element) return;
    const onAnswered = (event: Event) => {
      console.log((event as CustomEvent).detail);
    };
    element.addEventListener("quiz-result:answered", onAnswered);
    const onCompleted = (event: Event) => {
      console.log((event as CustomEvent).detail);
    };
    element.addEventListener("quiz-result:completed", onCompleted);
    return () => {
      element.removeEventListener("quiz-result:answered", onAnswered);
      element.removeEventListener("quiz-result:completed", onCompleted);
    };
  }, []);

  return <quiz-result ref={ref} locale="en" />;
}
  • Adicione o script do Taggor do site uma vez; o componente aparece quando ele carrega.
  • O React 19 define uma propriedade quando o elemento já a tem e um atributo no resto.
  • O evento é ouvido com addEventListener, dentro de um efeito.

src/QuizResult.vue

<script setup lang="ts">
function onAnswered(event: Event) {
  console.log((event as CustomEvent).detail);
}

function onCompleted(event: Event) {
  console.log((event as CustomEvent).detail);
}
</script>

<template>
  <quiz-result
    locale="en"
    @quiz-result:answered="onAnswered"
    @quiz-result:completed="onCompleted"
  />
</template>

vite.config.ts

import vue from "@vitejs/plugin-vue";
import { defineConfig } from "vite";

export default defineConfig({
  plugins: [
    vue({
      template: {
        compilerOptions: {
          isCustomElement: (tag) => tag === "quiz-result",
        },
      },
    }),
  ],
});
  • Adicione o script do Taggor do site uma vez; o componente aparece quando ele carrega.
  • O vite.config.ts avisa o Vue de que esta tag não é um componente Vue.

src/app/quiz-result.component.ts

import { afterNextRender, Component, CUSTOM_ELEMENTS_SCHEMA, DestroyRef, ElementRef, inject } from "@angular/core";

@Component({
  selector: "app-quiz-result",
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  template: `
    <quiz-result locale="en"></quiz-result>
  `,
})
export class QuizResultComponent {
  constructor() {
    const host = inject<ElementRef<HTMLElement>>(ElementRef);
    const element = () => host.nativeElement.querySelector("quiz-result");
    const onAnswered = (event: Event) => {
      console.log((event as CustomEvent).detail);
    };
    afterNextRender(() => element()?.addEventListener("quiz-result:answered", onAnswered));
    inject(DestroyRef).onDestroy(() => element()?.removeEventListener("quiz-result:answered", onAnswered));
    const onCompleted = (event: Event) => {
      console.log((event as CustomEvent).detail);
    };
    afterNextRender(() => element()?.addEventListener("quiz-result:completed", onCompleted));
    inject(DestroyRef).onDestroy(() => element()?.removeEventListener("quiz-result:completed", onCompleted));
  }
}
  • Adicione o script do Taggor do site uma vez; o componente aparece quando ele carrega.
  • O componente declara CUSTOM_ELEMENTS_SCHEMA.
  • O evento é ouvido com addEventListener, dentro de um efeito.

src/TaggorComponent.svelte

<script>
  function onAnswered(event) {
    console.log(event.detail);
  }

  function onCompleted(event) {
    console.log(event.detail);
  }
</script>

<quiz-result
  locale="en"
  onquiz-result:answered={onAnswered}
  onquiz-result:completed={onCompleted}
></quiz-result>
  • Adicione o script do Taggor do site uma vez; o componente aparece quando ele carrega.

Como um agente leva um componente assim a um site:

taggor checktaggor publish

As variáveis CSS que o componente expõe, definidas como a página de um cliente faria.

styles.css

quiz-result {
  --qz-radius: 12px;
}

03

Fora desta lista

Plugins para plataformas específicas e cobrança não fazem parte desta lista. Um recurso aparece aqui quando está construído.