Aplicación de escritorio (web local) para carpinteros: a partir de una foto de un mueble, identifica las piezas con IA, calcula medidas y materiales, genera planos de corte profesionales en PDF y compone el presupuesto final para el cliente.
Monorepo gestionado con npm workspaces y orquestado con Turborepo:
packages/
backend/ Hono server (API + integración con FreeCAD y Gemini)
frontend/ React SPA con Vite (UI)
shared/ Zod schemas compartidos
freecad/ Generadores Python que se invocan desde el backend
installer/ Launcher empaquetable como .exe + script Inno Setup
Antes de lanzar el proyecto necesitas instalar tres cosas en el sistema:
La versión está fijada en .node-version. La forma recomendada es usar fnm:
# Instalar la versión de Node del proyecto (sólo la primera vez)
fnm install
# Activar la versión en la shell actual
fnm use(Opcional) Para que fnm cambie de versión automáticamente al entrar al directorio:
# macOS / Linux — añadir a ~/.bashrc o ~/.zshrc
eval "$(fnm env --use-on-cd)"
# Windows PowerShell — añadir al $PROFILE
fnm env --use-on-cd --shell powershell | Out-String | Invoke-ExpressionOpenWood usa FreeCAD para generar tanto los planos de corte (PDF) como los modelos 3D (.glb) de cada pieza. Para desarrollo local — descárgalo desde freecad.org (https://www.freecad.org/downloads.php?lang=es_ES) y déjalo en la ruta por defecto:
C:\Program Files\FreeCAD 1.1\bin\freecad.exe
Si lo tienes en otra ubicación, exporta FREECAD_EXE en el .env del backend (ver siguiente sección). Para generar el instalador .exe — no necesitas hacer nada extra. El build copia automáticamente los binarios de FreeCAD portable desde packages/installer/assets/freecad-portable/, por lo que el usuario final recibe FreeCAD incluido sin necesidad de instalarlo por separado.
El script Python que se ejecuta dentro de FreeCAD necesita dos paquetes externos:
| Paquete | Para qué se usa |
|---|---|
pypdf |
Unir en un único PDF los planos de cada pieza |
pygltflib |
Consolidar los GLBs de las piezas en 3D |
Se instalan en una carpeta local del repo (packages/backend/freecad_lib/) usando el Python embebido de FreeCAD para asegurar compatibilidad de versiones (FreeCAD 1.1 trae Python 3.11):
& "C:\Program Files\FreeCAD 1.1\bin\python.exe" -m pip install `
--target packages/backend/freecad_lib pypdf pygltflib
⚠️ Si no instalas estas dependencias, los planos sólo contendrán la primera pieza (pypdffalla al importar y se cae al fallback) y los modelos 3D no se generarán.
El backend lee variables de entorno desde packages/backend/.env. Crea el archivo con al menos:
# Obligatorio: el script de arranque requiere que el .env exista (aunque sea
# casi vacío) porque tsx se lanza con --env-file=.env
PORT=3000
# Para análisis de imagen y asistente de chat con Gemini. Sin esta clave,
# subir fotos o usar el chat lanzará un error. Generala en
# https://aistudio.google.com/apikey
GEMINI_API_KEY=tu_clave_aqui
# Opcional — sólo si tienes FreeCAD en otra ruta
# FREECAD_EXE=D:\Apps\FreeCAD\bin\freecad.exeLa clave de Gemini también se puede configurar desde la propia app (pantalla "Configurar API Key" la primera vez que abras), pero ponerla en el .env es más cómodo para desarrollo.
Con Node 24 activo y FreeCAD instalado:
# 1. Instalar dependencias del monorepo
npm install
# 2. Instalar pypdf + pygltflib en freecad_lib (sólo la primera vez)
& "C:\Program Files\FreeCAD 1.1\bin\python.exe" -m pip install `
--target packages/backend/freecad_lib pypdf pygltflib
# 3. Crear packages/backend/.env con GEMINI_API_KEY (ver sección anterior)
# 4. Arrancar backend (puerto 3000) y frontend (puerto 5173) en paralelo
npm run devAbre http://localhost:5173.
Desde la raíz del monorepo:
npm run dev # backend + frontend en paralelo (turbo)
npm run build # build de producción de todos los paquetes
npm run typecheck # tsc --noEmit en todos los paquetes
npm run format # oxfmt --write . (formatea todo el repo)
npm run knip # detecta exports / deps sin usar
npm run jscpd # detecta código duplicadoPara un paquete concreto: npm -w <paquete> run <script>. Ejemplos útiles:
npm -w backend run typecheck
npm -w frontend run typecheck
npm -w frontend run build # bundle estático del frontendEl paquete @openwood/installer empaqueta el conjunto como un único .exe instalable. Sólo lo necesitas si quieres distribuir el producto fuera del entorno de desarrollo.
Requiere Inno Setup 6 instalado en C:\Program Files (x86)\Inno Setup 6\.
npm -w @openwood/installer run build:installerGenera el instalador final en packages/installer/build/.
Pasos intermedios disponibles:
| Script | Qué hace |
|---|---|
start |
Lanza el launcher (server.js) con Node, sin empaquetar |
stage |
Prepara contenido (frontend + backend + freecad) en build/stage |
build:exe |
Genera build/OpenWood.exe con pkg |
build:all |
Cadena completa: iconos → stage → exe → ocultar consola |
installer |
Ejecuta ISCC.exe sobre installer/installer.iss |
El backend falla con node: .env: not found
Crea packages/backend/.env aunque sea con sólo PORT=3000. El flag --env-file=.env de tsx exige que el archivo exista.
Los planos generados sólo contienen una pieza
Falta pypdf en packages/backend/freecad_lib/. Ver requisito 3.
"GEMINI_API_KEY no configurada" al analizar una foto
Añade GEMINI_API_KEY=... en packages/backend/.env o configúrala desde la pantalla "Configurar API Key" de la app.
No se pudo lanzar FreeCAD en C:\Program Files\FreeCAD 1.1\bin\freecad.exe
Instala FreeCAD 1.1 en esa ruta, o define FREECAD_EXE en el .env con la ruta correcta.
Puertos 3000 / 5173 ocupados Mata el proceso anterior. En Windows PowerShell:
netstat -ano | findstr ":3000 :5173"
taskkill /PID <pid> /T /F