CommunityImagemgithub.com

Joinery

Transforma a foto de um móvel (mesa, cadeira, banco, estante, aparador, cama, escrivaninha) em um modelo 3D construtível que um marceneiro pode fazer — cada peça como material real com encaixes reais, uma página HTML interativa offline com vista explodida, raio-X e montagem passo a passo, além do pacote do construtor: lista de cortes, desenhos técnicos cotados, madeira a comprar, ferragens e um manual de montagem ilustrado.

O que é Joinery?

Este skill transforma uma foto de um móvel em um modelo 3D totalmente construtível, com cada peça representada como madeira real e encaixes de marcenaria reais. Ele gera uma página HTML interativa offline (usando Three.js) que permite ao usuário explodir o móvel, visualizá-lo em raio-X e seguir passo a passo a montagem. Além disso, produz um pacote completo para o construtor: lista de cortes, desenhos técnicos cotados, diagramas de corte de placas e tábuas, lista de ferragens e um manual de montagem ilustrado (em HTML e PDF). O processo começa com uma interpretação cuidadosa da foto (definindo âncoras de dimensão, tipo de móvel, materiais e encaixes), seguida pela modelagem paramétrica em JavaScript, validação de colisões e flutuação, e finalmente a geração da página e do pacote. O skill suporta madeira maciça, compensado, MDF, aço e vidro, e inclui uma biblioteca de encaixes (mortise-and-tenon, dowel, dado, rebate, hinge, etc.). É ideal para cenários onde alguém envia uma foto de um móvel e quer que ele seja construído, pedindo "planos", "lista de cortes" ou "manual de montagem".

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/JoseChipanaTica/joinery/tree/HEAD

Installed? Explore more Imagem skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

Perguntar na sua IA favorita

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

Documentação

O que Joinery faz?

Uma peça, uma página, um pacote. O visitante vê a peça montada, arrasta um controle deslizante e ela se desmonta, percorre os passos de montagem, clica em uma peça e lê suas dimensões de estoque. O mesmo modelo que movimenta as peças escreve a lista de cortes, os desenhos e o manual, para que nada no papel possa discordar do que está na tela.

SKILL_DIR é a pasta onde este arquivo está localizado. As construções e o pacote vão para ./joinery-out na pasta de onde você executa.

Primeira execução

cd "$SKILL_DIR" && npm install

Node 20.10+. Para imagens de revisão e imagens do manual, você precisa do Chromium: npx playwright install chromium, ou aponte CHROMIUM para qualquer binário Chrome/Chromium (CHROMIUM=/usr/bin/google-chrome).

O pipeline

foto + âncoras ─► spec.json ─► model.js ─► validar ─► página ─► imagens ─► pacote
EtapaComandoO que você obtém
1. Interpretarvocê, lendo a fotospec.json: tipo, âncoras, materiais, cada peça nomeada, cada encaixe escolhido, cada suposição escrita
2. Modelarvocê, escrevendo model.jsa peça como uma função de seus parâmetros: caixas, encaixes, passos
3. Validar + empacotarnode "$SKILL_DIR/pack.mjs" ./my-piecerecusa empacotar se algo colidir ou flutuar; escreve lista de cortes, desenhos, diagramas de corte de tábuas e placas, estoque, ferramentas e acabamento, manual (e manual.pdf quando o Chromium estiver presente)
4. Construir páginanode "$SKILL_DIR/build.mjs" ./my-piecejoinery-out/dist/my-piece.html, offline, ~570 KB
5. Revisarnode "$SKILL_DIR/capture.mjs" my-piece --stills stepsuma folha de contato de cada vista e passo — leia, corrija, repita
6. Empacotar novamentenode "$SKILL_DIR/pack.mjs" ./my-piecemanual e PDF agora carregam as imagens dos passos

Comece copiando o exemplo mais próximo da peça. Cada um tem todos os arquivos que uma peça precisa: spec.json, model.js, main.js. Uma peça geralmente fica na própria pasta da pessoa, não em SKILL_DIR: após copiar, altere os dois imports ../../kit/ (em model.js e main.js) para o caminho absoluto $SKILL_DIR/kit/.

