Skip to content

Moonomat FAQ

Welcome to the Moonomat FAQ. New here? Start with Getting Started. If you can't find your answer, reach us at support@moonomat.com.

Getting Started & Orientation


What is Moonomat, and who is it for?

Moonomat is a 3d design tool for designers, makers, data visualizers, and hobbyists who want precise, reproducible 3d content without the overhead of a full desktop suite.

It sits in a deliberate niche:

  • AI-native — the Design agent is the flagship way to work: describe what you want, and the agent writes, runs, and refines the underlying design for you. Moonomat was designed around this way of working from the start.
  • Designs as text — every design is a small Moon file. Text is exactly reproducible, diff-friendly, remixable, and ideal for iterative work — change a parameter and the whole model rebuilds.
  • Real modeling operations — booleans, fillets, chamfers, extrude, revolve, sweep, loft, 2d-to-3d workflows, PBR materials, and data-driven generation.
  • Rooted in glTF — the standard for 3d on the web. Moonomat produces display-ready .glb files with automatic UV unwrapping and texture baking, ready for any web viewer, game engine, or AR scene.
  • Good at data visualization — import .csv, .json, or NumPy data and turn rows and tensors directly into geometry.

It runs in any modern browser (installable on Android).


Do I need to install anything?

No. Moonomat runs entirely in the browser — no download, no plugins. On Android you can add it to your home screen for an app-like experience: in Chrome, open the menu (⋮) and choose Add to Home screen.


Do I need an account?

Not to design. Everything local — the editor, the Moon runtime, the 3d viewer, unlimited bundles, sharing by link — works without signing in, and your work is stored on your device.

A free account (Google sign-in) adds the things that need an identity: the Design agent, GitHub sync, and GitHub-hosted publishing. When you sign in for the first time, the bundles you created on that device are adopted into your account — nothing is lost.


What's free, and what does Full Moon add?

Free — without an account: the full editor, the Moon runtime, the 3d viewer, parameters, unlimited local bundles, the asset libraries, and sharing by link. Free — with an account: the Design agent (10 requests per 24 hours, bring-your-own AI) plus GitHub sync and publishing.

Full Moon, the paid plan, lifts the limits: unlimited Design agent use — still bring-your-own AI (your key or your own machine); we never resell or mark up inference — plus Google Drive sync. It is also the best way to support Moonomat's development.


What is Moon, and do I have to learn it?

Moon is a small declarative language for parametric 3d design. A Moon document is a YAML hierarchy of nodes — primitives like Box or Sphere, operations like Union or Extrude, and reusable compositions you define yourself. The Moon runtime evaluates the node graph and produces a single asset: usually a .glb, but also .svg, .png, or .json.

And the honest answer: you don't have to learn it. The Design agent writes and maintains Moon for you — free to try with an account. Learning the basics is still worthwhile: to review what the agent produced, tweak details by hand, or work entirely without AI. The specification and API reference cover everything.


What is a bundle?

A bundle is the unit of work in Moonomat: a self-contained folder of Moon files and assets (models, images, data). Its entry file is main.moon — the design the bundle presents when run or shared. A bundle without a main.moon acts as a library bundle: a collection of reusable parts.

Bundles are portable: a whole bundle packs into a single .moons text file (or .moon.zip in binary form) for sharing, publishing, and syncing. You can keep as many bundles as you like, on every tier.


Where do my files live — locally, in the cloud, or both?

By default, on your device, in the browser's storage (IndexedDB). Your content is never uploaded to Moonomat's servers.

Browser storage quotas typically allow from hundreds of megabytes up to many gigabytes per site — Chrome allows up to 60% of free disk space. Large binary imports count against this.

For cloud backup and working across devices, connect the Transfer panel to your own GitHub repositories (free, signed in) or Google Drive (Full Moon). Both remotes live in your accounts — Moonomat never holds your data.


Is my work private?

By default, yes — your bundles live only on your device, like files in desktop software. Keep your device secure and they're yours alone.

Sharing is always an explicit act: publishing a link, pushing to a GitHub repo, syncing to Drive, or downloading and sending a file. Each of those paths is described below.


How do I import existing files into a bundle?

