Tenon

Tenon designs flat-pack parts and lays them out on the board you are actually going to cut.

You do not draw anything. You pick a product — a box, a cabinet, a tray, a pegboard panel — and turn its parameters. Tenon generates the parts, cuts the joinery into them, and nests every part of every item onto your stock, redrawing as you type. When it looks right, you either export a CAM-ready bundle of SVGs or send the job straight to MapleCAM to cut.

Tenon's stock parameter form beside a live preview of project-box parts nested on the board

What it is for

A flat-pack design is a set of parts that fit together with cut joinery — finger joints, half-laps, tabs into slots — so a sheet of plywood becomes a box without fasteners. Getting that right by hand is fiddly: the joints have to interlock, the slots have to allow for the cutter's kerf, and the parts have to fit the board you own. Tenon does that arithmetic.

It is deliberately narrow. It knows about parts, joints, and sheets; it does not generate toolpaths, drive machines, or write G-code. That is MapleCAM's job, and the two hand off to each other.

What a design contains

One design is a cut list:

  • Shared stock — one board, one material, one cutter. Every item is cut from the same setup, so the stock lives once at the design level rather than being repeated per item.
  • Line items — each a product, its own parameters, and a quantity.

Everything on the list nests together onto the shared board. Change the board thickness and every item's joinery follows, because thickness is what finger joints are cut from.

Where to start

Tenon is in development. What is documented here is what works today; anything still landing says so on the page.

Installation

Tenon is a desktop application. It runs on Windows, macOS and Linux, and it needs Java 21 or later.

Get Java

Any JDK distribution works — your package manager, your OS vendor, or a build from openjdk.org. Check what you have:

java -version

If that reports 21 or higher, you are ready.

Download and run

Download the JAR for your platform from maplecam.ca/downloads and run it from the directory you saved it in:

java -jar tenon-alpha-<platform>.jar

On Windows, double-clicking the JAR also works once Java is installed.

Each JAR carries the JavaFX native libraries for its own platform, so take the one that matches your operating system and architecture — they are not interchangeable.

There is no server to start

Tenon is split into an application and a local server, the same way MapleCAM is, but you never launch the server yourself. On startup the app either attaches to one already answering on its API port or starts one inside its own process and stops it again on exit.

This matters for one reason: the same design you are editing is reachable over an HTTP API, so a script or an AI agent can drive it while you watch. If you want to point the app at a server running elsewhere, set TENON_API_URL before launching.

Cutting needs MapleCAM

Tenon produces parts and sheets. Turning those into toolpaths and G-code is MapleCAM's job. You do not need it installed to design — export writes plain SVGs that any CAM package can read — but the MapleCAM tab and the direct send only light up when MapleCAM is running. See Sending to MapleCAM.

Your First Design

This walks a box from an empty window to a file you can cut. It takes a couple of minutes and nothing here is destructive — a design is just a text file.

1. Set the stock

The Stock tab describes the board every item will be cut from. Start with the three that matter most:

  • Thickness — the actual thickness of your sheet, measured. Not the nominal figure printed on it: 6 mm ply is rarely 6 mm, and every finger joint in the design is cut to this number.
  • Board width and Board length — the sheet you are going to put on the machine.
  • Cutter diameter — the bit you will cut with. Slots are widened so a round cutter can actually enter them.

Everything else can wait. See Shared Stock for the rest.

2. Add an item

On the Items tab, choose a product — start with Project Box, the glued finger-jointed box — and add it. The form beneath is built from that product's own parameters, so each product shows only what applies to it.

Set the outside dimensions (L, W, H). The preview redraws as you type: parts appear, joints interlock, and the sheet fills up.

Set a quantity if you want more than one. Quantity is per item, so a cut list of three boxes and one tray is four line items' worth of parts on one board.

3. Read the preview

The preview on the right is the actual sheet. Underneath it, the status line reports what the nester made of the job — how many parts, how many pieces, and whether they all fit. If the job needs more than one board you will see more than one sheet.