ExemploCopie paraMostra
parsons-tableuma mesa simples, escrivaninha, bancoo mínimo: pernas, travessas, tampo, mortise-and-tenon, botões. 64 linhas
walnut-racetrack-tablepeças redondas, ovais ou cônicasperfis roundedRect / circle, pernas redondas cônicas, tenões curtos o suficiente para não se encontrarem na perna
walnut-display-cabinetuma peça com curvas ou vidrocantos laminados curvos (quarterRing, stock.layers), portas de vidro em dobradiças de grampo, pinos de prateleira, fundo encaixado, um plinto
walnut-entry-unitembutidos, guarda-roupas, unidades estilo cozinhavários corpos, portas de painel e moldura, gavetas em corrediças, prateleiras flutuantes, MDF pintado junto com folheado, encaixes para LED e ganchos
walnut-hallway-unituma peça mista de aço e madeirauma estrutura de aço soldada segurando caixas de madeira, portas de painel de junco, um nicho aberto deixado ao redor de um painel elétrico

Etapa 1: leia a foto honestamente

Uma única foto não fornece escala nem estrutura oculta. Este skill é interpretação de design, não fotogrametria. Antes de escrever qualquer geometria:

  1. Obtenha âncoras. Peça uma a três dimensões reais (C × L × A total, ou uma conhecida como "o tampo tem 180 cm"). Se a pessoa não puder fornecer nenhuma, use os padrões ergonômicos em kit/validate.js (jantar 750 A, assento 450 A) e diga isso. Todas as outras dimensões são uma proporção lida da foto vezes a âncora.
  2. Nomeie o tipo. mesa-de-jantar, cadeira, estante… isso seleciona as verificações ergonômicas e a construção típica.
  3. Liste o que você pode ver e o que não pode. Pernas, tampo, prateleiras visíveis são visible. Travessas sob um tampo grosso, painéis traseiros, esticadores, corrediças de gaveta, blocos de canto são inferred — marque-os como inferred: true na peça para que sejam sinalizados em todas as saídas. O construtor irá substituí-los; eles devem saber quais são seus.
  4. Escolha os encaixes da biblioteca (templates/joinery-library.md), indexados por tipo × material × oficina. Pergunte qual oficina o construtor tem se não for óbvio (shop: hand, cabinet, cnc); também seleciona a lista de ferramentas. Padrão para oficina de marcenaria: mortise-and-tenon para pernas/travessas, dados para prateleiras, cavilhas ou Dominos para painéis, parafusos de bolso apenas onde ocultos. Escreva a escolha e o motivo em spec.source.assumptions.
  5. Leia o material e o acabamento. Espécie pela cor e figura, espessura pela proporção da borda, tratamento da borda (arredondamento / chanfro / reto) pelos realces. A espessura deve recair em um tamanho de estoque (STOCK_T em kit/validate.js) — 40, não 38,7. Defina finish pelo brilho: uma superfície aberta e fosca é hardwax-oil (o padrão) ou oil, uma película acetinada uniforme é lacquer. Peças pintadas e de metal seguem seu material.

Escreva tudo isso em spec.json usando templates/spec.schema.json. O spec é para humanos: o construtor lê source.assumptions antes de qualquer outra coisa.

Etapa 2: construa o modelo

model.js exporta piece = definePiece({name, type, shop, finish, params, source, materials, build}). build(P) retorna {parts, joints, steps, hardware}. O exemplo tem 70 linhas; uma cadeira tem cerca de 120.

Peças são caixas alinhadas aos eixos em sua pose montada: box(id, name, [sx, sy, sz], [x, y, z], {grain, material, edge, explode, inferred, note}). x é comprimento, y é para cima com o chão em 0, z é profundidade. grain é o eixo ao longo do qual a madeira corre — decide o comprimento do estoque na lista de cortes e o padrão dos anéis no render. Peças que são do mesmo corte recebem o mesmo name e se fundem em uma linha da lista de cortes; id permanece único.

