CommunityImagengithub.com

Joinery

Convierte la foto de un mueble (mesa, silla, banco, estante, aparador, cama, escritorio) en un modelo 3D construible que un carpintero pueda fabricar: cada pieza como madera real con ensambles reales, una página HTML interactiva sin conexión con vista explosionada, rayos X y montaje paso a paso, más el paquete de fabricación: lista de cortes, planos acotados, qué madera comprar, herrajes y un manual de montaje ilustrado. Úsalo cuando alguien envíe una foto de un mueble y quiera construirlo, necesite "planos", una "lista de cortes" o un manual.

¿Qué es Joinery?

Joinery es una habilidad para agentes de IA (como Claude Code, Cursor, Codex) que transforma una foto de un mueble en un modelo 3D paramétrico listo para fabricar. El agente guía al usuario a través de un proceso de cinco pasos: interpretación de la foto (con anclas de dimensiones y elección de ensambles), modelado en código (JavaScript con funciones predefinidas), validación (detección de colisiones y flotaciones), generación de página web interactiva (HTML sin conexión con Three.js) y empaquetado (lista de cortes, planos, manual PDF). Soporta muebles de madera, metal y combinados, con ensambles como mortaja y espiga, dowels, ranuras, bisagras, y más. Integra reglas de carpintería real (espesores comerciales, direcciones de veta, tolerancias) y un bucle de revisión visual para garantizar precisión proporcional y constructiva.

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

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

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

¿Qué hace Joinery?

Una pieza, una página, un paquete. El visitante ve la pieza ensamblada, arrastra un deslizador y se desarma, recorre paso a paso cómo se monta, hace clic en una pieza y lee su tamaño comercial. El mismo modelo que mueve las piezas escribe la lista de cortes, los planos y el manual, por lo que nada en el papel puede contradecir lo que está en pantalla.

SKILL_DIR es la carpeta donde vive este archivo. Las construcciones y el paquete van a ./joinery-out de la carpeta desde donde ejecutes.

Primera ejecución

cd "$SKILL_DIR" && npm install

Node 20.10+. Para las imágenes fijas de revisión y las imágenes del manual necesitas Chromium: npx playwright install chromium, o apunta CHROMIUM a cualquier binario de Chrome/Chromium (CHROMIUM=/usr/bin/google-chrome).

El flujo

foto + anclas ─► spec.json ─► model.js ─► validar ─► página ─► imágenes fijas ─► paquete
PasoComandoLo que obtienes
1. Interpretartú, leyendo la fotospec.json: tipo, anclas, materiales, cada pieza nombrada, cada ensamble elegido, cada suposición escrita
2. Modelartú, escribiendo model.jsla pieza como función de sus parámetros: cajas, ensambles, pasos
3. Validar + empaquetarnode "$SKILL_DIR/pack.mjs" ./my-piecese niega a empaquetar si algo colisiona o flota; escribe lista de cortes, planos, diagramas de corte de tableros y láminas, madera, herramientas y acabados, manual (y manual.pdf cuando Chromium está presente)
4. Construir páginanode "$SKILL_DIR/build.mjs" ./my-piecejoinery-out/dist/my-piece.html, sin conexión, ~570 KB
5. Revisarnode "$SKILL_DIR/capture.mjs" my-piece --stills stepsuna hoja de contactos de cada vista y paso — léela, corrige, repite
6. Empaquetar de nuevonode "$SKILL_DIR/pack.mjs" ./my-pieceel manual y el PDF ahora llevan las imágenes de los pasos

Empieza copiando el ejemplo más cercano a la pieza. Cada uno tiene todos los archivos que necesita una pieza: spec.json, model.js, main.js. Una pieza normalmente vive en la propia carpeta de la persona, no en SKILL_DIR: después de copiar, cambia las dos importaciones ../../kit/ (en model.js y main.js) a la ruta absoluta $SKILL_DIR/kit/.