If something does not fit, the fix is usually the board, not the design: a longer sheet, or a smaller box.

4. Save it

File → Save As… writes a .tenon file. It is YAML — readable, diffable, and safe to keep in version control alongside the rest of a project.

5. Cut it

Two ways out, covered in their own pages:

  • Export job… writes a folder of CAM-ready SVGs plus a setup sheet. Any CAM package can take it from there. See Exporting a Job.
  • The MapleCAM tab sends the job to MapleCAM directly, with your tools and machines already chosen. See Sending to MapleCAM.

What to try next

Turn the thickness up by 3 mm and watch every joint in the design change. That is the whole idea: the parts are generated from the parameters, so the design is never out of step with the material.

The Cut List

A Tenon design is not a drawing of one object. It is a cut list: shared stock, plus a list of line items to cut from it.

design
├── stock          one board, one material, one cutter — shared by everything
└── items
    ├── project box   L=310 W=210 H=110   × 3
    ├── divider       3 × 2 spots         × 1
    └── marker        "whatsit.ca"        × 2

Why stock is shared

Because you cut a job, not a part. Every item on the list goes onto the same sheet in the same setup, so the board, the material and the cutter belong to the design rather than to any one item.

It also keeps the joinery honest. Finger joints are cut from the material thickness — a 6 mm box and a 9 mm box are different geometry, not the same geometry scaled. With one shared thickness, every item in the design agrees about the material it is made of, and changing it updates all of them at once.

Why items carry quantity

Quantity belongs to the item because the nester needs to place every copy. Three boxes is not one box cut three times: it is fifteen pieces that all have to fit on the board together, and the layout is different from one box's.

The status line under the preview reads out both numbers — parts (distinct shapes) and pieces (how many get cut).

Editing is live

Every change — a parameter, a quantity, an item added or removed — recomputes the parts and re-nests the sheet immediately. There is no generate step and no stale preview: what you are looking at is the job.

The design is the file

A design saves as a .tenon file containing exactly this structure: the stock block, then the items with their parameters and quantities. Nothing is baked; opening it rebuilds the parts from the parameters, so a design saved against 6 mm ply can be re-cut in 9 mm by changing one number.

Shared Stock

The Stock tab is the board every item is cut from. These settings apply to the whole design.

Panel and material

Thickness (mm) — the measured thickness of your sheet. This is the single most consequential number in a design: finger joints, slot depths and tab lengths are all cut from it. Measure the actual board. Sheet goods are routinely half a millimetre off nominal, and half a millimetre is the difference between a joint you tap together and one you hammer.

Board width / Board length (mm) — the sheet size the nester lays parts onto. If the job needs more than one, it fills additional sheets.

Material — a label carried through to the export and to MapleCAM, so the setup sheet says what to load.

Solid board edge — how the nester may treat the board's edges: whether it can run parts up to the edge, or must keep clear of it. Use clamp border when the sheet is held down at its edges and the cutter must not reach them.

Keep stock (mm) — margin held back from the board, for the same reason.

Cutting

Cutter diameter (mm) — the bit doing the cutting. A round cutter cannot cut a square internal corner, and it cannot enter a slot narrower than itself, so slots are widened to at least this. Set it to the tool you will actually use; too small a value produces a design your machine cannot cut, and too large loosens every joint.

Fit clearance (mm) — how much slack a joint gets. Zero is a theoretical perfect fit, which in real plywood means a joint you cannot assemble. A few tenths is normal; more for rough material or a machine with backlash.

Joint fit — the named fit preset (e.g. slip fit), which sets how tight interlocking parts are relative to the clearance above.

Tab recess (mm) — how far a plain tab sits below the surface it passes through, so nothing stands proud of a finished face.

Marking and layout

Board marks — whether the sheet carries its identifying marks (panel number, order number, registration scores).