Peças curvas e com raio mantêm uma caixa delimitadora para size/at e adicionam profile: {axis, path, note}: o contorno real através de axis, centralizado na caixa (quarterRing(R, t, [su, sv]) para um canto curvado, roundedRect(w, h, radii) para vidro com cantos arredondados, um fundo ou um tampo oval, circle(d) para uma perna redonda; profile.taper: {to, end} afunila em direção a uma extremidade). Ele renderiza extrudado, valida em seu contorno e desenha como seu contorno. Quando a caixa não é o estoque (uma laminação curva), adicione stock: {L, W, T, layers, layerT} e a lista de cortes e a lista de compras usarão isso. Uma peça curva em duas direções (um encosto de cadeira esculpido, uma travessa composta) ainda não tem tipo de corpo: informe a pessoa, modele a extrusão reta mais próxima e diga isso em sua note.

Acessórios são ferragens compradas desenhadas em uma peça, não cortadas: fittings: [{kind, size, at, material, axis, dir, holes: {n, d, cc, axis}}] com at relativo ao centro da peça. Puxadores, ganchos e perfis de LED renderizam; seus furos para parafusos aparecem no desenho da peça. Liste-os também em hardware.

Cores por peça: uma entrada no mapa materials pode conter base, dark, ring, streak, rough, clearcoat, env para reajustar um material do kit para a foto sem alterar outras peças. Madeiras escuras oleadas em um tampo grande e plano precisam de rough ≈ 0,9 ou o brilho da luz principal as torna acinzentadas; amostre a foto e o render e compare números, não impressões.

Encaixes conectam dois IDs de peça: {a, b, type} onde a carrega o tenão/parafuso e b o recebe. Tipos: mortise-tenon (tenonLen, tenonT, shoulder, mitred), dowel (count, d, len), dado (depth), rebate (face, depth: um fundo em um rebate ao longo da borda de b), shelf-pin (count, d, len, inset: uma prateleira em pinos em b), hinge (face, at: [y mundo…], cup: 35 para furar a taça em a: uma porta voltada para +z pendurada em b), groove (width, depth: um painel ou fundo de gaveta flutuando na borda ou face de b), runner (uma caixa de gaveta em corrediças laterais em b), weld (aço com aço), pocket-screw, button, figure-8, screw, glue. shelf-pin e hinge permitem os poucos mm de folga que a ferragem preenche; toda peça deve estar unida ao resto ou a validação recusa. applyJoinery escreve as características correspondentes em ambos os membros: o tenão aumenta o comprimento do estoque na lista de cortes, a mortise aparece no desenho da perna com sua face e posição, e ambos renderizam. Um encaixe também diz ao validate que esses dois corpos podem se tocar.

Passos são o manual: {title, parts: [ids], note, check, view}. Cada peça deve aparecer em exatamente um passo. Ordene-os da forma que um construtor faria: submontagens primeiro (estruturas das extremidades, caixas de gaveta), depois o que as une, depois o que fica em cima, com a peça de cabeça para baixo quando for assim que se faz. view define a câmera para aquele passo na página e no manual.

Parâmetros. Tudo é um número em P. Altere L e as travessas, tenões, espaçamento dos botões e lista de cortes seguem. Esse é o objetivo: o mesmo model.js faz a versão de 1600 e a versão de 2200.

Regras que decidem se pode ser construído

  1. Comece pela foto, nunca pela imaginação. Construa contra ela e compare renders lado a lado: silhueta, proporção perna-tampo, balanço, onde a linha de sombra da travessa cai. Uma peça inventada a partir de "uma bela mesa de carvalho" sai genérica; o mesmo código reconstrói a real de perto quando tem algo para igualar.
  2. Estoque real. A espessura é um tamanho de estoque. Nada mais largo que 200 mm é uma tábua — pack.mjs transforma em uma colagem de tiras e diz isso. Nada mais grosso que 50 mm é uma tábua — torna-se uma laminação. O grão corre ao longo do comprimento de cada peça, ou a validação avisa sobre grão curto.
  3. Cada encaixe é um encaixe real. Duas peças só podem compartilhar volume por meio de um encaixe declarado. Tenões que se encontram dentro de uma perna devem ser mitred: true ou encurtados; a validação verifica a colisão. Um tampo maciço largo deve ser preso com botões, figure-8s ou furos alongados — nunca colado rigidamente — e a validação avisa se for.
  4. Corrija colisões com um número. Quando a validação reportar uma peça passando por outra, altere um valor em P ou em build. Nunca esconda com a câmera.
  5. Escreva a suposição, não apenas a peça. Uma travessa que a foto não mostrou é inferred: true com uma note. A primeira caixa do manual lista cada suposição.
  6. Um número, uma fonte. A lista de cortes, o desenho, o HUD na página e o manual leem todos stockOf(part). Se um número parecer errado, corrija o modelo, não a saída.

