Especificação do Projeto: Populator
- Visão Geral do Projeto Problema: Designers gastam muito tempo preenchendo manualmente dados reais (título, preços, tags e imagens) em cards de produto durante a prototipagem.
Objetivo: Criar um plugin do Figma que popula automaticamente até 10 cards selecionados com dados dinâmicos vindos de uma planilha pública do Google Sheets.
Abordagem de Imagens: Para garantir performance e consistência visual, as imagens não serão baixadas da internet. O plugin irá alterar a variante de um componente de imagem interno no Figma, baseado no nome do produto vindo da planilha.
- Arquitetura Técnica O plugin é dividido em duas partes (Sandbox e UI) que se comunicam via mensagens:
Interface (UI - ui.html / ui.ts): Roda em um iframe. Faz o fetch dos dados da planilha do Google Sheets (formato CSV) e envia o array de produtos para o Figma.
Core do Figma (Sandbox - code.ts): Recebe os dados, identifica os elementos selecionados na tela, varre as camadas filhas por nome e injeta os textos e troca as variantes de imagem.
- Contratos de Dados e Estruturas A. Estrutura da Planilha (Google Sheets) A planilha deve ser publicada na web como CSV e conter exatamente estes cabeçalhos na primeira linha: titulo | desconto | preco-pix | centavos | preco-parcelado | imagem | descricao | tags | categoria
Na coluna tags, informe uma lista das tags que devem ficar ligadas para aquele produto.
Tags suportadas: Tags Promocional, Cupom, Internacional, Cliente Ouro,
Tags Logística, Entregue pelo Full, Frete grátis, Receba amanhã,
LMPM, Cashback, Frete grátis Full, Mercado Full, Receba amanhã grátis,
Receba em até 2 dias úteis.
Exemplo de valor da coluna tags:
Tags Promocional|Cupom|Frete grátis
Na coluna categoria, informe a categoria do produto (ex: Eletrônicos, Casa, Moda).
Na UI do plugin, use o select de categoria para popular apenas uma categoria específica
ou Todas.
Nota: Na coluna imagem, o valor será o nome exato da variante (ex: iPhone15, CamisetaPreta).
B. Mapeamento de Camadas no Figma (Convenção de Nomes) O Card de produto no Figma deve conter camadas internas renomeadas com # para que o plugin as encontre:
#titulo -> Tipo: TextNode
#desconto -> Tipo: TextNode
#preco-pix -> Tipo: TextNode
#centavos -> Tipo: TextNode
#preco-parcelado -> Tipo: TextNode
#descricao -> Tipo: TextNode
#imagem -> Tipo: InstanceNode (Instância de um Component Set/Variante. A propriedade de variação deve se chamar Produto).
#tags-bottom-cards -> Tipo: InstanceNode (com propriedades booleanas para as tags suportadas).
- Estrutura de Arquivos (Stack: Vite + TypeScript) Plaintext product-populator/ ├── manifest.json ├── package.json ├── tsconfig.json ├── vite.config.ts └── src/ ├── code.ts (Lógica do Figma - Sandbox) ├── ui.html (Interface HTML/CSS do Plugin) └── ui.ts (Lógica da UI - Fetch do CSV)
- Prompts para o GitHub Copilot (Dividido por Etapas) Você pode copiar e colar os prompts abaixo diretamente no chat do Copilot conforme for criando os arquivos.
📑 Passo 1: Configuração do Ambiente Crie os arquivos de configuração na raiz e use este prompt:
Prompt para o Copilot: "Estou criando um plugin do Figma usando TypeScript e Vite. Gere os arquivos de configuração iniciais para o projeto:
Um package.json com os scripts de build do Vite e as dependências necessárias (incluindo @figma/plugin-typings como devDependency).
Um tsconfig.json configurado para o ambiente do Figma e Vite.
Um vite.config.ts que compile o code.ts em dist/code.js e compile o ui.ts inserindo-o diretamente dentro do dist/ui.html (inline inline-chunks), pois o Figma exige a UI em um arquivo único de HTML.
Um manifest.json válido para a API atual do Figma, apontando o main para dist/code.js e a ui para dist/ui.html."
🌐 Passo 2: O Lado da Interface (src/ui.html e src/ui.ts) Crie a interface que vai disparar a busca dos dados da planilha.
Prompt para o Copilot: "Crie os arquivos da interface do plugin: src/ui.html e src/ui.ts. Em src/ui.html: Crie um layout simples e limpo usando a identidade visual do Figma (Figma Design System). Deve conter um título, um botão com id 'btn-populate' escrito 'Popular Componentes' e uma área para mensagens de erro/sucesso. Em src/ui.ts:
Adicione um listener de clique no botão.
Quando clicado, faça um fetch em uma URL de CSV pública do Google Sheets (use um placeholder de URL por enquanto).
Faça o parse manual do CSV (ou crie uma função simples de split por quebra de linha e vírgula) para transformar as linhas em um Array de Objetos contendo: titulo, desconto, preco-pix, centavos, preco-parcelado, imagem e descricao. Limite a 10 itens.
Envie esse array para o processo principal do Figma usando parent.postMessage({ pluginMessage: { type: 'populate', produtos: dados } }, '*')."
🎨 Passo 3: O Lado do Figma (src/code.ts) Crie a lógica pesada que manipula os elementos dentro do canvas do Figma.
Prompt para o Copilot: "Crie o arquivo src/code.ts usando a API de TypeScript do Figma (@figma/plugin-typings). Ele deve seguir estas regras:
Abrir a UI do plugin com um tamanho padrão de 300x350: figma.showUI(html, { width: 300, height: 350 });.
Escutar as mensagens vindas da UI usando figma.ui.onmessage.
Se o tipo da mensagem for 'populate':
Pegue a seleção atual do usuário no Figma (figma.currentPage.selection).
Valide se há itens selecionados. Se não houver, mande um alerta ou mensagem para a UI.
Itere sobre os itens selecionados (máximo 10). Cada item selecionado corresponde a um índice do array de produtos recebido.
Para cada card selecionado, crie uma função recursiva para buscar nós filhos (children).
Se encontrar um nó de texto (TextNode) com nome #titulo, #desconto, #preco-pix, #centavos, #preco-parcelado ou #descricao, você DEVE carregar a fonte usando await figma.loadFontAsync(node.fontName as FontName) antes de alterar a propriedade node.characters com o respectivo dado da planilha.
Se encontrar um nó do tipo Instância (InstanceNode) chamado #imagem, use o método node.setProperties({ 'Produto': produto.imagem }) para trocar a variante do componente de imagem de acordo com o texto da planilha. Trate possíveis erros caso a propriedade ou variante não exista."