Order no. — free text stamped on the job, so a cut sheet on a bench can be matched to the order it belongs to.

Nest in windows — whether the nester may place small parts inside the waste windows of larger ones. It packs tighter; leave it off if you would rather those cut-outs stayed intact.

Changing stock later

Any of these can change at any time and the whole design follows — that is the point of parameters. The one to be careful with is thickness: it changes every joint in every item, so a design cut successfully in one thickness should be re-checked in the preview after a change rather than sent straight to the machine.

Joinery and Fit

Tenon's products are held together by cut joinery — geometry, not fasteners. This page explains what it generates and which settings move it.

Finger joints

Box corners are finger-jointed: alternating fingers and sockets, each one material-thickness deep, so the two walls interlock and register themselves square. The pitch is a parameter on the products that use it; the depth always comes from the stock thickness.

Tabs and slots

A captured bottom does not sit in a groove — it carries tabs that pass through slots in the walls. That way the floor is located in all three axes by geometry alone, and the box cannot rack.

Plain tabs are recessed slightly below the outer face (Tab recess) so nothing protrudes on a finished surface. Some products hook their tabs instead, so a pin can draw the joint tight.

Pinned versus glued

Two boxes of the same size can be built two ways:

  • Glued (Project Box) — the joints go together with adhesive and stay together. Fewer parts, simpler cut.
  • Pinned (Pinned Project Box) — the corners carry hooked tenons drawn tight by a separate flat pin, so the box knocks down and reassembles. More parts: each hook needs its pin.

Pick glued for a box that will live assembled, pinned for one that has to ship flat or come apart.

Half-laps

Dividers and trays interlock with half-lap crossings: each board is notched halfway through where it meets another, so the grid assembles flush. This is why a divider's boards do not need any fasteners either.

Kerf, clearance and fit

Three settings decide whether the parts you cut actually go together:

SettingWhat it does
Cutter diameterSlots widened so a round cutter can enter; internal corners cannot be sharper than this
Fit clearanceSlack added to mating features so a joint can be assembled
Joint fitThe named preset (e.g. slip fit) that sets how tight the interlock is

The cutter cannot cut a sharp internal corner, so a socket cut with a 3.175 mm bit has 1.6 mm radii in its corners, and a square finger will not seat fully into it. Products handle this in their geometry; what you control is telling Tenon the truth about the cutter.

If joints are too tight, raise fit clearance a tenth or two. If they are sloppy, lower it — but check the cutter diameter first, since an overstated cutter widens every slot.

Test before you commit

Cut one corner in the real material before cutting a whole job. Fit is the one thing the preview cannot tell you: it depends on your machine, your bit and your plywood, and a tenth of a millimetre either way is the difference between a press fit and a gap.

Nesting and Sizing

Every part of every item is laid out on the shared board automatically, and re-laid out on every change. That layout is the sheet you cut.

What the nester does

It takes the full set of pieces — every part of every item, times its quantity — and places them on the board, respecting the margins the stock settings impose: the kept-back edge stock, and whether parts may run to a clamped edge.

If everything does not fit on one board, it fills another. A job can span as many sheets as it needs, and the preview shows each.

Reading the sizing line

Under the preview, the status line reports the job:

  • parts — distinct shapes in the design.
  • pieces — how many actually get cut, quantity included.

A three-box design has the same parts as a one-box design and three times the pieces.

If some pieces could not be placed, that is reported too — the job as specified does not fit the board you gave it.

When it does not fit

The nester will not silently shrink anything. Your options, roughly in order of how often they are the right answer:

  1. Use a bigger board. Most often the design is fine and the sheet is small.
  2. Split the job. Cut it as two designs, or drop a quantity.
  3. Turn on Nest in windows. Small parts get placed inside the waste windows of larger ones. Tighter, at the cost of those cut-outs.
  4. Reduce keep-stock margin. Only if your workholding genuinely allows it.

Sheet layout is not yours to place

