Metadata-Version: 2.5
Name: woodwright
Version: 0.2.0
Summary: A semantic CAD library for woodworking.
Project-URL: Homepage, https://github.com/bzamecnik/woodwright
Project-URL: Source, https://github.com/bzamecnik/woodwright
Project-URL: Issues, https://github.com/bzamecnik/woodwright/issues
Project-URL: Documentation, https://github.com/bzamecnik/woodwright/tree/HEAD/docs
Author-email: Bohumir Zamecnik <bohumir.zamecnik@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: build123d,cad,cut list,furniture,joinery,woodworking
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Manufacturing
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Multimedia :: Graphics :: 3D Modeling
Classifier: Topic :: Scientific/Engineering
Classifier: Typing :: Typed
Requires-Python: >=3.14
Requires-Dist: build123d>=0.13.0
Description-Content-Type: text/markdown

# woodwright

A semantic CAD library for woodworking. You describe furniture the way a
woodworker thinks about it: boards with named sides, and the joints between
them. woodwright works out the joinery, the cut sizes and where every part
goes, and produces 3D models (STEP, STL), drawings (SVG) and cut lists.

It is built on [build123d](https://github.com/gumyr/build123d). This is an
early alpha: the API will still change.

## Installation

```shell
pip install woodwright  # or: uv add woodwright
```

Requires Python 3.14. Source: <https://github.com/bzamecnik/woodwright>

## Quickstart

A rail tenoned into a stile. You give the design dimensions and the joint;
the tenon, the mortise, the rail's cut length and its placement are derived.

```python
from pathlib import Path

import woodwright as ww
from woodwright.export import export_model

oak = ww.Stock.board(thickness=20, species="oak")

frame = ww.Assembly("corner", root_location=ww.orient(right_end=ww.UP, back_edge=ww.RIGHT))
stile = frame.add(ww.Board("stile", oak, length=600, width=60))
rail = frame.add(ww.Board("rail", oak, length=300, width=60))  # shoulder to shoulder
frame.join(ww.MortiseTenon(tenon=rail.left_end, mortise=stile.back_edge))

model = frame.resolve()
print(model.cut_list())
export_model(model, Path("output/corner"))  # STEP, STL, SVG views, cut list
```

```text
stile  600 x 60 x 20 mm  oak
       - mortise 50 x 8 mm, 42 deep, in stile.back_edge
rail   340 x 60 x 20 mm  oak
       - tenon 50 x 8 mm, 40 long, on rail.left_end
```

What's there so far:

- **Cuts:** grooves, dados and rabbets (through or stopped), mortises, slot
  mortises, tenons (haunched, mitred, chamfered, multiple side by side or
  across the thickness, wedged), tongues, dovetail tongues and laps,
  chamfers, mitres (across the face, the edge, or along the grain), tapers.
- **Joints:** butt (also turned at an angle); dado, rabbet, groove and
  tongue and groove housings (also stopped); mortise and tenon (blind,
  through, stub, haunched, mitred, with mitred shoulders, multiple, wedged,
  tusk); loose tenons and loose tongues; bridles (L and T); half laps
  (plain, dovetailed, mitred), cross laps, mitred face tenons; box joints;
  sliding, through, half-blind, mitred-corner and blind mitred dovetails;
  mitre corners and splices; table-top buttons.

## Example library

`woodwright.examples` holds over ninety examples, from single cuts through
joints to projects: a try square, a mallet, a bookshelf, a dovetailed drawer
with a bottom, a dining table, a side table, a chair, a step stool seat,
ledged and frame-and-panel doors.

```shell
python -m woodwright.examples list
python -m woodwright.examples export projects.chair --out output
```

The design ideas are in [docs/vision.md](https://github.com/bzamecnik/woodwright/blob/HEAD/docs/vision.md)
and [docs/plan.md](https://github.com/bzamecnik/woodwright/blob/HEAD/docs/plan.md).

## Development

Install the environment and dependencies:
```shell
uv sync
pre-commit install  # ruff lint + format on commit
```

Optionally, for notebooks with an interactive 3D viewer:
```shell
uv sync --group notebook
uv run jupyter lab
```

Run the tests and the linters:
```shell
uv run pytest
uv run ruff format
uv run ruff check --fix
```

## License

[MIT License](./LICENSE).

### Credits

- Ideas and guidance: Bohumír Zámečník
- Most of the implementation: Claude Code (Opus 5.5)
