CommunityEscrita e Ediçãogithub.com

tjst-t/boxloom

Escreva apresentações como Boxloom Markdown (.bx.md) e converta-as em PPTX nativas e editáveis. Use quando for solicitado a criar uma apresentação / PowerPoint / slides com Boxloom, ou ao editar um arquivo .bx.md. Abrange a sintaxe, como escolher um padrão para cada conteúdo, limites de densidade medidos pelo mecanismo de layout e o ciclo de verificação → correção.

O que é boxloom?

Boxloom é uma skill que permite escrever apresentações em uma sintaxe Markdown própria (.bx.md) e, em seguida, convertê-las em arquivos PPTX nativos e editáveis no PowerPoint. A skill separa o **significado** da **aparência**: você define apenas o conteúdo (listas, comparações, planos), e um modelo (template) decide cores, fontes, margens e posições. O fluxo de trabalho é simples: primeiro, leia o esquema do template com `boxloom schema` para entender os blocos e regras aceitos; depois, escreva o deck em `deck.bx.md`; em seguida, execute `boxloom check` para validar e corrigir erros; por fim, gere o PPTX com `boxloom build`. A skill suporta múltiplos tipos de conteúdo, como gráficos, tabelas, processos, cronogramas (gantt) e imagens, e cada um possui regras específicas de uso e densidade. É útil para desenvolvedores e usuários do editor Claude Code, Cursor ou Codex que precisam criar apresentações de forma programática, mantendo a edição final no PowerPoint. A skill cobre desde a sintaxe básica até escolhas de padrões, limites de layout e o ciclo de verificação e correção.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/tjst-t/boxloom/tree/HEAD/skills/boxloom

Installed? Explore more Escrita e Edição skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Prévia

Do README da skill

texto alt
alt

Documentação

Boxloom: escrevendo decks

Boxloom separa o significado da aparência. Você escreve apenas o que o conteúdo é (uma lista de pontos, uma comparação de opções, um plano com datas). O modelo decide todas as cores, tamanhos de fonte, margens e posições. Você nunca escreve uma cor, um tamanho ou uma coordenada fora do único recurso de escape (shapes, último caso).

O ciclo é sempre:

  1. boxloom schema — leia o que os modelos atuais aceitam (faça isso primeiro).
  2. Escreva deck.bx.md.
  3. boxloom check -format json deck.bx.md — corrija todos os erros e, em seguida, todos os avisos que puder.
  4. Repita o passo 3 até que "ok": true e não haja aviso layout-overflow.
  5. boxloom build -o deck.pptx deck.bx.md (flags antes do arquivo).

Os comandos são executados a partir do diretório boxloom/ do repositório: go run ./cmd/boxloom <schema|check|build|parse> … (Go 1.24+, nenhuma outra dependência).

1. Leia o esquema primeiro