Placement is automatic and not hand-editable in the general case — it is recomputed on every parameter change, so any manual arrangement would be discarded the moment you typed a number. Design intent lives in the parameters; the layout is derived.

Grain

Products declare grain direction where it matters structurally. The nester honours those constraints when placing, so a part that must run along the grain is not rotated to save space.

The Catalogue

Every product is a generator: parameters in, parts out. Adding one to a design gives you its own parameter form, and its geometry is rebuilt from those parameters every time they change.

ProductidWhat it is
Project Boxproject_boxGlued finger-jointed box with a captured bottom
Pinned Project Boxpinned_boxThe same box, knock-down: hooked tenons drawn tight by flat pins
Produce Boxproduce_boxThe glued box with every face turned into a honeycomb grille — a ventilated crate
CabinetcabinetA single column of openings — drawer, door, open bay or display — in a finger-jointed carcass with a captured back
DrawerdrawerA lean finger-jointed box sized to a cabinet opening
DividerdividerEgg-crate grid of half-lapped boards, sized to a box's interior
TraytrayA floor with border walls and per-bay half-lap dividers
Skadis Panelskadis_panelPegboard panel cut to the IKEA Skadis hole pattern
PlateplateA bare rectangular blank for engraving — nameplate, award, label
MarkermarkerAn engrave-only branding tile: artwork plus a line of text, nothing cut

The id is what appears in a saved .tenon file and in the HTTP API. The title is what the app shows.

Sizes are external

Where a product takes L, W and H, those are outside dimensions. The interior is whatever is left after the walls, and the app reports it back to you — a box with 310 mm outside length in 9 mm ply has a 292 mm interior, and the readouts say so rather than making you work it out.

This is the right way round for the usual question, which is "will it fit on that shelf", not "how thick are its walls".

Parameters are validated

A product refuses parameters it cannot build — a box too short for its own handle, a lidded box too thin for the lid notch. The message says which dimension is fighting which, and what to change. That is a contract failure, not a bug: it is the product telling you the object cannot exist in that material.

Adding products

Products are discovered from the engine, not hard-coded into the UI. A new product appears in the picker with its own form the moment the engine offers it — no UI change, and no update to this guide's mechanics.

Boxes

Three boxes, same lineage: a finger-jointed carcass around a captured bottom, with a stacking crown on the end walls so one nests onto the next.

Project Box (project_box)

The glued box. Four walls box-jointed at the corners, a bottom captured on tabs through the walls, an optional handle in the end walls, and an optional lid.

Choose it when the box will be assembled once and stay that way. It has the fewest parts and the simplest cut.

Key parameters: L, W, H (external), handle on/off, lid style, finger pitch.

Pinned Project Box (pinned_box)

The same box, knock-down. Each corner carries a hooked tenon plus a plain registration tenon, and a separate flat hook pin scissors the hook to draw the joint tight. The captured bottom hooks the same way.

Choose it when the box has to ship flat or come apart. The cost is parts: one pin per hook — four corners plus the bottom's hooks — and a slightly busier sheet.

Key parameters: as the Project Box, plus hook angle, the ramp angle the pin rides. Shallower self-locks harder but makes a taller hook; the default is a sensible middle.

A caution worth stating: on a very shallow box the hook has little room to ramp into, and Tenon shortens it to fit rather than letting the geometry cross itself. A box under about four times the material thickness in height will hold less well than a taller one.

Produce Box (produce_box)

The glued box with every face turned into a honeycomb grille, and no lid — a ventilated crate. Same carcass, stacking crown, handle and captured bottom; the vents are the only addition.

Choose it for anything that needs airflow. Expect a longer cut: the grille is a lot of internal geometry.

Lids

Where a box offers a lid, the options are none, cover slots (the walls are notched to receive a sliding cover) or a full cover.

A lid consumes the top of each wall for its notch, which is why a wall too short or too thick for both the notch and its corner tenon is rejected outright rather than built wrong.

