# Guide — building your first bench

This guide assumes you have MyBenchLab running locally or on the hosted site. It walks you from a blank workspace to a saved bench with two meshing gears, then shows how to iterate.

## 1. Open the workspace

The home hub is a single page: an AI creation hero on top, a preset showcase, and your bench grid. Describe a bench in the hero field and hit **Montar com IA** (the workspace opens with the IA drawer pre-filled), or start clean with **Bancada vazia** / **Importar .mbl** / a preset card (or **Sandbox 3D** for an unsaved session, only available when the `public.sandboxEnabled` Meteor setting is on). You land on the workspace, a CAD-style layout: a hero 3D viewport, a left icon rail, a resizable bottom drawer, a full-height right dock, and a status bar.

- **Workspace modes (header, left of the bench name — desktop; a full-width switcher below the header on mobile):** four modes organized around what you are DOING, in order — **Montagem** (assembly *at rest*: you BUILD the bench here, with the 3D canvas as the hero, the component palette and the Blueprint node view; the simulation clock is stopped and the transport is hidden), **Render** (owns the kinematics player: you WATCH the motion here — play/pause, speed and the ω/θ readouts — with the geometry read-only, so no move/rotate gizmos), **Peças** (the sketch/part-design world — draw a part, constrain it, save it to your library; reachable both from the hub and from inside a bench) and **Código** (the DSL power-user / AI surface, the source of truth underneath). Entering Render starts/resumes the simulation and leaving it pauses; switching a mode rearranges the whole screen and the last mode is remembered per bench. Internally the modes keep their original ids, so remembered preferences and shared/embedded benches keep working unchanged.
- **Context strip (under the header — desktop):** a slim strip that reflects the *active mode*. In **Montagem** it shows the part and junction counts, the static-validator state, and the active rail tool (**Ferramenta ativa**); in **Render** it shows the player state (**Reproduzindo/Pausado**) and the max ω. (The old Mecanismos/Estruturas chip is gone — component categories live only in the palette now.)
- **Left icon rail (desktop):** the always-visible universal tools — **Selecionar**, **Medir** (point-to-point distance in the viewport — see below), **Mover** and **Rotacionar** (direct-manipulation gizmos for the selected part — see below), **Validar** (recompiles and opens the Console only if errors remain), **Paleta** (toggles the component palette flyout; also **Shift+A**) and **IA** (opens the IA drawer tab). In **Montagem** a labeled **＋ Componente** button sits at the top-left of the viewport as the primary, discoverable way to add a part (the Paleta rail icon and **Shift+A** keep working alongside it). In **Render** the build tools (Mover, Rotacionar, Paleta and the ＋ Componente button) are hidden — the geometry is read-only there.
- **3D viewport (hero):** live render of the compiled bench. A grouped floating toolbar at the top-center holds icon buttons — projection (**perspective ◇ / orthographic ▢** — a real camera swap, remembered per bench, with **F·L·T** working in both), the named views **F·L·T**, **explode** (exploded view with an amount slider), **measure** (point-to-point ruler), reset, and a compact **Export** dropdown (STL, print-ready STL, PNG 1×/2×/4×, WebM, GIF); an orientation cube sits inside a round medallion at the top-right. Hovering a part shows its id; parts flagged by a validation error are outlined in orange; clicking a part selects it, floating a selection chip (id · dimensions · first junction) at the bottom-left. The camera framing adapts to the bench size, so a 50 mm gear train and a 2.6 m workbench are both framed sensibly. (Measure and explode are desktop-only.)
  - **Medir (ruler):** toggle it from the rail or the 📐 toolbar button. The cursor becomes a crosshair; click a point on any part, then a second point, and a line is drawn between them labelled with the distance in millimeters (hover the label for the per-axis Δx/Δy/Δz breakdown). Clicks snap to the nearest **snap point** (a part's bounding corners, face centers, center, or a joint anchor) when one is within a small screen radius — a highlighted dot marks the candidate before you click, and a free click still works when none is in range. Up to five measurements can coexist; **Limpar** removes them and **Esc** (or toggling the tool again) exits.
  - **Mover / Rotacionar (transform gizmos):** select a part, then pick **Mover** or **Rotacionar** from the rail to get the standard 3D handles (arrows / arcs) on that part. Dragging moves or rotates it live; orbiting is suspended while you drag. On release the new transform is written straight back into the source (position in millimeters, rotation in degrees — the DSL authoring units) and the bench recompiles, so the layout solver re-cascades any parts anchored to it. A part the solver had placed automatically gains an explicit `transform` the first time you move it, which anchors it there. When a moved part's snap point lands within 5 mm of another part's snap point the position snaps to it; hold **Alt** while dragging to disable that. **Esc** or the **Selecionar** tool exits. Scaling has no gizmo on purpose — parts are parametric, so size is a parameter edit in the Inspector, not a transform. (Gizmos are desktop-only.)
  - **Explodir (exploded view):** toggle it from the ✸ toolbar button to push every part radially away from the assembly centroid; a slider (1.0–2.5×) next to the toolbar controls how far. It is render-only — the graph, the simulation and the source are untouched, and selection/outliner highlighting keep working on the exploded positions.
- **Simulation transport pill (viewport, bottom-center — visible in Render):** a green play/pause circle, a compact **vel 1×** speed dropdown (0.25×–4×), the simulation time (pt-BR decimals) and the ω state (green **ω ok** while rotation flows, red **conflito** on an inconsistent-loop conflict, muted when idle). The pill only appears in **Render** — in the other modes the assembly is frozen at rest.
- **Bottom drawer (under the viewport):** a resizable drawer whose tabs are **Código** (plain JavaScript), **Blueprint** (visual node editor), **Materiais** (bill of materials), **Console** (compile/validation errors), and **IA** (the AI assistant). Código and Blueprint edit the same source — switching never loses your work; Materiais is read-only. New components come from the palette flyout (rail Paleta button / Shift+A), which replaced the old Paleta drawer tab. Drag the drawer's top edge to resize it, click the active tab (or press the backtick key \`) to collapse/expand it, and the last height is remembered. The IA tab requires `public.ai.enabled` plus a usable AI provider — either the platform provider configured centrally in the `zodo:ai-kit` settings (managed by an admin at **/admin/ai**), or your own key set at **Configurações → IA** (/settings/ai), which takes precedence over the platform for your own requests. AI runs through the shared `zodo:ai-kit` engine (usage/cost is tracked in the admin **Uso** tab).
- **Console tab:** every compile and validation error in one place. Each error that names a part is a clickable row: it selects that part in 3D and reveals its line in the Código tab. The tab shows a red badge with the current error count.
- **Right dock (full height):** the **Outliner** on top — the group → component → junction (⚡) hierarchy, with a per-part visibility eye (hidden parts are dropped from the render but keep simulating) and a red outline on parts with validation errors — over the **Inspector** below. The inspector header reads **Propriedades — <id>** (rename via the pencil); a commercial-size pair like width×height collapses into one **Largura × Altura** field; every numeric field carries its unit (mm/kg) inline and accepts pt-BR decimals; junctions are a select field; and the weight is a read-only **Peso** field at the bottom.
- **Status bar (bottom):** the error lead (**✗ N erro(s): <first>**, click to open the Console) or **✓ válido**, then per-validator ✓/✗ segments for static benches (envelope · interferência · conectividade), the current selection, and right-aligned meta (mm · compile version).

## 2. Describe the mechanism

### Code editor

The workspace starts with a tiny default bench (two gears meshing). A bench source is a JS module ending with `export default defineBench(buildFn)`. The compiler strips the `export default`, runs the body inside a sandbox (no `window`, `document`, `fetch`, `import`, or Meteor), and passes a DSL context to your `buildFn`. A minimal example:

```js
export default defineBench(({ mech }) => {
  const G1 = mech.spurGear({
    id: 'G1',
    teeth: 20,
    module: 2,
    transform: { position: [0, 0, 0] },
  });
  const G2 = mech.spurGear({ id: 'G2', teeth: 40, module: 2 });

  mech.mesh(G1, G2);
  mech.drive(G1, { rpm: 60 });
});
```

Three things are happening here:

1. **Components:** `mech.spurGear({ ... })` records a gear and returns a handle you bind to a const. Every category (`mech`, `elec`, ...) is exposed as a namespace on the DSL context.
2. **Connections:** `mech.mesh(G1, G2)` links the two handles through a gear-mesh edge. The layout solver places G2 tangent to G1 automatically, so only one anchor usually needs an explicit `transform`.
3. **Drivers:** `mech.drive(G1, { rpm: 60 })` injects 60 RPM on G1's axis port. A bench with no drivers simulates a static mechanism.

The canonical unit for lengths is **millimeters**; rotations are authored in **degrees** and converted to radians internally; driver speed is **RPM** on the surface, rad·s⁻¹ inside the engine.

### Blueprint editor

Click the **Blueprint** button to switch to the visual node editor. Every component in the compiled document appears as a node; every connection is an edge. You can:

- **Drag nodes** to reposition them — positions are written back to the source as `/** @blueprint x=… y=… */` annotations and survive reloads.
- **Add a component** from the palette sidebar (left side of the Blueprint view): click a kind and it is inserted at the top of the source.
- **Connect ports** by dragging from one handle to another — the appropriate `mech.<connectionKind>` call is written into the source automatically.
- **Delete a component** by selecting it and pressing Delete — all wiring calls that reference the handle are cascade-removed.
- **Delete a connection** by selecting an edge and pressing Delete.

Components that use constructs the Blueprint view cannot represent (loops, `defineComponent`, computed helpers) appear as locked nodes — switch to the Code editor to change them.

### Component palette

Open the palette from the left rail's **Paleta** button or with **Shift+A**; it appears as a flyout anchored to the rail (Esc or an outside click closes it). It lists every registered component kind grouped by category — **Mecanismos** (kinematic parts) and **Estruturas** (structural parts) — each with its icon, title and an expandable summary, plus a search box. The grouping is organizational only: a bench can freely mix categories. Clicking an entry inserts a ready-to-edit declaration for that kind (with default parameters) into the active source and selects the new component, exactly as adding one from the Blueprint palette does — the source stays the single source of truth.

### Bill of materials

The **Materiais** tab is a read-only bill of materials for the current bench: identical physical parts collapse into one line with a quantity and a rolled-up weight, and a totals row sums the part count and total mass. Weights come from each kind's declared dimensions, so the numbers match the `.mbl` export and the MCP surface exactly.

## 3. Compile and simulate

Compilation runs automatically whenever the source changes (debounced). If it succeeds, the 3D viewer updates and keeps simulating. The play/pause button in the viewer toolbar pauses the tick loop without losing the compiled state.

Compiler output:
- **Errors** block the simulation: missing kind, invalid parameters, duplicate `id`, connection loop, module mismatch on a gear mesh, static-assembly problems (part outside the envelope, interference, disconnected body), etc. The editor shows them inline; multiple errors from all passes surface at once so you don't fix them one by one. When an error names a specific part, clicking the error row selects it — and any part blamed by a validation error is outlined in orange in the 3D viewer.
- **Warnings** do not block but highlight suspicious setups (e.g. unconnected port, unreachable component).

See [DSL reference](/docs/dsl) §Compilation passes for the six passes the compiler runs in order.

## 4. Tweak via the inspector

Select a component in the Outliner or in the Blueprint view. The inspector shows:

- **ID** — shown in the panel header as **Propriedades — <id>**. Click the pencil to rename; the source is updated everywhere the old name appears.
- **Parameters** — editable fields for every declared parameter. A width×height pair collapses into one **Largura × Altura** field; every numeric field carries its unit (mm) inline and accepts pt-BR decimals (comma or dot). Editing a parameter rewrites the source via AST and triggers an immediate recompile.
- **Junctions** — a select field listing the connections that touch the part; picking one selects that connection.
- **Weight** — a read-only **Peso** field (kg) for kinds that expose a weight.
- **Authored transform** — the `transform` you wrote in the source.
- **Effective transform** — what the layout solver computed (may differ when the solver auto-places a driven component).
- **Derived dimensions** — pitch radius, tip radius, etc. for kinds that expose them.
- **Live kinematics** — while the simulation is running:
  - Rotational ports: θ (rad), ω (rad/s), speed (RPM).
  - Linear ports (e.g. rack): position x (mm), velocity v (mm/s).

All inspector edits are undoable with **Ctrl/Cmd+Z** (see §Keyboard shortcuts below).

## 5. Save

When a bench is bound to a user (any non-sandbox bench), Ctrl+S or the **Salvar** button persists the current source to MongoDB. The engine API version is recorded with the bench so future engine updates can migrate it forward automatically.

## 6. Export

### Images and video

The **3D viewer toolbar**'s **Export** dropdown groups every export:

| Button | What it produces |
| ------ | ---------------- |
| **PNG ▾** | Hi-res screenshot at 1×, 2×, or 4× the canvas resolution. |
| **WebM ▾** | Screen-recorded video. A modal lets you set duration, fps (30/60), and simulation speed before recording starts. |
| **🎞** | Animated GIF. A modal lets you set fps (5/10/15) and duration (2–10 s). The export samples the live canvas — start the simulation before clicking. |
| **STL** / **STL◉** | Binary STL of the full bench (or the selected component when one is highlighted). Coordinates are in millimeters. |

### Print-ready STL

Click **STLp** / **STLp◉** for a print-optimised version. A **Print options** modal appears where you can set bore clearance, nozzle diameter, and end chamfer before downloading. Each component is downloaded as a separate file; kinds that do not yet have a dedicated printable geometry fall back to the visual mesh (a warning is shown). The printable geometry uses denser tessellation and adjusted tolerances suited for FDM printing.

## 7. Reuse via groups

Once a subassembly starts appearing twice, wrap it in `group({ id, build })`. The inner build runs against a fresh recorder; the outer bench gets a handle with exactly the ports you expose. See [Groups](/docs/groups) for the namespacing model, inline local kinds, and the multi-file roadmap.

## 8. Share

Saved benches can be made public from the ⋯ menu on a bench card in the home hub (or the **Compartilhar** button in the workspace). A public bench exposes a read-only `/embed/:id` route that renders the compiled document in the viewer with no editing chrome. Source code is never exposed on the public endpoint.

## Keyboard shortcuts

| Action          | Shortcut             |
| --------------- | -------------------- |
| Save             | Ctrl/Cmd+S           |
| Undo             | Ctrl/Cmd+Z           |
| Redo             | Ctrl/Cmd+Shift+Z     |
| Toggle drawer    | \` (backtick)        |
| Open palette     | Shift+A              |
| Clear selection  | Esc                  |
| Play/pause       | (button only)        |
| Reset camera     | (button only)        |
| Delete selected  | Delete (Blueprint)   |

Compilation happens automatically — there is no explicit recompile shortcut.

## Next steps

- Design your own part in [Peças — desenho paramétrico](/docs/pecas) and turn it into a [Ficha técnica](/docs/ficha-tecnica).
- Browse the [component catalog](/docs/components) for the parts you can use.
- See the [connection catalog](/docs/connections) for the rules that link them.
- Read the [DSL reference](/docs/dsl) for the full authoring surface.
- Learn about [Groups](/docs/groups) when you want to reuse subassemblies.
- Write your own part in the [custom components guide](/docs/custom-components).