Two ways:

  • From the Explorer — right-click and choose Import, or simply drag and drop files or folders onto the Explorer panel.
  • By URL — reference a publicly hosted file directly from an import: node in Moon. Browsers may block the request if the host doesn't allow cross-origin access (see the CORS question below).

Supported formats include glTF (.glb/.gltf), .obj, .stl, STEP CAD files, .svg, images, fonts, and data (.csv, .json, NumPy) — the full table is in the Moon section below.


The Design agent


What can the Design agent actually do?

It's a true agent, not a chat window: it explores your bundle, reads and searches files, writes and edits Moon, and verifies its own work. Every .moon file it writes or edits is validated and executed immediately — if validation fails, the agent sees the errors and fixes them. After a successful change it renders the 3d result and checks the image against your intent before reporting back.

Each agent step lands on the same undo stack as your own edits — one Undo reverts it (see below).


What do I need before I can use it?

Two things, both quick:

  1. Sign in free (Google) — the agent is metered per account and its connection settings live in your profile.
  2. Connect an AI backend — Moonomat never bundles or resells AI. You bring your own: an OpenRouter key, your Claude or ChatGPT subscription, or a server you run yourself.

Then open the Design panel and start prompting. Free accounts get 10 requests per 24 hours; Full Moon removes the cap.


Which AI backends are supported?

Three kinds, switchable in the Design panel header:

  • OpenRouter — one account for virtually all current AI models. Click Connect, authorize Moonomat on OpenRouter (you can cap its spending there), and pick a model. Credits are paid directly to OpenRouter; Moonomat takes no cut.
  • Claude / Codex — connect the agent to your Claude (Pro/Max) or ChatGPT (Plus/Pro) subscription via a small open-source bridge you run on your computer (setup instructions in the panel). Great if you already pay for one of them.
  • Your own endpoint — any OpenAI-compatible server, local or remote: Ollama, LM Studio, llama.cpp, vLLM on your own machine, or a cloud API (OpenAI, Groq, Together, Mistral, xAI) with your key. A local Ollama endpoint is pre-configured as a starting point.

All backends are treated the same: sign-in plus the same meter — because in every case the inference is yours.


Which model should I pick, and what is "thinking effort"?

On OpenRouter we mark recommended models — ones we've tested on Moon tasks; you can pick anything that meets the minimum requirements (large context, image understanding). There's a real trade-off between capability and cost: cheap models handle small edits; for complex iterative design, state-of-the-art models usually save more time than they cost.

Thinking effort controls how much internal reasoning the model spends before acting. Start low; raise it when the agent struggles with a multi-step task.


How does the free request meter work?

One "send" = one request, no matter how many files the agent reads, edits, or runs within it. The free allowance is 10 requests per 24 hours, in a fixed window starting from your first request; when you hit the cap, the app tells you when it resets. Requests that fail are refunded.

The meter exists because what Full Moon sells is unlimited use of the Design agent — the AI underneath is always brought by you, at cost.


Does Moonomat charge for AI usage?

No. Moonomat never earns money on your AI spend. OpenRouter bills you directly for tokens; Claude / Codex usage rides on your existing Claude or ChatGPT subscription; your own endpoint is your own hardware or API contract. Moonomat charges only for the plan (unlimited agent use + Drive sync), never for inference — and there is no markup, no reselling, and no silent fallback to some other provider.


Can the agent see my 3d scene?

Yes — in two ways:

  • It looks by itself. After edits, the agent renders the result (a 3×3 multi-view covering nine standard angles) and compares it against your request.
  • You show it something specific. The attachment menu (paperclip) offers Capture Current 3D View (exactly what you framed), Capture Scene Multi View, Upload Images (references, sketches), and Files from Bundle.

How do sessions work?

The agent keeps one session per bundle, per backend — switch bundles and you're back in that bundle's conversation; switch backends and each keeps its own thread. New Session starts fresh (the old session for that bundle is deleted).

Sessions keep context focused; start a new one when you switch to an unrelated task.


How do I write a good prompt?

Be specific. Iterate.

A bad prompt:

"Generate a 3-bedroom house."

The model can't know what your house should look like — and unlike an image generator, it won't fake an "average" one. You stay the designer; the agent translates intent into Moon.

A good workflow:

"Make a box, 1 meter, blue." "Now put a red sphere on top, 20 cm, centered." "Make the sphere smaller and matte."