Stacking

The end walls carry a crown: a bump on top, a congruent indent underneath. A stacked box self-centres on the one below, and the indent exposes the captured bottom's edge as a lip for the bump to seat against. Boxes of the same footprint stack whether they are glued or pinned.

Cabinets and Drawers

Cabinet (cabinet)

A single column of openings in a finger-jointed carcass with a captured back. Each opening is independently a drawer, a door, an open bay or a display, so one parametric product covers what would otherwise be a shelf of separate designs — workshop cabinet, kitchen cabinet, wall cabinet, open shelving.

You describe the column: the carcass size, then what each opening is. The carcass, dividers and back are generated to suit.

Because it is one column, a wider run is several cabinets side by side rather than one cabinet with two columns. That is a deliberate limit — it keeps the joinery honest and the nesting predictable.

Drawer (drawer)

A lean finger-jointed box sized to a cabinet opening: four walls box-jointed around a captured, tabbed bottom, and none of the box's extras — no handle, no stacking crown, no lid.

It is available as its own product, so you can cut a replacement drawer for an existing cabinet without regenerating the cabinet.

Sizing a drawer to an opening

A drawer has to be smaller than the hole it slides into, by enough for the runners or the clearance you intend. Tenon does not assume a runner system, so the gap is yours to specify: size the drawer to the opening minus your clearance, and cut one before committing to a set.

Inserts

Two products that go inside something else.

Divider (divider)

An egg-crate: a grid of boards that slot together with half-lap cross-laps, sized to a box's internal dimensions.

You give it the grid — X by Y spots — and it works out the boards. An X×Y grid needs X-1 cross boards and Y-1 long boards, each notched halfway through where they cross, so the assembly is rigid without glue or fasteners.

The size to give it is the box's interior, which the box's own readouts tell you. Design the box first, read its internal dimensions, then size the divider to them.

Tray (tray)

A flat floor, four border walls that capture the contents, and a configurable per-bay layout of half-lap dividers slotted into the floor.

Unlike the divider, the tray is glued, which keeps its underside flat. That matters: a tray with nothing protruding underneath will seat on top of a box divider without needing clearance cut for it, so trays and dividers stack in the same box.

Choose a tray when the compartments need a floor — small parts, tools, anything that would otherwise fall through to the bottom of the box. Choose a divider when the box's own floor is the floor.

Sizing inserts

Both are sized to fit something, and both are cut from the same shared stock as the thing they go into. Two consequences worth remembering:

  • Changing the design's thickness changes the insert's boards as well as the box's walls, so the fit is maintained.
  • Fit clearance applies here too. An insert that drops into a box wants a little more slack than a joint that is meant to be tight.

Panels and Plates

Three products that are a single piece rather than an assembly.

Skadis Panel (skadis_panel)

A pegboard panel cut to the IKEA Skadis hole pattern, so standard Skadis accessories clip into it.

The field is a grid of vertical 5 × 15 mm obround slots on a 40 mm pitch, with alternating columns staggered half a pitch. Give it a panel size and it fills the field.

Use it to make a Skadis-compatible panel in a size IKEA does not sell, or in material that matches the rest of your shop.

Plate (plate)

A bare rectangular blank — a nameplate, an award plate, a label — sized by its width and height and the shared stock thickness, and nothing else.

The plate deliberately has no marks of its own. Everything on it is applied as a decal: a logo, a rule, lines of text. That keeps one product covering every plate you might cut instead of growing a parameter per kind of marking.

Marker (marker)

An engrave-only branding tile: a rectangular panel carrying centred artwork scaled to fit and a line of text scored beneath it — and nothing cut.

The distinction from a plate matters. A plate is cut out of the sheet; a marker is only engraved onto it. Use a marker to brand a surface in place — the inside of a box lid, a corner of a panel — where cutting it free would be wrong.

When to use these instead of decals

