Pular para conteúdo
Logo
Overview
Kiro Ghost: animando o mascote do Kiro com SVGs oficiais e morphing vetorial

Kiro Ghost: animando o mascote do Kiro com SVGs oficiais e morphing vetorial

September 14, 2026
4 min read

Nos meus projetos e artigos recentes sobre o ecossistema do Kiro (como os relatos de 1 ano de Kiro na Dimensa e o repositório de KiroCrew Ports), o assistente aparece como ferramenta de terminal e infraestrutura de trabalho. No meio desses experimentos com agentes e skills, resolvi explorar outra face desse universo: transformar o mascote fantasma do Kiro em um avatar SVG animado e interativo para a web.

O resultado é o kiro-ghost, um projeto open-source em Vue e TypeScript que reproduz o personagem em animação fluida a partir dos contornos oficiais.

Do Bloub ao Kiro Ghost

O projeto começou como um fork do Bloub, criado por Jérémy Perret. O Bloub original é uma realização técnica impressionante: ele animava o mascote do x.ai usando modelagem radial. O corpo era tratado como um perfil circular modulado por raios angulares medidos quadro a quadro a partir de um vídeo de referência.

Para um personagem esférico ou circular, a matemática polar funciona muito bem. O mascote do Kiro, no entanto, tem outra estrutura. Ele é vertical, tem dobras na base, assimetrias marcadas em cada expressão e proporções que variam conforme a inclinação. Tentar encaixar o fantasma em um perfil de raios centrados distorcia o desenho e apagava os traços que definem a silhueta.

Em vez de construir tudo do zero, preservei o motor de estados, a interface reativa e os exportadores do Bloub. A mudança essencial foi substituir a modelagem polar por um pipeline de extração e interpolação vetorial direta.

Extração e normalização de contornos

O repositório armazena as oito poses de referência em reference/ghost-poses/. Para que duas curvas SVG possam transitar suavemente entre si, elas precisam ter a mesma quantidade de pontos e uma correspondência direta de vértices. Se um contorno tiver 50 pontos e o outro 80, ou se o ponto inicial de uma pose começar na base e na outra no topo, a interpolação gera um emaranhado de linhas cruzadas.

A solução foi automatizar esse tratamento no script tools/extract-kiro-poses.mjs:

  1. Varredura dos comandos: o extrator faz o parse dos paths SVG (comandos absolutos M, L, H, V, C e Z) diretamente pelo arquivo, sem depender do DOM do navegador.
  2. Aproximação de Bézier: curvas cúbicas são fragmentadas em passos densos para reproduzir fielmente o traçado original.
  3. Alinhamento do topo: o algoritmo calcula a área orientada da curva e localiza o ponto mais alto da cabeça, garantindo o mesmo vértice inicial em todas as poses.
  4. Reamostragem regular: o contorno do corpo principal é reamostrado em exatamente 128 pontos distribuídos por comprimento de arco.
  5. Olhos e elementos secundários: cada olho recebe 32 pontos normalizados. Elementos avulsos (os accents, como a bolha flutuante da pose 1) são amostrados com 48 pontos.

O resultado desse processamento gera o arquivo src/bot/kiro-poses.ts. Sempre que um SVG de referência precisa de ajuste, o comando pnpm generate:kiro atualiza as coordenadas de forma previsível.

Motor de animação e interpolação

Com a geometria padronizada, a transição entre poses torna-se uma interpolação direta. No arquivo src/bot/kiro.ts, a função blendPoints interpola linearmente as coordenadas dos 128 pontos do corpo e dos 32 pontos de cada olho:

function blendPoints(a: Point[], b: Point[], t: number): Point[] {
return a.map((point, index) => ({
x: lerp(point.x, b[index]!.x, t),
y: lerp(point.y, b[index]!.y, t)
}))
}

Quando a pose seguinte possui elementos que não existem na pose atual (ou vice-versa), o motor aplica um crossfade de opacidade no contorno secundário. Isso permite que detalhes como bolhas surjam e desapareçam sem corte brusco.

Na animação de repouso (idle), a timeline foi ajustada para alternar poses mantendo pausas estáveis. O personagem não fica em mutação contínua: ele repousa por alguns segundos e executa a transição em um intervalo curto, preservando o peso visual da ilustração.

Note

Para garantir que a animação seja reproduzível e testável, o módulo src/bot/ não utiliza relógio de sistema nem importa reatividade do Vue. Toda amostragem é uma função pura do tempo decorrido: sample(t).

Componente e exportação

O projeto expõe o componente Vue BloubBot (nome mantido por compatibilidade com a base herdada), aceitando controles de tamanho, estado, ciclos e direção do olhar:

<BloubBot v-model:state="state" v-model:playing="playing" />
<BloubBot state="orbit" :size="120" :frozen-at="1.2" />

Além da renderização em tela, o projeto preserva a esteira de exportação:

  • SVG animado: gera código vetorial com tags SMIL calculadas a partir dos paths interpolados, rodando nativamente no navegador sem depender de scripts.
  • Formatos rasterizados: exportação em PNG estático, GIF animado e MP4 (utilizando a biblioteca mediabunny carregada sob demanda via import dinâmico).

Stack técnica e atribuição

A base do projeto utiliza:

  • Vue 3.5 e Vite 8 com TypeScript strict
  • Tailwind CSS 4 com @tailwindcss/vite
  • pnpm como gerenciador de pacotes
  • Vitest para testes de regressão matemática e geométrica

O código do Kiro Ghost está sob licença MIT. O projeto é um fork que estende o trabalho de Jérémy Perret no Bloub. Os contornos vetoriais e a identidade visual do mascote pertencem aos seus respectivos detentores (Kiro / AWS), sendo esta uma implementação independente para estudo e desenvolvimento open source.

O código completo e as instruções de execução estão no GitHub.

Leitura Relacionada