Describe the object the way you'd mentally construct it. If something's wrong, say so plainly — "that should sit on the floor, not float". If a file has an error, just ask the agent to fix it. The key insight: this is iterative, not one-shot.


Can I stop or undo something the agent did?

Yes, three levels:

  • Undo (Ctrl+Z or the toolbar) — each agent step is a single entry on the same undo stack as your own edits; one undo reverts a whole step. The history terminal command lists what would be undone.
  • Ask the agent — "revert the last change", "remove the box you added". Natural language works.
  • Duplicate first — for big experiments, duplicate the bundle beforehand (bundle menu → Duplicate), or push to GitHub so you can compare and roll back via Transfer.

Is my prompt content sent to third parties?

It's sent to the backend you chose — and only there. With OpenRouter, prompts, attached images, and tool calls go through OpenRouter to the model provider you selected (review their retention policies before sending anything sensitive). With Claude / Codex, they go to Anthropic or OpenAI under your subscription. With a local endpoint (e.g. Ollama), everything stays on your machine.


Can the agent work offline or fully on-device?

The agent can run on your own hardware — connect a local endpoint like Ollama or LM Studio and no prompt ever leaves your machine. Be aware that agentic coding is demanding; small local models are fine for parameter tweaks and simple edits, while complex construction favors frontier models. Sign-in and the meter still apply (they're what the free tier and Full Moon differ on).


The App


What are the icons in the sidebar, and what does each panel do?

Design — the AI agent (the labeled entry at the top)

The Design agent: prompt input, conversation, backend and model pickers, thinking effort, and the attachment menu. Signed-out users see a sign-in invitation here — the agent needs a (free) account.

Explorer — the bundle's file tree

All files in the open bundle. Selecting a file shows it in the matching viewer (3d model, image, SVG, data, …) and — for text formats — the Editor. Right-click for the usual operations: new file, rename, delete, import, download. Folders are created implicitly by writing paths like parts/lid.moon.

Search — full-text search

Search the contents of every file in the bundle, with results grouped by file.

Editor — the code editor

A full code editor (the engine that powers VS Code). Moon files get YAML syntax highlighting, schema-aware validation and hovers, and error markers from the last run. Saving is automatic — every edit is persisted immediately.

Parameters — tweak a design without touching code

Interactive controls for the selected .moon file's parameters — sliders, color pickers, toggles, and more, derived from the parameters' metadata. See the Parameters question below.

Transfer — sync bundles with your own cloud

Manual push / pull / compare between local bundles and your GitHub repositories (free, signed in) or Google Drive (Full Moon). See the Sync section.

Publish — share a design

Share links and QR codes, the GitHub-hosted Viewer link, the website embed snippet, and downloads. See the Sharing section.

Libraries — ready-made content

Browse example designs and assets, preview them, and copy anything into your bundle as a starting point. Available without an account.

Settings — viewer options

3d viewer controls — rendering engine, brightness, background, model scale, AR mode, coordinate-system overlay, wireframe, vertex normals — plus live scene statistics (vertices, triangles, materials, bounds).

Help — docs, runtime status, about

Links to this documentation, app and Moon runtime version info, live memory usage, and a Restart button for the Moon runtime.

There is also a terminal: the status strip in the header shows the most recent command — click it to open the full terminal (see below).


How do I create, rename, duplicate, or import a bundle?

The bundle name in the header is a menu: New Moon bundle, Import Moon bundle… (open a .moons or .moon.zip from disk), Duplicate, Rename, and Delete, plus the list of your bundles for switching. Bundles are unlimited on every tier. A fresh bundle starts with a small parameterized main.moon that runs as-is.


Which file types can the app display?

Each format opens in a dedicated viewer: 3d models (.glb/.gltf, plus imported .obj/.stl/STEP shown as models), images, SVG, JSON, CSV tables, NumPy arrays, fonts, Markdown, HTML, and plain text for everything else. Selecting a .moon file shows its latest run result.


What does the Run button do?

Run (or Ctrl+Enter) evaluates the selected .moon through the Moon runtime: parse, link (resolve imports and references, type-check), evaluate the node graph, bake materials for glTF output, and write the result to the bundle's export/ folder — then shows it in the viewer. Errors come back with line numbers and appear as markers in the Editor.

You don't need to run constantly: a bundle that has never produced output runs automatically when opened, and the viewer always shows the newest result for the selected file.


Why is the Run button sometimes greyed out?

Run needs a runnable .moon file selected, and an idle runtime — it's disabled while another run is in flight (including in another tab; the Moon runtime is shared across tabs). Long runs can be cancelled with Ctrl+C in the terminal.


What is the Parameters panel, and does it change my file?

If a .moon file declares params:, the Parameters panel (and the standalone Viewer) render interactive controls for them — sliders with bounds, number/text inputs, color pickers, toggles, vector fields — based on the parameter metadata (kind:, min:/max:/step:, choices:, label:, doc:, category:; see the Moon section).

Tweaking parameters never edits your source file: the values run through a generated wrapper under export/, and the viewer shows that result. Reset discards the overrides and returns to your defaults.


What is the terminal?

A command line over the open bundle: POSIX-style file verbs (ls, cat, mv, …) and moon … commands for everything else (run, render, share, sync). The terminal, the UI, and the Design agent are three front-ends to the same commands — everything lands on the same undo stack and the same history, and the terminal doubles as the app's live activity log. help lists everything; see the Terminal reference.


Are there keyboard shortcuts?

  • Ctrl+Enter — run the open .moon file.
  • Ctrl+P — quick-open a file by name.
  • Ctrl+Z / Ctrl+Y — undo / redo (agent steps count as single entries).
  • The Editor supports the standard VS Code editing shortcuts.
  • Saving is automatic — there is nothing to press.

Can I have multiple browser tabs open?

Yes. Write access simply follows the tab you're using: the active tab holds the bundle's write lock, and a background tab takes over automatically the moment you return to it — no banners, no cleanup. Note the Moon runtime is shared across tabs, so only one run executes at a time.


What is the export/ folder?

Generated output: every run writes its result there, mirroring the source path (parts/lid.moonexport/parts/lid.glb), along with screenshots from moon render. It persists locally so results survive reloads, but it is not included when a bundle is packed, published, or synced — it can always be regenerated. Right-click any file in it to download; remove files with rm in the terminal.


How large can a bundle be?

Bundle imports are capped at 2 GiB, and total local storage is governed by your browser's quota (Chrome allows up to 60% of free disk). In practice, keep an eye on large binary imports — heavy .glb files and high-resolution textures dominate.


Sharing & Publishing


How do I share a design?

Open the Publish panel. Sharing is where designs-as-text pays off — you share the live parametric design, not a frozen mesh:

  • Inline link & QR code — the whole design travels inside the URL (up to roughly 8,000 characters after compression; small and medium designs fit easily). Anyone with the link sees it instantly — no account.
  • GitHub link — for bigger bundles: push the bundle to a public GitHub repository in Transfer, and Publish gives you a permanent hosted Viewer link.
  • Download — the packed .moons / .moon.zip, or the rendered .glb from export/, for use anywhere.

What is Moonomat Viewer?

A free, viewer-only companion app at moonomat.com/view — no account, no editor: just the model, orbit controls, and its parameter panel. Every shared link and embed opens there. The small Moonomat mark in the corner leads back to Moonomat — for link-shared designs it offers View source, opening the design in the Moonomat app to remix — so your audience can go from viewing to creating in one click.


Can people play with my design's parameters?

Yes — this is the point of publishing Moon rather than a mesh. The Viewer shows interactive controls for every parameter your design declares (see parameter metadata in the Moon section). You can even pre-set values in a shared URL — ?params.radius=0.4&params.style=matte — to share specific variants of one design, or hide the panel entirely with ?parameters=false.


How do I embed a design on my own website?

Publish → Embed gives you a copy-paste snippet using the <moonomat-viewer> element. Your page gets the full interactive Viewer — 3d orbit and parameters included. The generated snippet loads the bundle from your public GitHub repository, so it requires the bundle to be pushed, in sync, and public there (the hosting is your repo; it keeps working as long as the repo exists, independent of your Moonomat plan). <moonomat-viewer> itself isn't tied to GitHub, though: its src can point at a packed .moons hosted on any publicly reachable URL.


Sync & Collaboration


How does the Transfer panel work?

Transfer is manual, explicit sync of whole bundles between your device and remotes you own: Push uploads your local state, Pull fetches the remote state, and Compare shows what differs (modified / added / deleted, with per-file diffs) before you decide. Bundles travel as packed .moons files. Nothing syncs automatically — no surprise uploads.


How do I connect GitHub?

Free, with a sign-in. Install the Moonomat GitHub App on your account, then grant it access to specific repositories via Manage repository access — installation alone grants nothing. Public and private repos both work; permissions are governed entirely by GitHub. For security, signing out of Moonomat clears the GitHub connection; just click Connect again next time.

GitHub is also the best fit for .moon work generally: text designs diff, version, and review like code.


How do I connect Google Drive?

Drive sync is part of Full Moon. Connecting asks for a narrow, incremental Google Drive permission that only covers files Moonomat itself creates, inside a Moonomat folder in your Drive — Moonomat cannot see anything else in there. Your synced bundles remain plain files in your own Drive: even if you downgrade, everything stays reachable at drive.google.com.


How do I work across multiple devices?

Connect the same remote on each device and use the classic rhythm: pull before you start, push when you're done. Any device with the bundle pulled has a full local copy — Transfer is sync, not streaming.


Can several people collaborate on one bundle?

Yes — via a shared remote: add collaborators to the GitHub repo, or share the Drive folder with their Google accounts. Everyone works on their own local copy and syncs via Push/Pull. Moonomat does not merge concurrent edits (see next question), so agree on who edits what, or work in turns.


What happens if the same file changed on two devices before syncing?

Compare shows the conflict, but resolution is manual — Moonomat never auto-merges. A safe routine: duplicate your local bundle (or copy the affected file), Pull, merge your changes back in the Editor, then Push. Text-based designs make the merge itself straightforward.


Are my GitHub / Google / AI tokens stored securely? Can I revoke access?

Standard OAuth practice: short-lived tokens held in your browser under your signed-in profile, never on Moonomat's servers. Signing out wipes them all from the device. You can also revoke Moonomat from the provider's side at any time:


The Moon Language

Everything about Moon itself — the full picture lives in the specification, the API reference, and the ECMAScript guide; these are the questions that come up most.


What is the minimal structure every .moon file must have?

The root of a Moon document is always a Composition: it declares the language version, a doc: description, and a render: node — the thing it produces.

yaml
moon: "1.0"
doc: |
    A sphere with a radius of 0.5 meters
render:
    op: Sphere
    with:
        radius: 0.5

Why does my file need moon: "1.0" at the top?

It declares the language version. The current version is 1.0, but the specification is still being refined — the app and runtime always ship the latest spec, and files may need small updates as things evolve. Only the root composition carries this property; inner compositions must omit it.


What is doc: for?

On a composition it is required — it documents the component's contract and is the most valuable documentation you can write (the Design agent reads it too). On any other node it is an optional annotation: a free-form note the runtime ignores. Regular YAML # comments also work anywhere.


What's the difference between a Composition, an Operation, and an Expression?

Three ways a node produces its output:

  • Composition (render:) — a reusable blueprint you define, like a function declaration: optional params: (the external interface), optional assets: (internal named pieces), and a render: as its return value. Invoked with use:.
  • Operation (op:) — a call to a built-in function by name (Box, Union, Transform, …). The declarative bread and butter.
  • Expression (expression:) — an escape hatch into sandboxed ECMAScript for logic that's awkward as a node graph: loops, math, array transformations.

When should I use op: vs. expression:?

Prefer op:. The declarative form is shorter, type-checked at link time, cached more precisely, and easier for both humans and the Design agent to read. Reach for expression: only for genuine logic — and even there you can call operations as functions (Box({...}), Union([...])), so you never have to choose one world exclusively.


When should I use pipe: vs. nested input:?

They produce identical results. pipe: reads top-to-bottom like a Unix pipe and wins for linear chains of more than two steps; nested input: fits single steps and branching graphs.


When should I use group: vs. items: vs. Union?

  • group: — merges assets of the same type with the cheapest strategy: for glTF a lazy scene assembly (no geometry math), for tables row concatenation, for JSON a deep merge.
  • items: — builds a list to pass to a multi-input operation (Union, Difference, Intersection, Stack, …). It merges nothing itself.
  • Union — a true boolean solid merge, computing actual geometry.

Rule of thumb: group: to assemble a scene; items: + Union to fuse overlapping solids into one watertight body.


What's the difference between params: and assets:?

  • params: — the composition's external interface: defaults the caller can override via with:. Think function arguments.
  • assets:internal named intermediate results, invisible from outside. Use them to break a complex render: into labeled pieces or reference a subgraph several times.

How do I make my parameters user-friendly (sliders, colors, choices)?

Declare a parameter in expanded form — a default: plus metadata — and every parameter UI (the Parameters panel, the Viewer, shared links) picks it up:

yaml
params:
    radius:
        default: 0.5
        kind: number
        min: 0.1
        max: 2
        step: 0.1
        label: Radius
        doc: Outer radius in meters
        category: Shape

kind: selects the widget: number, string, boolean, color, position, direction, rotation, scale, or raw. Numbers and strings take choices: for dropdowns; label:, doc:, and category: control presentation and grouping. Plain scalars infer a sensible widget automatically; everything else without a kind: is edited as raw Moon. Metadata is advisory UI information — with one useful exception: direction normalizes and rotation wraps to 0–360 at evaluation.


How do I reuse code across multiple .moon files?

Treat Moon files as parameterized components:

  1. Split a scene into files with one responsibility each (a door, a chair, a wing profile) — each can be viewed and run in isolation.
  2. Expose configurable properties via params: with sensible defaults.
  3. Pull a component in with import: and invoke it with use::
yaml
render:
    use:
        import: ./components/chair.moon
    with:
        height: 0.9

Importing the same file many times is cheap — identical subgraphs are computed once (see caching, below). The Libraries panel is this pattern at scale: browse ready-made components and copy them into your bundle.


What does produces: do on an expression, and when is it required?

An expression returns a data asset (numbers, strings, arrays, plain objects) by default. If it produces anything else — geometry, contours, a material — declare it:

yaml
expression: |
    Union(positions.map(p => Transform({ input: Box({ size: [1,1,1] }), translate: p })))
produces: GLTF

This lets the linker type-check the document before running it, and the runtime verifies the declaration against what actually comes back — precise errors instead of mysterious failures.


How do conditionals work — if: vs. match:?

if: for binary boolean branches (the condition must be a real boolean — no truthy/falsy coercion). match: for multi-way selection on a discrete key — enum-style params, three or more named branches — with an optional default:. Only the selected branch is evaluated; the others cost nothing.


Which JavaScript can I use inside an expression:?

Modern ECMAScript 2023, in a strict sandbox: expressions are pure functions of their inputs, with no network, filesystem, clock, or mutable global state. async/await and class are rejected at parse time (scripts are synchronous; use factory functions), and a multi-statement script must end in an explicit return.

The dedicated ECMAScript guide is the full reference — every available method, the exact sandbox rules, worked patterns, and every example verified against the Moon runtime.


How does randomness work in Moon?

Deterministically. The runtime caches aggressively and identical inputs must produce identical output — so Math.random() and Date.now() are simply blocked inside expressions.

Instead, seed randomness through parameters: use the built-in RandomNormal({ shape, seed }) for random tensors, or expose a seed param and derive values from it. Reproducible by construction — and changing the seed gives you controlled variations.


Can expressions fetch data from the internet or read files?

No — expressions are fully sandboxed, for security and reproducibility. External data enters only through import: nodes, which are visible and auditable in the document.

Remote imports are subject to CORS: the host must explicitly allow browser access (Access-Control-Allow-Origin). Public CDNs and GitHub raw URLs typically do; arbitrary websites often don't — and there's nothing any web app can do to bypass that. The reliable workaround: download the file once, drop it into your bundle, and import it by relative path.


What coordinate system does Moonomat use? Which way is "up"?

The glTF 2.0 convention: right-handed, Y-up, +Z toward the viewer. All measurements are in meters — model at real-world scale (a chair is 0.8, not 80). Imports from Z-up tools (Blender, many CAD packages) typically need a Transform with rotate: [-90, 0, 0]. Imperial units aren't built in; convert in an expression (inches * 0.0254).


What file types can I import, and what gets lost?

ExtensionBecomesNotes
.glb, .gltf3d modelFull fidelity — materials, UVs, scene graph preserved.
.obj3d modelMesh only; .mtl materials are ignored.
.stl3d modelMesh only; STL has no materials.
.step, .stp3d modelCAD B-rep, tessellated on load.
.svg2d contoursPaths tessellated to polygons; curve data not retained.
.csvData (table)Numeric and text columns auto-detected.
.npy, .npzData (tensor)NumPy arrays.
.jsonDataVerbatim.
.png, .jpg, .webp, .bmp, .gif, .tga, .tifTextureChannel count auto-detected.
.ttf, .otfFontFor the Text operation.
.moonCompositionA full component with its params.

If your source tool can export .glb, prefer it over .obj/.stl — it's the richest format. And prefer files inside your bundle over remote URLs: no CORS trouble, no re-fetching.


Why did my imported .glb lose its textures after Union or Difference?

The most common gotcha. A 3d asset exists in one of three internal forms — raw glTF, triangle mesh, and CSG (watertight solid) — and boolean operations force promotion to CSG, which carries no UVs or material assignments. So booleans strip imported materials.

Strategies:

  • Do booleans on primitives first, then apply materials afterward with ApplyMaterial.
  • Use group: instead of Union when you only want to assemble a scene — it preserves everything.

What is "CSG", and why does watertightness matter?

Constructive Solid Geometry represents shapes as closed, watertight solids — the only setting where booleans are mathematically well-defined (a shape needs an unambiguous inside and outside). All Moonomat primitives are watertight; arbitrary imported meshes may not be, and a boolean on a non-watertight import silently produces an empty result. If a boolean on an import comes back empty, watertightness is almost certainly why.


How do I apply a material to only part of my model?

Apply materials to the parts before combining, not after — ApplyMaterial affects only its input: subgraph, and later grouping preserves what's already applied:

yaml
render:
    group:
      - op: ApplyMaterial
        with:
            material: { asset: red_matte }
        input:
            op: Box
            with: { size: [1, 0.1, 1] }
      - op: ApplyMaterial
        with:
            material: { asset: blue_metal }
        input:
            op: Sphere
            with: { radius: 0.3 }

What's the difference between ApplyMaterial and OverrideMaterial?

  • ApplyMaterial — fills in materials only where none exist yet. A default; existing materials on inner parts win.
  • OverrideMaterial — unconditionally repaints everything.

How do I use an image as a texture?

Import the image into your bundle and pass it to Material — image files are automatically recognized as textures:

yaml
op: Material
with:
    color:
        import: ./textures/wood_Color.jpg
    normal:
        import: ./textures/wood_NormalGL.jpg
    roughness:
        import: ./textures/wood_Roughness.jpg

Per the glTF conventions: color is sRGB; normal maps use the OpenGL ("GL") variant; roughness and metallic are single-channel. textureSizeInMeters sets the physical size of one texture tile on the surface (1.0 = one square meter, 0.25 = a much finer repeat) — which is why seamlessly tileable textures work best; that's the standard format PBR libraries ship.


How do I make rounded edges?

Four tools for four situations:

  • Chamfer — a flat cut across an edge (distance). Cheap, looks engineered.
  • Fillet — true circular rounding (radius). Organic, but the radius must stay below half the thinnest feature or that feature collapses; heavier to compute.
  • RoundedBox — want a rounded box? Use this instead of Box + Fillet: dramatically faster and mathematically exact.
  • Smooth — subdivision smoothing that preserves sharp edges above an angle threshold; good for organic shapes.

How do I turn 2d SVG contours into a 3d object?

Four operations, four kinds of geometry: Extrude (straight up, with optional twist/taper), Revolve (lathe around Y — bottles, bowls), Sweep (along an arbitrary 3d path — pipes, cables), and Loft (blend between cross-sections at different heights).


How do I create 3d text?

Build 2d outlines with Text, then extrude:

yaml
render:
    op: Extrude
    with:
        height: 0.05
    input:
        op: Text
        with:
            text: "Hello"
            fontSize: 0.3
            alignX: center
            alignY: center

Custom fonts: import a .ttf/.otf into your bundle; a default font is embedded as fallback.


How does the 2d SVG plane map into 3d space?

The SVG plane becomes the 3d X-Z plane (the floor): SVG +X → 3d +X, SVG +Y → 3d +Z. Extruding along +Y lifts profiles off the floor naturally. One SVG user unit = 1 meter internally; on export, dimensions are written in millimeters so vector editors show expected physical sizes.


Performance & Troubleshooting


Why is my file slow to run?

Diagnose before optimizing — the run output reports timing per phase:

  • Evaluation heavy? Usually one expensive operation: a boolean on a high-resolution mesh, a Fillet at fine resolution, a Smooth with many subdivisions.
  • Baking heavy? Many materials / large textures on a complex mesh.
  • Linking heavy? Remote imports being re-fetched — copy them into the bundle.

General rules: lower resolution: on primitives where it doesn't show, prefer group: over Union when you don't need a fused solid, and RoundedBox over Box + Fillet. Isolate a suspect part into its own .moon file to measure it alone.


How does caching work?

Any subgraph with identical declaration and inputs is computed once — re-runs, repeated imports, and repeated use: calls of the same component with the same arguments are nearly free. This is also why determinism is enforced (see the randomness question): the cache must be able to trust that same inputs mean same outputs.


I'm hitting memory limits — what can I do?

The Help panel shows the Moon runtime's live memory usage. To reduce the footprint: lower resolution: on primitives, split very large scenes into parts you work on separately, and reduce texture sizes. If the runtime accumulated too much over a long session, Help → Restart gives it a clean slate (your files are untouched — only the in-memory cache resets).


A run hangs or the tab freezes — what should I do?

First, Ctrl+C in the terminal cancels a running moon run. Runaway native computations are watched by a watchdog: a wedged runtime is restarted automatically and the run fails with an error instead of hanging forever. Long computations are fine — the watchdog only steps in when the engine stops reporting progress — but a single run is capped at 10 minutes, after which it is stopped with an error. If the whole tab is stuck, close and reopen it — your bundle is persisted on every edit, so nothing is lost.

The usual suspects: booleans on very high-resolution meshes, fillets with a radius larger than the thinnest feature, and huge tensor operations.


The 3d view went black or disappeared

On some devices (especially Android) the browser can discard the 3d context under memory pressure. Moonomat detects this and rebuilds the viewer automatically; if a view ever stays black, switching files or reloading the tab restores it. Your design is unaffected — this is purely display-side.


The Design agent says "Thinking…" and never responds

Reload the page — a model stream occasionally gets stuck mid-flight (network blip, provider hiccup). Your session is preserved; failed requests don't count against your meter.


The viewer shows an old result after I edited

The viewer shows the newest produced output for the selected file — if you edited the source and haven't re-run, you're seeing the previous run. Press Run (Ctrl+Enter).


What hardware and browser do I need?

Any current browser on WebGL2 — effectively every modern desktop and mobile browser. A laptop with integrated graphics comfortably handles scenes intended for web delivery; all geometry processing runs locally in the browser (WebAssembly), so a faster machine means faster runs.


How do I report a bug or request a feature?

Email support@moonomat.com. For bugs, include what you expected, what happened, a minimal .moon file that reproduces it if applicable, and your browser/OS/app version (Help → About). Independently reproducible reports get fixed fastest.


Account, Privacy & Billing


Who owns the content I create with Moonomat?

You do. Always.


Can I use Moonomat output commercially?

Yes — no royalties, no per-output licensing. Third-party assets you import (textures, models from external libraries) keep their own licenses; respect them as you would anywhere.


What data does Moonomat store about me?

In short: authentication identifiers, subscription status, a small request counter for the free Design agent allowance, and pseudonymized analytics — not your files, designs, prompts, name, or email. Your content lives on your device and in remotes you own. See the Privacy Policy for the complete breakdown.


What happens when I sign out?

All provider tokens (Google, GitHub, AI backends) are wiped from the device. Your bundles stay in local storage and reappear when you sign back in. Signing out never deletes work.


How do I delete my account?

User menu (bottom of the sidebar) → Account & PrivacyDelete my account. This cancels any active subscription and removes your server-side records. Local files on your device remain until you clear them yourself. Deletion requires being signed in — only the verified account holder can trigger it.


What happens if I cancel Full Moon?

Nothing is trapped, by design. Every bundle stays local; everything synced sits as plain files in your own Drive and GitHub, still reachable there; published GitHub embeds keep working. You lose the in-app conveniences — unlimited Design agent use (back to 10/24h) and the Drive sync surface. Back up anything you care about by pushing it or downloading the packed bundle first, and you can resubscribe anytime.