A plate or a marker is a line item on the cut list, so it nests as its own piece and can carry a quantity. A decal is applied to another part. If you want ten identical badges, that is a plate with quantity ten. If you want your mark on the bottom of every box, that is a decal on the box.

Decals and Components

A decal puts an artifact on a part: a logo, a QR code, a line of text, a maker's mark. Products carry no branding of their own — it is all applied this way, so any mark can go on any part of any product.

Kinds

KindWhat it places
textEngraved text — single-stroke, using a built-in engraving face
filledtextFilled text from a TTF/OTF font file
svgArtwork from an SVG file, or inline SVG markup
qrA QR code from a URL or any text
datamatrixA Data Matrix code, same idea in a smaller footprint
rectA solid filled rectangle, sized to the decal's box

Engraved (text) and filled (filledtext) text are genuinely different operations, not two styles of one. Single-stroke text is scored — the tool follows the letterform once, quickly. Filled text is cleared out, so it reads at a distance and takes considerably longer to cut.

Placement

A decal is placed on a named part, at a position in that part's own frame, sized to fit a box you give it — width and height, in millimetres. It can be turned in quarter turns.

Sizing is fit-within, not stretch: artwork keeps its proportions inside the box you specify.

Where the files live

An SVG decal's artwork and a filled-text decal's font are referenced by path, and a path is resolved relative to the design file's own directory. Keep artwork beside the design and it travels with it; use an absolute path and the design only opens on the machine that has that file.

Cut blocks

Each decal carries a block token — logo, qr, and so on. That token follows the geometry into the export and into MapleCAM, where it becomes the grouping that operations select on. It is what lets a whole job say "engrave every logo with this tool" without naming parts one at a time.

Components

The Components menu handles reuse:

  • Save selection as component… stores what you have selected so it can be used again.
  • Add component… brings one into the current design.

Use it for the marks you apply on everything — a maker's mark with your logo, your URL as a QR, and your name in text, positioned the way you like it — so each new design is one insertion rather than three placements.

Saving and Opening

The design file

File → Save and Save As… write a .tenon file. Older saves use .tenon.yaml; both open.

The format is YAML, and it is meant to be read:

stock:
  T: 6.35
  SHEET_W: 1150.0
  SHEET_L: 590.0
  MATERIAL: Baltic birch ply
  TOOL: 3.2
  CLR: 0.2
items:
- product: project_box
  quantity: 3
  params:
    L: 310.0
    W: 210.0
    H: 110.0
    LID: slots
    HANDLE: 'yes'

Parameters, not geometry. Opening the file rebuilds every part from these numbers, which is why a design survives a change of material: edit T, and the joinery is regenerated to suit.

It also means designs diff usefully. A commit that changes a box's height shows as one changed line, and two versions of a job can be compared without opening either.

Recent files

The app keeps a recent-files list, so the design you were working on last is one click away. That list is the only thing Tenon stores locally on your behalf — everything else about a design is in the design file.

Where files are read and written

Saving, opening and exporting are done by Tenon's local server, not by the window. You choose the path in the file dialog and the server does the writing.

This is invisible in normal use — the app and its server are the same machine. It only matters if you point TENON_API_URL at a server on another host, in which case the paths you choose are interpreted on that machine, and save/open/export will not do what you expect. Running against a remote server is not a supported setup for that reason.

Keeping designs with a project

A design references its artwork and fonts by path, resolved against the design's own directory. Keeping the .tenon file, its SVGs and its fonts in one folder makes the whole job portable — copy the folder, and it opens anywhere.

Exporting a Job

Export job… writes the CAM-ready bundle into a folder you choose. This is the route that does not need MapleCAM: the output is plain SVG, which any CAM package can read.

What lands in the folder

For each panel in the job:

  • panel-<n>-cut.svg — the cut contours.
  • panel-<n>-engrave.svg — the engraved marks.
  • panel-<n>-combined.svg — both together, for looking at.