EjemploCópialo paraMuestra
parsons-tableuna mesa simple, escritorio, bancoel mínimo: patas, delanteros, sobre, mortaja-y-espiga, botones. 64 líneas
walnut-racetrack-tablepiezas redondas, ovaladas o cónicasperfiles roundedRect / circle, patas redondas cónicas, espigas lo suficientemente cortas para no cruzarse en la pata
walnut-display-cabinetun mueble con curvas o vidrioesquinas de laminado curvado (quarterRing, stock.layers), puertas de vidrio sobre bisagras de pinza, clavijas de estante, un fondo rebaixado, un plinto
walnut-entry-unitempotrados, armarios, unidades tipo cocinavarios armazones, puertas de tablero y marco, cajones sobre correderas, estantes flotantes, MDF pintado junto a chapa, herrajes LED y ganchos
walnut-hallway-unituna pieza mixta de acero y maderaun armazón de acero soldado que sostiene cajas de madera, puertas de panel de caña, un nicho abierto alrededor de un panel eléctrico

Paso 1: lee la foto honestamente

Una sola foto no da escala ni estructura oculta. Esta habilidad es interpretación de diseño, no fotogrametría. Antes de escribir cualquier geometría:

  1. Obtén anclas. Pide una a tres dimensiones reales (L × A × P total, o una conocida como "el sobre es de 180 cm"). Si la persona no puede dar ninguna, usa los estándares ergonómicos en kit/validate.js (comedor 750 A, asiento 450 A) y dilo. Cada otra dimensión es una proporción leída de la foto multiplicada por el ancla.
  2. Nombra el tipo. dining-table, chair, bookshelf… esto elige las comprobaciones ergonómicas y la construcción típica.
  3. Enumera lo que ves y lo que no. Patas, sobre, estantes visibles son visible. Delanteros bajo un sobre grueso, paneles traseros, travesaños, correderas de cajón, tacos de esquina son inferred (inferidos) — márcalos inferred: true en la pieza para que se señalen en cada salida. El fabricante los anulará; debe saber cuáles son tuyos.
  4. Elige el ensamble de la biblioteca (templates/joinery-library.md), clave por tipo × material × taller. Pregunta qué taller tiene el fabricante si no es obvio (shop: hand, cabinet cnc); también elige la lista de herramientas. Por defecto, un taller de ebanistería: mortaja-y-espiga para patas/delanteros, ranuras para estantes, espigas o Dominos para paneles, tornillos de bolsillo solo donde queden ocultos. Escribe la elección y la razón en spec.source.assumptions.
  5. Lee el material y el acabado. Especie a partir del color y la figura, grosor a partir de la proporción del borde, tratamiento del borde (redondeado / chaflán / vivo) a partir de los reflejos. El grosor debe coincidir con un tamaño comercial (STOCK_T en kit/validate.js) — 40, no 38.7. Establece finish a partir del brillo: una superficie abierta y mate es hardwax-oil (por defecto) o oil, una película satinada uniforme es lacquer. Las piezas pintadas y de metal siguen su material.

Escribe todo eso en spec.json usando templates/spec.schema.json. El spec es para humanos: el fabricante lee source.assumptions antes que nada.

Paso 2: construye el modelo

model.js exporta piece = definePiece({name, type, shop, finish, params, source, materials, build}). build(P) devuelve {parts, joints, steps, hardware}. El ejemplo tiene 70 líneas; una silla tiene unas 120.

Las piezas son cajas alineadas a los ejes en su pose ensamblada: box(id, name, [sx, sy, sz], [x, y, z], {grain, material, edge, explode, inferred, note}). x es el largo, y es arriba con el suelo en 0, z es la profundidad. grain es el eje a lo largo del cual corre la madera — decide la longitud comercial en la lista de cortes y el patrón de anillos en el renderizado. Las piezas que se cortan igual reciben el mismo name y se fusionan en una línea de lista de cortes; id sigue siendo único.

Las piezas curvas y con radios mantienen una caja delimitadora para size/at y añaden profile: {axis, path, note}: el contorno real a través de axis, centrado en la caja (quarterRing(R, t, [su, sv]) para una esquina curvada, roundedRect(w, h, radii) para vidrio con radios, un respaldo o un sobre tipo racetrack, circle(d) para una pata redonda; profile.taper: {to, end} la estrecha hacia un extremo). Se renderiza extruido, se valida en su contorno y se dibuja como su contorno. Cuando la caja no es el stock (una laminación curvada), añade stock: {L, W, T, layers, layerT} y la lista de cortes y de compra usan eso. Una pieza curvada en dos direcciones (un respaldo de silla tallado, una pieza central compuesta) aún no tiene tipo de cuerpo: díselo a la persona, modela la extrusión recta más cercana y dilo en su note.