boxloom schema [-template light|dark] imprime um documento JSON. Ele é a fonte da verdade; se este arquivo e o esquema discordarem, o esquema vence.

  • markdown.rules — as regras de sintaxe (lista curta; obedeça a todas).
  • markdown.frontMatter — chaves permitidas no cabeçalho --- (title é obrigatório).
  • templates[].blocks — os blocos cercados (:::name) que este modelo conhece, com inside (onde pode aparecer), contains (o que contém) e minChildren.
  • templates[].subsystems — os tipos de figura (blocos de código ```name), com markdown (suas regras extras) e schema (um JSON Pointer para irSchema fornecendo todas as chaves permitidas).
  • Qualquer coisa não listada é um erro. Não invente nomes de blocos, atributos ou chaves.
  • Os modelos são escolhidos pelo nome (template: light no front matter, ou -template dark). Um modelo personalizado é um arquivo de tabela de valores passado por caminho: -template ./my.json (funciona para schema, check, build, fonts; exemplo examples/templates/forest.json). Quando o deck for construído com um modelo personalizado, execute schema e check com o mesmo -template — os nomes de funções e estilos de texto vêm desse arquivo.
  • variant (# Title {variant=…}) existe na sintaxe, mas os modelos atuais não declaram variantes (templates[].variants está vazio), portanto não a use.

A saída é grande. Para ver apenas o que você precisa:

go run ./cmd/boxloom schema -template light > /tmp/schema.json
python3 -c "import json;d=json.load(open('/tmp/schema.json'));print(json.dumps({'rules':d['markdown']['rules'],'blocks':d['templates'][0]['blocks'],'subsystems':[(x['name'],x['markdown']) for x in d['templates'][0]['subsystems']]},ensure_ascii=False,indent=1))"
python3 -c "import json;d=json.load(open('/tmp/schema.json'));print(json.dumps(d['irSchema']['\$defs']['gantt'],ensure_ascii=False,indent=1))"   # todas as chaves gantt

2. Sintaxe em uma tela

---
title: Movendo o serviço de relatórios para o novo cluster
subtitle: Plano e opções (exemplo fictício)
author: Equipe de Plataforma
date: 2026-11-11
confidential: Interno
disclaimer: Todos os nomes e valores são fictícios
template: light
---

# Suporte do fornecedor ao cluster antigo

:::lead
O cluster antigo perde o suporte do fornecedor em março de 2028, portanto os 14 serviços nele devem migrar antes disso.
:::

- O fornecedor encerra correções de segurança em **2028-03-31**
- 14 serviços ainda estão lá; 9 podem migrar sem alterações de código
- A migração leva cerca de 6 semanas por grupo de serviços

:::source
Aviso de suporte do fornecedor de 2026-09; inventário de serviços até outubro de 2026
:::

:::notes
Notas do apresentador vão aqui. Apenas parágrafos simples e marcadores.
:::
  • # Title inicia um slide. Mantenha o título como uma manchete curta que caiba em uma linha ("Suporte do fornecedor ao cluster antigo"); um título que quebra é avisado (title-wrap). Escreva o que o slide diz — a conclusão — como uma frase em :::lead logo após o título (1–2 linhas). O modelo coloca o lead abaixo do título, fora do corpo.

  • --- não é um separador de slide (é um erro). ## e cabeçalhos mais profundos são erros (um título de grupo é escrito como :::column Title, não como um subcabeçalho).

  • Corpo: parágrafos, marcadores - / 1. (máximo de dois níveis), **ênfase** (apenas um tipo de ênfase), `código`, [texto](url), \ no final para uma quebra de linha significativa. Sem itálico, tachado, notas de rodapé, HTML.

  • Blocos cercados: abra com :::nome e feche com o mesmo número de dois-pontos. Ao aninhar, a cerca externa recebe um dois-ponto a mais que a interna:

    :::::compare
    ::::option Manter o cluster antigo
    :::pros
    - Nenhum trabalho de migração este ano
    :::
    :::cons
    - Nenhuma correção de segurança após março de 2028
    :::
    ::::
    ::::option Migrar para o novo cluster
    :::pros
    - Suportado até 2033
    :::
    :::cons
    - Seis semanas de trabalho por grupo de serviços
    :::
    ::::
    :::::
    
  • :::lead (a mensagem do slide), :::notes (notas do apresentador) e :::source (de onde os números do slide vêm) devem estar no nível superior de um slide, uma vez por slide cada. :::lead é apenas para slides de conteúdo.

  • date, confidential e disclaimer no front matter são escritos uma vez para o deck; o modelo os coloca na capa (e confidential no rodapé). Nunca repita "fictício" / "confidencial" em uma :::note em cada slide.

  • Figuras são blocos de código cercados cujo idioma é o nome do subsistema, corpo em YAML restrito: sem âncoras/aliases (&, *), sem tags, sem valores multilinha, sem blocos |/>; booleanos apenas true/false; datas são strings YYYY-MM ou YYYY-MM-DD; intervalos 2027-01 .. 2027-06. Coloque entre aspas qualquer valor que comece com *, &, ! ou contenha ": ", por exemplo, text: ["**Etapa mais lenta**", 5 dias em média] — um **…** sem aspas no início de um item de fluxo é interpretado como um alias YAML e rejeitado.

3. Escolhendo um padrão para cada conteúdo

Decida o tipo de conteúdo antes de escrever. Aplique estas regras em ordem e use a primeira que corresponder. (Conjunto completo de regras com exemplos bons/ruins: docs/patterns.md §4.)

Disponível agora (verifique boxloom schema — mais podem ter sido adicionados):

ConteúdoUseNotas
Uma quebra de capítulo# Parte 2: Como migramos {type=section}O texto do cabeçalho é o título do capítulo; nada além de :::notes pode vir em seguida. Não é um sumário — quando o deck tem duas ou mais seções, o modelo desenha a lista de capítulos com o atual destacado em cada slide de seção por si só
O slide diz exatamente uma frase; a evidência está em outros slides# A migração deve ser adiantada em dois anos {type=statement}O texto do cabeçalho é a frase (este é o único tipo de slide cujo cabeçalho é uma frase completa); nada além de :::notes e :::source pode vir em seguida. Se você adicionaria razões, use um slide normal com um título curto e a conclusão como :::lead
1–4 números para mostrar fortemente, sem série para comparar::::stat → :::value 3 → 12 {unit=modelos} + rótulo de uma linha dentro5+ números ou uma série temporal é um gráfico/tabela, não stat. O valor é escrito como está e deve conter um dígito. Valor e unidade nunca são quebrados no meio, então mantenha-os curtos — 4 cartões são estreitos (stat-value)
Uma série de números (3+ pontos): classificação, mudança ao longo do tempo, participação em um todo, distribuição, relação de duas quantidades```chartcompare: item / timeSeries / component / frequency / correlation — o tipo de gráfico é escolhido para você (nunca escreva barra/linha/pizza). categories: [...], series: [{name, values: [...]}] (um valor por categoria, números sem aspas, máximo 3 séries), unit opcional, emphasis: [category] (uma série) ou emphasis: true em uma série, stacked: true quando as séries são partes de um total. correlation usa xAxis: {title, unit?}, yAxis e points: [[x, y], …] em vez de categorias. component (participação) tem 1 série e ≤ 6 partes — mescle partes pequenas em "Outros"
Palavras de outra pessoa:::quote Texto da fonte + as palavras dentroA fonte (texto do cabeçalho) é obrigatória. Nunca cite sua própria conclusão
Uma frase para enfatizar dentro de um slide normal:::takeaway + uma fraseNo máximo uma por slide, geralmente no final
Linhas × colunas de texto simples ou númerosTabela GFM: | A | B | + | --- | --- | + linhasA primeira linha é o cabeçalho; toda linha tem uma célula por coluna (table-shape). Sem marcadores de alinhamento (:--, --: são erros); colunas numéricas são alinhadas à direita para você. Células são apenas inline. Uma linha : legenda logo após a tabela é sua legenda. Se a última linha for um total, termine essa linha com {total=last} (: Estimativas {total=last}, ou apenas : {total=last}); ela é desenhada como uma linha de total. Totais não são computados — escreva o valor. Coloque uma unidade uma vez na legenda ou cabeçalho, não em cada célula. Avaliações em células → matrix (abaixo)
Linhas × colunas onde cada célula é uma avaliação (suportado / condicional / não / risco)```matrixcolumns: [A, B], rows: [{label, cells: [{status, text?}]}], legend: {support: Bom} opcional. Uma célula por coluna (matrix-cells). A opção recomendada: emphasis: <texto do cabeçalho da coluna> (exatamente como escrito em columns, matrix-emphasis) — nunca diga "a coluna azul" em prosa. Células que são texto simples ou números são uma tabela, não uma matriz
3–7 etapas sem datas, em uma direção (a saída de uma é a entrada da próxima)```processsteps: [{title, detail?, status?, emphasis?}], caption opcional. Números (1. 2. …) e setas são adicionados para você; processos longos quebram para uma segunda linha. Se você usar status, diga o que significa em legend: {conditional: Precisa de aprovação} (figure-legend)
Duas ou mais opções, cada uma com prós e contras:::compare → :::option → :::pros / :::consSe 3+ critérios compartilhados se aplicam a todas as opções, uma matriz se encaixa melhor (acima)
Um pai com filhos (e netos): configuração de equipe, propriedade```orgchartroot: {title, detail?}, units: [{title, detail?, members: [{title, detail?}]}]. Máximo de 3 níveis. Um status em uma caixa precisa de legend: {conditional: Mais duas pessoas necessárias} — a legenda abaixo do gráfico explica; não explique cores de contorno em uma :::note. Não é para equipes não relacionadas lado a lado
Estágios cuja contagem diminui (visitas → inscrições → pagos)```funnelstages: [{label, value, note?}], unit opcional. value é um número ou texto; larguras de barra são escalonadas, não proporcionais. Taxas de conversão estágio a estágio (↓ 45%) são desenhadas para você a partir de valores numéricos — não as escreva em note; use note para o motivo pelo qual um estágio cai. status precisa de legend. Valores que crescem são avisados (funnel-increase) — use process para etapas simples
Um plano com datas, períodos, prazos, status ao longo do tempo```ganttEstados são support, conditional, none, danger (funções, não cores). Períodos de hardware/risco de suporte são um grupo risk: A .. B. Anotações apontam para um id de grupo/linha via target; o subsistema as posiciona
2–3 grupos paralelos lidos lado a lado ("este ano / próximo ano / não fazendo")::::columns → :::column Título do grupo (2 ou 3)Cada grupo contém parágrafos, marcadores, uma tabela, uma imagem, um ```chart ou :::note. Sem colunas aninhadas, compare, galeria ou outras figuras. Gráfico + sua leitura lado a lado: gráfico em um grupo, os takeaways como marcadores no outro. Larguras não são números: marque o grupo principal como {role=main} (os outros suportam) ou deixe todos iguais. 4+ grupos de uma linha → marcadores. Não é para um argumento dividido em dois
Uma imagem que mostra o ponto (captura de tela, foto, desenho)um parágrafo contendo apenas ![texto alt](images/x.png "legenda")Texto alt é obrigatório (image-alt). O caminho é relativo ao arquivo do deck; sem URLs, caminhos absolutos ou .. (image-path). Apenas PNG ou JPEG (image-format). Mantido em proporção, nunca cortado. Imagem + texto lado a lado → ::::columns com a imagem em um grupo
2–6 imagens comparadas ou em sequênciaum parágrafo com 2–6 ![alt](caminho "legenda")Torna-se uma galeria (uma linha para 2–3, uma grade para 4–6). 7+ é um erro: divida o slide
Pontos paralelosmarcadoresMáximo de 2 níveis
Prosa conectadaparágrafo2–3 frases
O que o slide diz: sua conclusão em uma ou duas frases:::lead no nível superior de um slide de conteúdo, um parágrafoTodo slide de conteúdo ganha um. Colocado pelo modelo logo abaixo do título, fora do corpo; ele ocupa espaço do corpo (1 linha ≈ 32 pt, 2 linhas ≈ 57 pt). Quando precisa de duas linhas, o mecanismo quebra após o final de uma frase (。) ou, não sendo possível, após uma vírgula (、) sem adicionar uma linha — então duas frases curtas são melhores para leitura. Não é um resumo dos marcadores — é a afirmação que eles provam
De onde vêm os números, tabela, figura ou citação do slide (fonte, tamanho da amostra, data):::source no nível superior do slide, um parágrafoTodo slide que mostra números, uma tabela, um gráfico ou uma citação ganha um. Apenas slides de conteúdo e declaração (não seção). Colocado pelo modelo abaixo do corpo, acima do rodapé; ele ocupa espaço do corpo (layout-overflow o conta). Um por slide: várias fontes vão em um parágrafo
Data, confidencialidade, aviso legal do deck ("todos os valores são fictícios")front matter date, confidential, disclaimerEscrito uma vez; mostrado na capa (e confidential no rodapé)
Uma observação / ressalva do tipo nota de rodapé:::noteUma linha curta. Não para fontes (:::source), não para o aviso legal do deck (front matter) e nunca para a conclusão ou um número chave
Um diagrama cujas posições/links carregam significado e nenhum dos acima se encaixa```shapesÚltimo caso, veja §3.1

Em todas as quatro figuras acima você escreve apenas texto, status (support, conditional, none, danger) e emphasis: true; posição, tamanho e cor vêm do modelo. Em chart você escreve apenas o que é comparado e os números; o gráfico é um gráfico real do PowerPoint cujos valores permanecem editáveis. Enfatize o único ponto que o título faz:

compare: timeSeries
unit: " inscrições"
categories: [Abr, Mai, Jun, Jul, Ago, Set]
emphasis: [Set]
series:
  - name: Inscrições
    values: [120, 150, 180, 220, 260, 310]

3.1 shapes (último caso)

Se você precisa de posições/links que carregam significado e nenhum padrão acima se encaixa:

fill:
  color: "0,0,0"  # R,G,B 0–255
  opacity: 0.7
shapes:
  - type: rectangle
    position: [1.5, 0.5, 3, 2]  # cm: left, top, width, height
    text: Caixa
    fill:
      color: "200,200,255"
    border:
      color: "100,100,200"
      width: 0.08  # cm
  - type: line
    start: [3, 2.5]
    end: [3, 4.5]
    width: 0.08
    color: "200,0,0"
  - type: ellipse
    position: [2, 5, 2, 1.5]
    text: Elipse
    fill:
      color: "150,255,150"

Apenas rectangle, ellipse, line e text ({text: …, position: …}, sem moldura/preenchimento). fill, border, line-end são opcionais. Coordenadas em cm absolutos — zero/topo da borda superior do slide. Os templates light e dark não têm estilos shapes, portanto cores de preenchimento e borda são usadas como escritas. Isso sempre parece fora de lugar; use shapes apenas quando não houver outra maneira de transmitir a informação.

4. Limites de layout

O motor de layout boxloom check -format json relata layout-overflow quando o conteúdo excede a área de corpo do template. Seus limites (verifique boxloom schema para o template atual —

[truncado conforme original: a seção 4 continua com limites específicos, mas foi truncada na entrada; o restante não é necessário para a tradução do conteúdo fornecido]

Habilidades Relacionadas