Plus one maplecam-setup.txt — the setup sheet, telling whoever is running the machine which stock to load and how to machine each SVG.

The combined file is the one to open when you want to check the job by eye. Cut from the separate files.

Why cut and engrave are separate files

Because they are different operations with different tools, and often different machines: a router cuts the outlines while a laser does the engraving, or a single machine does both in two setups with a tool change between.

Keeping them apart means each file maps to one operation with one tool, and nothing has to be filtered by layer or colour downstream.

Multiple panels

A job that needs more than one board exports one pair of files per panel, numbered. Cut them in order; the setup sheet lists what each one needs.

The setup sheet

Read it before cutting. It names the material and thickness the design was built for — a job cut in the wrong thickness will have joints that do not fit, and the sheet is the check against that. It also carries any warnings the job generated, such as holding-tab caveats.

Headless export

The same bundle can be produced without opening the window:

tenon --export <design.tenon> --out <dir>

Useful for regenerating a job in a script, or rebuilding every design in a folder after changing a shared component. Add --3d for the 3D output.

Sending to MapleCAM

The MapleCAM tab hands the job to MapleCAM directly: the parts arrive on stock as a project, with operations already set up from the choices you make here. No exporting, no re-importing.

MapleCAM must be running. While it is not reachable the tab says so and keeps checking, so starting MapleCAM after Tenon recovers on its own within a few seconds.

Choosing tools

The tab lists the tools from MapleCAM's own library — the same presets you maintain there, not a second copy. Reload re-reads them if you have just added one.

Pick two: the engrave tool and the cut tool. They can be on different machines, which is the point of the machine pickers beside them: engrave on the laser, cut on the router, in one job.

Options

Leave holding tabs — small uncut bridges that hold each part to the sheet so it cannot come loose and be thrown while the cut finishes. Set the tab size in millimetres beside the checkbox. Leave this on for anything cut on a router.

Score cut outlines (verify pass) — traces the cut outlines with the engrave tool before cutting them. A cheap dry run: you see exactly where the parts will land on the board and can confirm the stock is positioned correctly before any material is removed.

Cut filled shapes (outline only) — cuts around filled artwork rather than clearing it out. Faster, and appropriate when the "fill" is meant to be a cut-out rather than an engraved area.

What arrives in MapleCAM

A project per panel, containing the panel's geometry as parts on stock, with operations generated for the tools you chose: laser contours for a laser cut, spindle contours for a router, engrave or fill operations for the marks, each selecting on the decal blocks the design carries.

From there it is an ordinary MapleCAM project. Generate the toolpaths, check the simulation for overcut, and export G-code.

If a send is rejected

MapleCAM validates what it is given and refuses a job it cannot cut safely. The messages are specific — a laser whose lens cannot focus as deep as the cut asks, a tool too short for the material. Fix it on the MapleCAM side (a different tool or lens) or on the Tenon side (thinner stock), and send again.

Nothing is lost when a send is rejected: the design is untouched, and the validation happens before any toolpath is generated.

Files and Locations

Your files

WhatWhere
DesignsWherever you save them — .tenon (older saves: .tenon.yaml)
Exported jobsThe folder you pick in Export job…
Decal artwork and fontsReferenced by path, resolved against the design's own directory

Tenon's files

WhatWhere
Recent-files list$XDG_CONFIG_HOME/tenon/recent.txt, or ~/.config/tenon/recent.txt

That list is the only thing Tenon keeps on your behalf. There is no library, no preferences database and no cache to go stale: a design carries everything about itself, and the tools come from MapleCAM's library rather than a second copy here.

Exported bundle

<chosen folder>/
├── panel-1-cut.svg
├── panel-1-engrave.svg
├── panel-1-combined.svg     both layers, for checking by eye
├── panel-2-cut.svg          (only if the job needs a second board)
├── panel-2-engrave.svg
├── panel-2-combined.svg
└── maplecam-setup.txt