Los herrajes son hardware comprado que se dibuja sobre una pieza, no cortado: fittings: [{kind, size, at, material, axis, dir, holes: {n, d, cc, axis}}] con at relativo al centro de la pieza. Tiradores, ganchos y perfiles LED se renderizan; sus agujeros para tornillos aparecen en el plano de la pieza. También enuméralos en hardware.

Colores por pieza: una entrada en el mapa materials puede llevar base, dark, ring, streak, rough, clearcoat, env para reajustar un material del kit a la foto sin cambiar otras piezas. Las maderas oscuras aceitadas en un sobre grande y plano necesitan rough ≈ 0.9 o la luz clave vuelve gris su brillo; muestra la foto y el render y compara números, no impresiones.

Los ensambles conectan dos ids de pieza: {a, b, type} donde a lleva la espiga/tornillo y b lo recibe. Tipos: mortise-tenon (tenonLen, tenonT, shoulder, mitred), dowel (count, d, len), dado (depth), rebate (face, depth: un fondo en un rebaje a lo largo del borde de b), shelf-pin (count, d, len, inset: un estante sobre clavijas en b), hinge (face, at: [y mundo…], cup: 35 para perforar la copa en a: una puerta que mira +z colgada en b), groove (width, depth: un panel o fondo de cajón flotando en el borde o cara de b), runner (una caja de cajón sobre correderas laterales en b), weld (acero con acero), pocket-screw, button, figure-8, screw, glue. shelf-pin y hinge permiten los pocos mm de holgura que el herraje salva; cada pieza debe estar unida al resto o la validación se niega. applyJoinery escribe las características coincidentes en ambos miembros: la espiga alarga el stock en la lista de cortes, la mortaja aparece en el dibujo de la pata con su cara y posición, y ambos se renderizan. Un ensamble también le dice a validate que estos dos cuerpos pueden tocarse.

Los pasos son el manual: {title, parts: [ids], note, check, view}. Cada pieza debe aparecer exactamente en un paso. Ordénalos como lo haría un fabricante: subconjuntos primero (bastidores laterales, cajas de cajón), luego lo que los une, luego lo que va encima, con la pieza boca abajo cuando así se haga. view establece la cámara para ese paso en la página y en el manual.

Parámetros. Todo es un número en P. Cambia L y los delanteros, espigas, espaciado de botones y lista de cortes le siguen. Ese es el punto: el mismo model.js hace la versión de 1600 y la de 2200.

Reglas que deciden si se puede construir

  1. Empieza desde la foto, nunca desde la imaginación. Construye contra ella y compara los renders lado a lado: silueta, proporción pata-sobre, voladizo, dónde cae la línea de sombra del delantero. Una pieza inventada de "una bonita mesa de roble" sale genérica; el mismo código reconstruye la real fielmente cuando tiene algo que igualar.
  2. Stock real. El grosor es un tamaño comercial. Nada más ancho de 200 mm es una tabla — pack.mjs lo convierte en un encolado de tiras y lo dice. Nada más grueso de 50 mm es una tabla — se convierte en una laminación. La veta corre a lo largo de cada pieza, o la validación advierte sobre veta corta.
  3. Cada ensamble es un ensamble real. Dos piezas solo pueden compartir volumen a través de un ensamble declarado. Las espigas que se encuentran dentro de una pata deben ser mitred: true o acortadas; la validación comprueba la colisión. Un sobre macizo ancho debe sujetarse con botones, figure-8 o agujeros ranurados — nunca pegado rígido — y la validación advierte si lo está.
  4. Arregla las colisiones con un número. Cuando la validación informa que una pieza atraviesa otra, cambia un valor en P o en build. Nunca lo escondas con la cámara.
  5. Escribe la suposición, no solo la pieza. Un delantero que la foto no mostró es inferred: true con un note. El primer recuadro del manual enumera cada suposición.
  6. Un número, una fuente. La lista de cortes, el plano, el HUD de la página y el manual leen todos stockOf(part). Si un número parece incorrecto, arregla el modelo, no la salida.

