Open a Grasshopper definition in your browser. No Rhino, no plugins, no install.
Mola Mola runs entirely in your browser. Your definition is solved locally by our geometry engine. Nothing is sent to a server to be computed, and the app keeps working if your connection drops.
.gh / .ghx file.| Region | What lives there |
|---|---|
| Top bar | Project name · node/wire count · the Model / Graph / Compare switch · Undo/Redo · theme · Gallery · Project · Export · Run |
| Left rail | Drawing tools, snaps, Select object, and at the bottom: Play mode, Projects, Account, Settings |
| Left panel | Parameters – every live input in the definition |
| Right panel | The data stack: Layers · States · Cameras · Inspector · Components · Notices |
| Viewport top-right | View toolbar: 2D/3D, projection, display mode, shadows, sun, zoom, gizmo, display settings |
Both side panels collapse with the chevron tab on their outer edge, and resize by dragging their inner edge. The layout is remembered in your browser.
The Gallery ships finished scenes, not raw definitions – parameters already tuned, layers and camera set up. Currently: Attractor points, Sine wave, Pergola by curve, Stack of sticks, Brick wall, Urban block and Spiral staircase. They are the fastest way to see what the app does before you bring your own file.
Project ▸ Open definition (Ctrl+O), or drag a file straight onto the viewport. The app sniffs the file's contents, not its extension, so a mis-named file still opens correctly.
| Format | What it is | Support |
|---|---|---|
.gh | Grasshopper binary definition | Open |
.ghx | Grasshopper XML definition | Open |
.mola | A Mola project: definition, your drawn geometry, layers, states, cameras and display settings | Open & save |
.ghjs / .json | The older name for the same project format | Opens (legacy) |
.3dm / .gha | Rhino models, compiled plugins | Not supported |
Both Grasshopper formats carry the same definition, so either works. If a file behaves oddly in one format, opening the other is a reasonable thing to try.
The Project menu still labels the project entries .ghjs; what actually lands
on disk from Save to file is a .mola. Same format, newer name.
Every live input in the definition appears here, and every change re-solves the model. What you get depends on the Grasshopper object:
| Grasshopper object | What you get |
|---|---|
| Number Slider | A slider plus a numeric box. Type a value and press Enter to commit – it is clamped to the slider's own min/max. Integer sliders step by 1; others keep the digit count the author set. |
| Boolean Toggle | A checkbox – or a pill switch, or a lit-up toolbar button, depending on how the author grouped it (see §4) |
| Value List | A dropdown. Options read Name (expression), e.g. Brick (0) |
| Graph Mapper | An interactive curve you can drag the control points of. Bezier graphs only – Sine, Perlin, Conic and the rest produce no control. |
| MD Slider | A 2-D pad with a draggable dot and an x , y readout |
| Colour Swatch | A colour picker. Without MolaUI cards these collect under a Colors heading. |
| Panel (text) | Static text, a heading, or an editable field – see the [H1]/[INPUT] markers in §4 |
| Button | A push button that re-solves. It does not send true into the definition. |
Two rough edges worth knowing. An MD Slider always opens centred at
0.5 , 0.5 – its saved value is not read from the file, so nudge it once to set it.
A Button only triggers a re-solve; anything wired downstream of it gets nothing.
This is the feature most people miss. You lay out the Parameters panel from inside Grasshopper,
by naming groups. No extra plugin, no separate config file – the group nicknames in your
.gh/.ghx are the UI definition. Open the same file in Rhino and it still
just looks like a tidily grouped definition.
Name a group so its nickname starts with # and it becomes a card – a titled,
collapsible section in the Parameters panel.
The moment any group in the file starts with #, the panel switches to card mode and
only controls that sit inside # groups are shown. Everything else disappears from the
panel. That is the whole mechanism – and it is also how you hide a control: leave it out of every
# group. A # card that ends up containing no supported control is dropped silently.
No # group anywhere in the file? You get the plain flat
list of every slider, toggle, value list, graph mapper, MD slider and panel, with colour swatches
gathered under Colors. That is the default and it is perfectly fine.
All of these go in the group nickname in Grasshopper (right-click a group ▸ rename).
| Type this | You get |
|---|---|
#Massing | A card titled Massing, collapsible by its header |
#5 Road corners | Same, but 5 is the sort order; the title is just Road corners. Un-numbered cards sort last. |
#1 Widths | notes to self | Everything after | is stripped from the title → Widths. A place to leave yourself a note. |
#t LEFT | A toolbar zone: one untitled row of controls pinned above the tab strip, visible on every tab |
A group nested inside a # group | Its controls are pulled up into the parent card (recursively). Use it to style a subset – see the next three rows. |
* on a nested group | Its toggles/buttons become a compact row of 40×40 square buttons |
*Tools [FLEX] or [WRAP] | Same row, but the buttons stretch to fill the card width |
! on a nested group | A Boolean Toggle inside it renders as an iOS-style pill switch instead of a checkbox |
A Scribble inside a # group | Renders as a heading in the card, at its canvas position |
Controls are ordered by their vertical position on the Grasshopper canvas, top to bottom. Not left-to-right, not wire order. Drag a slider higher on the canvas and it moves up in the card. That applies to Boolean Toggles and Buttons too, which are placed by their box rather than a pivot point.
Put a Panel component inside a card and give it a nickname starting with one of these to control how its text renders (the panel must not be wired into anything):
[H1] · [H2] · [H3] – a static heading[BODY], or no marker at all – static body text["] or [INPUT] – an editable text field the user can type into (a multi-line panel becomes a 3-row text area)To split the panel into tabs, add a Panel component and set its nickname to
[CONFIG][TABS] ({CONFIG}{TABS} and spacing variants also work, case-insensitive).
Its body text is the outline:
[Name] or {Name} starts a tab.-, |, >, a leading (n), and any […] tags are ignored, so you can format the list however reads best.A real one, from the urban-block demo. The file has groups
#1 Road Widths, #5 Road corners settings, #10 Building settings,
#2 Building 3d options, #33 Layers and #t LEFT, and a
[CONFIG][TABS] panel reading:
[MAIN]
- Road Widths
- Road corners settings
- Building settings
[3d]
- Building 3d options
Result: two tabs, MAIN and 3d, with the cards in the order you listed them – the
#N numbers stop mattering once a card is named in the outline. #33 Layers
is never listed, so it is a leftover and gets appended to the first tab (leftovers sort among
themselves by #N). #t LEFT becomes the toolbar row above the strip.
[CONFIG][TABS] panel → one implicit tab, cards sorted by #N.If you have seen the Rhino-side MolaUI builder, it documents more tokens than this app reads. These
are ignored today – sections ([SECTIONS]), a document-wide
[CONFIG][DESIGN] style block, sub-cards (||, --), sync links
([>card], [>>tab]), sub-tabs, virtual cards (Name), the
+ start-open and . badge markers, group colours and icons, and the
#i / #ti zone letters (only #t does anything).
Two traps worth calling out: a line like {Massing} on its own
makes a tab named Massing, not a section. And + / . markers are not
stripped, so they show up literally in the card title.
A live listing of every node in the definition, with a tag telling you how each one is being handled:
| Tag | Meaning |
|---|---|
| js | Implemented – the engine computes it |
| src | A parameter / input object |
| layer | A reference component: it reads geometry from your layers (see §10) |
| plug-in | Not a native Grasshopper component – a plugin, script or custom node. Passed through untouched. |
| pass | A native component with no implementation yet. Input passes straight through. |
The eye on each geometry-producing row toggles that component's preview, exactly like Grasshopper's own preview flag – the fastest way to work out which node is drawing the thing you don't want.
A state is a saved snapshot of your parameters, with a thumbnail. It is the design-option workflow: try something, keep it, try something else, flip between them.
+ Save in the States header offers three depths:
Then:
.mola file and survive a reload.Caveat. Restoring a state re-solves the model correctly, but the sliders in the Parameters panel keep showing their previous positions until the definition is reloaded. Trust the viewport, not the slider handles. (In Play mode, Reset all does refresh them.)
The third tab in the top-bar switch, beside Model and Graph. It is a full-screen board for evaluating several parameter sets side by side.
Compare is a read-only board: it shows the cached thumbnail and metrics from when each
state was saved rather than re-solving, there is no way to apply a scheme back onto the model from here
(restore it from States instead), and the board itself is session-only – it is not saved into the project.
A scheme added with + Current shows — for its metrics unless the model has geometry.
The Graph tab, for completeness, draws the definition as a node-link diagram laid out from its real Grasshopper canvas positions: drag to pan, wheel to zoom, click a node to inspect it, F to fit.
Play mode strips the app down to a clean configurator – viewport, Parameters, camera – and nothing else. It is what you put in front of a client, and what a share link opens into.
The rail's Play button opens a menu where you tick what the viewer gets, then press Enter play mode:
.stl geometry + .mola project)Everything else goes: the whole top bar (so Model/Graph/Compare, Project and Export vanish), the status bar, Projects, Account, Notices, and the Play menu itself. Parameters always stays. ⤢ Full mode in the corner brings the editor back.
A small floating bar sits at the bottom of the viewport – and you can drag it anywhere; it remembers where you put it. It carries:
.stl or the .mola projectCreate link in the Play menu produces a URL anyone can open – no account, no install. A viewer lands directly in the configurator; there is no way out to the full editor from a share. Their parameter changes and sketches are kept in their own browser, so a refresh doesn't lose their work.
A share is a snapshot, not a live pointer – later edits to your project don't change a link you already sent. And the definition travels with the link: whoever opens it can read the Grasshopper file too. Send links accordingly.
There is no animation timeline. Play mode is a configurator, not a playback mode – parameters do not animate, and there are no keyframes or looping. The only clock in the app is the sun-study scrubber (§13), which is a display feature.
Many Grasshopper files expect you to pick geometry in Rhino. Here you draw it instead – the left rail is a small but real CAD toolset, and what you draw feeds the definition (§10).
| Tool | Key | How it works |
|---|---|---|
| Select | V | Click, Ctrl-click to add, or drag a marquee |
| Orbit / pan | O | Navigate without leaving a drawing tool armed |
| Point | P | Flyout: square point grid (type an edge, or edge,spacing) and radial point grid (radius or radius,spacing) |
| Polyline | Y | Flyout: Line (L) and Region (G, auto-closes on finish) |
| Control-point curve | Rhino convention – your clicks are handles and the curve is pulled toward them. Flyout: Interpolate curve (C, passes through your clicks) and Curve through polyline (click an existing polyline to smooth it) | |
| Rectangle · 3 point | R | Hold Shift for a square. Flyout: rounded rectangle |
| Polygon | Centre, then a vertex – which sets both radius and rotation | |
| Ellipse | Hold Shift for a circle. Flyout: three arcs – start/end/bulge, 3 point, and centre/start/end | |
| Select object | B | Pick the generated geometry rather than your sketch – see §11 |
While a draw tool is active, just start typing numbers – SketchUp-style. The digits set the next
point's distance; Enter commits, Backspace corrects. It works on the box tools too,
where you can type length,width, and on the grids as described above.
The snap button on the rail opens: Endpoint · Midpoint · Center · Perpendicular · Intersection · Grid snap, plus Smart guides (alignment) and Ortho lock. S toggles snapping as a whole.
Shift does two different things on purpose: on the chain tools (line, polyline, curve) tapping it is a sticky ortho toggle that stays on until you tap it again; on the box tools (rectangle, ellipse) it is held to constrain to a square or circle.
Project ▸ Import model / drawing, or the little import icon on any layer row. Supported:
OBJ, STL, PLY, GLB/GLTF meshes and
SVG, DXF drawings. An import dialog lets you set Scale, the source
Up axis (Y-up or Z-up), whether to keep parts or merge, and the target layer
(a new one named after the file, or the current one). The whole import is a single undo step.
DXF import is deliberately minimal: LINE, LWPOLYLINE,
CIRCLE and ARC. Blocks, splines, text and hatches are skipped.
This is the bridge between your sketch and the Grasshopper file. Reference components – Geometry Pipeline, Query Model Objects and friends – read geometry by layer name. Draw on the layer they ask for and the definition picks it up.
When a definition loads, Mola Mola reads which layer names it references and creates those layers automatically, then switches your active layer to the first new one so your next stroke flows straight in. A toast tells you which names it found.
In the Layers panel, any layer the definition actually reads carries a fed badge – hover it to see which components. If a definition has reference components but no specific layer filter, anything you sketch anywhere feeds it.
Each layer row gives you: visibility (eye), lock (visible but not selectable), a colour / line-style swatch, double-click to rename, the fed badge, and a per-layer import button. Add layers from the field at the bottom of the panel.
Select a drawn element and the Inspector lets you set its Layer and Name, and attach any number of key = value attributes. Those matter because reference components can filter on name and attributes, not just layer – so you can draw twenty parcels on one layer and have the definition treat them differently.
At the bottom, the Inspector tells you plainly whether the selected element feeds anything: "feeds 2 pipeline components: Parcels, Roads", or "not matched by any pipeline component". That line is the fastest debugging tool in the app when a definition sits stubbornly empty.
Many Grasshopper files expect you to pick geometry in Rhino: a curve, a surface, a brep. Those inputs arrive here empty, because there is no Rhino document behind them, so the definition has nothing to build from and the viewport stays blank.
This is not a failure of the file. Check the Layers panel for the fed badges, draw or import the missing geometry onto those layers, and the definition runs.
Normal selection picks what you drew. Select object (B on the rail) picks what the definition made – a single tower out of a block of forty-six, a slat out of a pergola – without touching the definition itself. It is the tool that turns a parametric output back into something you can point at, hide, measure and take away.
With the tool armed, a bar appears at the bottom of the viewport:
| Control | What it does |
|---|---|
| Tree level – ] / [ | Widen or narrow the pick up the data tree: L0 a single object → L1 its parent group (a building) → L2 the grandparent (a block). Arm a level first and every click grabs at that depth. This is the feature to reach for on files where one branch is one building. |
| Hide / Unhide all | Temporarily take generated objects out of the view – look inside a massing, or clear a foreground tower – without editing the definition or the parameters |
| Bake selected | Convert the picked objects into editable elements you own: they land on a layer, get an entry in the Inspector, and can be moved, exported and saved with the project |
| Bake ALL | The entire generated model as one editable mesh – the quick way to freeze a design and carry on by hand |
Selecting a generated object also fills the Inspector with a read-only measurement: category and type, bounding Size, Footprint, Height, Volume, and vertex/face counts for meshes. Click a tower, read its area and volume – no Grasshopper wiring required.
The Graph tab is the companion view for reading the definition rather than its output: clicking a node there highlights it on the canvas and reports its name, category and input/output counts. It does not cross-highlight into the model.
There is a lot here, and it is worth ten minutes: the difference between the default view and a tuned one is
the difference between a debug screenshot and something you'd put in a presentation. Everything below is
stored with the project, so reopening a .mola restores the look you saved.
| Group | What you can set |
|---|---|
| Display | Mode · Line weight · Point size |
| Shadows | On/off · Strength · Softness · On geometry (deepens shadows cast between buildings) · Soft shade |
| Style | Clay colour · Outlines on/off and outline colour |
| Ambient occlusion | On/off · Strength · Radius · Half-res or Full quality |
| Sun & environment | Azimuth · Altitude · Animate day · North rose · Floor and its Z height · Fog and amount · Lens |
| Background | Auto (follows the theme), Solid, or a two-colour Gradient |
| Grid | On/off and grid size |
The north wind rose is draggable – spin it to set north, exactly as you would in a plan drawing. Sun angles follow.
| Group | Options |
|---|---|
| Navigation | Rhino (right-drag orbit · shift+right or middle to pan · wheel zoom) · Blender (middle-drag orbit) · Maya (alt+left orbit) |
| Modules | Sun study flavour: Direct (azimuth + altitude + day scrubber) or By location (city + all-year and day ranges) |
| Units | Metric / Imperial, and the scale within it |
| Visuals | Toolbar horizontal / vertical · Accent colour (Azure, Teal, Violet, Earth, or pick your own) · UI density comfy / compact · Slider style normal / bold / light · Panel opacity 45–100% · Render quality Perf / Balanced / Quality · move-axes gizmo on/off · Gizmo style Combined / Toggle |
| Geometry | Curve smoothness, separately for Fillets, Circles & arcs and Curves (1×–8×; higher is finer and heavier) · Edge softening: hide facet lines on curved surfaces, with a normal-angle threshold up to 60° |
The Geometry sliders are the ones to reach for when a fillet or a pipe looks faceted – they change tessellation density, not the underlying geometry. Turn them up for a render, back down while you work.
The sun button opens a banner over the viewport, in one of two flavours (switch in Settings ▸ Modules):
Shadows in the viewport follow the sun position, and buildings shadow each other, not just the floor.
.mola file to disk.A .mola file is the portable one. It carries the definition, your drawn elements, layers,
states, saved cameras and display settings in a single file you can move between machines – which is also
why it is the file to send when you report a bug.
| Format | For |
|---|---|
PNG | An image of the viewport as it looks right now |
OBJ · STL | Meshes – other 3-D software, 3-D printing |
GLB | The whole scene as glTF binary – web viewers, presentations |
DXF | Drawings, for CAD |
DXF · laser / CNC | A flattened 2-D DXF aimed at fabrication |
GeoJSON | Footprints for GIS and mapping tools |
All of it under Export in the top bar. In Play mode, a viewer gets STL and
.mola only, and only if you enabled Downloads.
| Key | Action |
|---|---|
| Ctrl+O | Open a definition |
| Ctrl+S | Save to the in-browser library |
| Ctrl+Shift+S | Save a .mola file to disk |
| Ctrl+Z / Ctrl+Y | Undo / Redo |
| F5 | Reload, returning you to your current work |
| Key | Action |
|---|---|
| V · O | Select · Orbit/pan |
| P · L · Y · G | Point · Line · Polyline · Region |
| C · R | Interpolate curve · Rectangle (while drawing, C closes the sketch) |
| B | Select object – pick generated geometry |
| [ / ] | Narrow / widen the selection up the object tree |
| S | Snapping on / off |
| Key | Action |
|---|---|
| digits, then Enter | Type an exact length / radius / length,width |
| Enter | Finish the current sketch |
| Esc | Undo last point → cancel sketch → back to Select → deselect |
| Shift | Tap for sticky ortho on chain tools; hold for square / circle on box tools |
| Delete | Delete the selection |
| Ctrl+A / C / X / V | Select all drawn · copy · cut · paste |
| Q / W / E, ← → | Move / Rotate / Scale gizmo, and cycle – only when Gizmo style is set to Toggle in Settings |
| Key | Action |
|---|---|
| Tab | Switch between 3D and 2D plan |
| F | Zoom to fit (fits the graph in the Graph tab) |
| Mouse | Rhino by default: right-drag orbit, shift+right or middle pan, wheel zoom. Blender and Maya presets in Settings. |
Mola Mola is an alpha. It re-implements Grasshopper's components; it is not Grasshopper, and it does not embed Rhino's geometry kernel. Here is an honest account of where that shows.
Across a test set of 52 real Grasshopper files (student and practice work, not curated demos) totalling 13,359 components: 97.2% of those component instances have a working implementation, and 43 of the 52 files used nothing unsupported at all. That is coverage of real-world usage. Measured instead against Grasshopper's whole 1,178-object catalogue – including everything nobody ever puts on a canvas – the figure is far lower.
Only Grasshopper's own components are implemented. If a definition uses a plugin, those components pass their input through untouched and the result will differ. The ones we see most:
Solver, Anchor, EdgeLengths, and so on).
This is an iterative solver, not a missing component; supporting it is a separate project.You can see exactly which nodes in your file are affected: open the Components panel and look for the plug-in and pass tags.
C#, VB and Python script components cannot run in the browser; their outputs are empty. Across our test set they are by a wide margin the single biggest source of unsupported nodes – a Python 3 Script component alone accounts for more unsupported instances than every other missing component combined. This is a hard boundary, not a gap we intend to close.
These have implementations, but built on polygon and mesh mathematics rather than true NURBS. They are usually right in shape and can drift in exact position, especially on curved or trimmed input:
Loft · Pipe · Offset Curve · Fillet ·
Sweep1 / Sweep2 · Isotrim · Surface Split ·
Nurbs Curve · Interpolate · Ruled Surface · Offset Surface
Solid Union, Solid Difference and Solid Intersection are not
modelled; their input passes straight through, so you see the un-cut solids. Brep splitting and
trimming (Split Brep, Trim Solid, Cap Holes Ex,
Merge Faces) are in the same position.
Use the 💬 Feedback button at the bottom-right of the app. It sends us the message along with which definition you had open, which is usually what we need to reproduce a problem.
The most useful bug report names the component that misbehaved and what you expected instead. If you
can share the .gh file – or better, the .mola project, which carries your
geometry and settings with it – better still. That is how most of the fixes so far were found.
Bugs and broken definitions: bugs@molamola.cloud
Anything else: hello@molamola.cloud
Written against app version 0.7.235. Definitions you open are confidential pre-release material; see the Terms & Privacy.