The local API

WhatValue
Default API port8788
OverrideTENON_API_URL

The app self-hosts a server on that port — attaching to one already there, else starting one it stops on exit. It is a first-class HTTP API, so the design open in front of you can also be driven by a script or an agent.

Setting TENON_API_URL attaches to an external server instead, and that server is never stopped by the app. Note that file operations run on the server's machine, so pointing this at another host breaks save, open and export — see Saving and Opening.

MapleCAM

WhatWhere
Tool and machine librariesMapleCAM's own, under ~/.maplecam/

Tenon reads MapleCAM's library over its API when the MapleCAM tab is open. It never copies or caches it, so a preset you add in MapleCAM is available here as soon as you press Reload.

Command Line

Launching

java -jar tenon-alpha-<platform>.jar [design.tenon]

A file argument opens that design on launch, which is also what the desktop launcher uses when you open a .tenon file from your file manager.

Headless export

Produce a job's CAM bundle without opening the window:

tenon --export <design.tenon> --out <dir> [--3d]

Both flags are required together. --3d additionally writes the 3D output.

The bundle is identical to what Export job… writes — per-panel cut and engrave SVGs plus maplecam-setup.txt — so this is the way to regenerate jobs in a script: after changing a shared component, or to rebuild a folder of designs against new stock.

Environment

VariableEffect
TENON_API_URLAttach to an external tenon-server instead of self-hosting. The app never stops a server it attached to.
XDG_CONFIG_HOMEWhere the recent-files list lives; defaults to ~/.config.

Driving the API directly

The app self-hosts its server on port 8788, and that API is the same one the UI uses — there is no private back channel. A design open in the window can be listed, edited and exported over HTTP while you watch it update.

That makes scripted and agent-driven use a first-class path rather than an afterthought: anything the interface can do, a curl can do.

FAQ

What Java version do I need? Java 21 or later, any distribution.

Do I need MapleCAM? Only to cut through it. Designing and exporting need nothing else — the export is plain SVG. The MapleCAM tab and the direct send need MapleCAM running.

Do I need an internet connection? No. Tenon runs entirely on your machine and sends nothing anywhere.

My joints are too tight to assemble. Raise Fit clearance a tenth or two. Before that, check Thickness against a caliper and Cutter diameter against the bit you actually used — an overstated cutter widens every slot, and an understated one makes every joint tight.

My joints are sloppy. Lower fit clearance. If they are sloppy in one axis only, the thickness is probably wrong: measure the sheet rather than trusting the label.

The parts do not fit on my board. Give it a bigger board, cut the job in two, or turn on Nest in windows to let small parts sit inside larger parts' cut-outs. See Nesting and Sizing.

Can I move parts around on the sheet myself? Placement is recomputed on every change, so a manual arrangement would not survive your next keystroke. Change the board or the parameters instead.

A product refuses my dimensions. That is the product saying the object cannot be built in that material — a box too short for its own handle, a lidded wall too thin for both the lid notch and its corner tenon. The message names what is fighting what.

Why is my pinned box's hook so short? On a shallow wall there is little room for the hook's ramp, and Tenon shortens it to keep the outline cuttable rather than letting the geometry cross itself. A box under roughly four times the material thickness in height will hold less firmly; use a taller box or the glued Project Box.

Where did my decal's logo go? Artwork paths resolve against the design file's directory. If the design moved and the artwork did not, the reference is dangling — keep them in one folder.

Can I use it with a laser? Yes. Choose laser tools in the MapleCAM tab; the cut becomes laser contours rather than spindle contours. Mind the lens: a laser cannot focus deeper than roughly its focal length divided by 1.5, so a short-focus diode lens will refuse thick stock.

Is it free? Yes. No account, no subscription. If it is useful to you, donations are welcome at paypal.me/maplecam.

Something is wrong and this page did not cover it. Email info@whatsit.ca with the design file, what you expected, and what happened.