Regras da página ao vivo

  • A página é um arquivo HTML offline com menos de 1 MB (Three.js embutido). Peças grandes com muitas partes permanecem rápidas porque cada parte é uma caixa arredondada e a madeira é um shader, não uma textura.
  • Estúdio de luz, luz principal quente, preenchimento frio, sombra suave no chão. O shader de madeira desenha figura de corte plano ao longo de grain e grão final nas extremidades automaticamente. Mantenha roughness ≥ 0,45; madeira brilhante em um fundo pálido parece plástico.
  • Deixado sozinho por 20 s, a página faz um tour: explode, percorre passos, raio-X por baixo. Qualquer entrada devolve o controle.
  • O estado da URL impulsiona a captura: ?step=2, ?explode=1, ?iso=leg-fl, ?view=under&xray=1, ?panel=0. Com qualquer um desses definidos, a página captura em vez de animar, para que uma imagem seja a mesma a 5 fps que a 60.

Ciclo de revisão

Você não pode olhar para a página; pode olhar para imagens. Nunca relate uma peça como concluída sem ler uma folha da construção atual.

  1. node "$SKILL_DIR/capture.mjs" <name> --stills steps → joinery-out/<name>-sheet.png: montada, explodida, frontal, raio-X por baixo, um bloco por passo.
  2. Leia cada bloco contra a lista de verificação. Coloque a foto de referência ao lado dos blocos front e assembled.
  3. Para uma peça, --stills parts isola cada uma; para um estado, --still "step=3&view=under".
  4. Corrija, reconstrua, volte para 1. Pare quando uma passagem não encontrar nada.
  5. Abra joinery-out/<name>/manual.html da mesma forma e leia como o construtor faria.

Lista de verificação:

  • Proporção. Contra a foto: espessura da perna vs comprimento, espessura do tampo vs comprimento, balanço, altura da linha da travessa. Dentro de 5% ou altere um parâmetro.
  • Encaixes. Mortises aparecem nas faces que as travessas encontram; tenões visíveis na vista explodida e no raio-X; nada flutua no ar na vista explodida (uma peça sem encaixe não tem vetor de explosão que faça sentido).
  • Passos. Cada passo adiciona algo que você pode ver; a câmera mostra as peças sendo adicionadas; peças já colocadas são visíveis por baixo. O passo 1 nunca é o tampo.
  • Desenhos. Cada mortise, dado e furo em um desenho nomeia sua face e distância da extremidade. Comprimentos da lista de cortes que incluem tenões dizem isso.
  • Estoque. A lista de estoque não tem tábua mais larga que 200 ou mais grossa que 50; colagens e laminações estão listadas. Cada peça está em uma tábua ou chapa nos diagramas de corte.
  • Ferramentas e acabamento. tools.md lista o que a oficina do construtor usaria, e os comprimentos dos grampos fazem sentido para a maior colagem. Peças pintadas, folheadas e de metal recebem cada uma seu próprio acabamento.
  • Render. Nada a menos de 60 px de uma borda, o painel nunca cobre a peça, madeiras quase brancas (bordo, freixo) têm uma borda visível contra o fundo pálido.

Materiais

kit/stage.js → MATERIALS: carvalho-branco, carvalho-vermelho, nogueira, bordo, freixo, faia, pinho, cerejeira, compensado-bétula, mdf, aço, latão. Adicione uma espécie como cores base/escuras mais força dos anéis e listras. Também: nogueira-mdf, nogueira-bendply (chapa folheada), mdf-preto, vidro (transparente, desenhado por suas bordas, encomendado cortado no tamanho certo no pacote em vez de cortado de tábuas). O mapa materials em definePiece os nomeia para a lista de cortes ("Carvalho branco, maciço").

Habilidades Relacionadas