Reglas de la página en vivo

  • La página es un archivo HTML sin conexión de menos de 1 MB (Three.js incrustado). Las piezas grandes con muchas partes se mantienen rápidas porque cada parte es una caja redondeada y la madera es un shader, no una textura.
  • Estudio de luz, luz cálida clave, relleno frío, sombra suave en el suelo. El shader de madera dibuja la figura plana a lo largo de grain y la testa en los extremos automáticamente. Mantén roughness ≥ 0.45; la madera brillante sobre un suelo pálido se lee como plástico.
  • Dejada sola durante 20 s, la página hace un tour: explosiona, recorre pasos, rayos X por debajo. Cualquier entrada devuelve el control.
  • El estado de la URL impulsa la captura: ?step=2, ?explode=1, ?iso=leg-fl, ?view=under&xray=1, ?panel=0. Con cualquiera de estos, la página se fija en lugar de animar, por lo que una imagen fija es la misma a 5 fps que a 60.

Bucle de revisión

No puedes mirar la página; puedes mirar imágenes fijas. Nunca informes una pieza como terminada sin leer una hoja de la construcción actual.

  1. node "$SKILL_DIR/capture.mjs" <name> --stills steps → joinery-out/<name>-sheet.png: ensamblada, explosionada, frontal, rayos X por debajo, un mosaico por paso.
  2. Lee cada mosaico contra la lista de verificación. Pon la foto de referencia junto a los mosaicos front y assembled.
  3. Para una pieza, --stills parts aísla cada una; para un estado, --still "step=3&view=under".
  4. Corrige, reconstruye, vuelve al paso 1. Para cuando una pasada no encuentre nada.
  5. Abre joinery-out/<name>/manual.html de la misma manera y léelo como lo haría el fabricante.

Lista de verificación:

  • Proporción. Contra la foto: grosor de pata vs largo, grosor de sobre vs largo, voladizo, altura de la línea del delantero. Dentro del 5 % o cambia un parámetro.
  • Ensamble. Mortajas aparecen en las caras donde se encuentran los delanteros; espigas visibles en la vista explosionada y en rayos X; nada flota en el aire en la vista explosionada (una pieza sin ensamble no tiene vector de explosionado que tenga sentido).
  • Pasos. Cada paso añade algo que se puede ver; la cámara muestra las piezas que se añaden; las piezas ya colocadas son visibles debajo. El paso 1 nunca es el sobre.
  • Planos. Cada mortaja, ranura y agujero en un plano nombra su cara y distancia desde el extremo. Las longitudes de la lista de cortes que incluyen espigas lo dicen.
  • Stock. La lista de stock no tiene ningún tablero más ancho de 200 ni más grueso de 50; los encolados y laminaciones se enumeran. Cada pieza reposa sobre un tablero o lámina en los diagramas de corte.
  • Herramientas y acabados. tools.md enumera lo que usaría el taller del fabricante, y las longitudes de las abrazaderas tienen sentido para el encolado más grande. Las piezas pintadas, chapadas y de metal reciben su propio acabado.
  • Render. Nada a menos de 60 px de un borde, el panel nunca cubre la pieza, las maderas casi blancas (arce, fresno) tienen un borde visible contra el fondo pálido.

Materiales

kit/stage.js → MATERIALS: roble-blanco, roble-rojo, nogal, arce, fresno, haya, pino, cerezo, abedul-contrachapado, mdf, acero, latón. Añade una especie como colores base/oscuros más fuerza de anillo y veta. También: nogal-mdf, nogal-bendply (lámina chapada), mdf-negro, vidrio (transparente, dibujado por sus bordes, pedido cortado a medida en el paquete en lugar de cortado de tableros). El mapa materials en definePiece los nombra para la lista de cortes ("Roble blanco, macizo").

Skills relacionados