- Docs
- Build for Thingport
SDK reference
Everything the thingport object has: what a widget’s or a tool’s default export is called with. Most of it is the
same for both; the At a glance table says which has what, and a member that differs shows each form. How a script
runs, and what it may reach, is in the overview.
Signatures are written in TypeScript; scripts are plain JavaScript. For an editor that completes thingport. and
checks your calls, put thingport.d.ts beside the script and start it with:
// @ts-check
/** @param {import("./thingport").WidgetSdk} thingport */export default function mount(thingport) {}For a tool, the type is ToolSdk.
At a glance
Section titled “At a glance”| Member | Widget | Tool | What it is |
|---|---|---|---|
root | ✓ | ✓ | The element to draw into: the panel or the window, with the HTML already in it. |
selector | ✓ | ✓ | A CSS selector for root, unique on the page, to scope styles to it. |
size | ✓ | ✓ | The size of root in pixels, kept current as it’s resized. |
onResize | ✓ | ✓ | Hears when root is resized. |
theme | ✓ | ✓ | Thingport’s colours and font, light or dark. |
settings | ✓ | The panel’s settings, as the metadata’s settings declares them, with their defaults filled in. | |
widget | ✓ | The widget itself. | |
widgetId | ✓ | The widget’s id, as widget.id. | |
instanceId | ✓ | This panel’s id, for a widget that’s on the dashboard more than once and keeps something per panel. | |
language | ✓ | ✓ | The language Thingport is in, as a code like "en" or "lt", already matched to one it has ("pt-BR" gets "pt" where that exists, else "en"). |
languages | ✓ | ✓ | Every language Thingport has, English first. |
t | ✓ | ✓ | The script’s own words, from its locales/<code>.json labels, in the user’s language. |
labels | ✓ | ✓ | Fills in the script’s words in its markup: data-t sets an element’s text, and data-t-title, data-t-aria and data-t-placeholder fill those attributes. |
models | ✓ | ✓ | The user’s models, as the user. |
collections | ✓ | ✓ | The user’s collections. |
fetch | ✓ | ✓ | A request to one of the hosts the metadata’s hosts lists, made by the Thingport server, so CORS and the local network aren’t in the way. |
api | ✓ | ✓ | Thingport’s own REST API, as the user, signed in as the page is. |
download | ✓ | ✓ | Hands the user a file to keep, as a browser download. |
ui | ✓ | ✓ | Thingport’s own toast and confirmation. |
achievements | ✓ | ✓ | The user’s achievements: badges for what they do in Thingport, while an admin has them on. |
close | ✓ | Closes the tool’s window. | |
library | ✓ | ✓ | A library Thingport carries, for a job a script can’t fit inside itself. |
libraries | ✓ | ✓ | The names library() takes. |
tool | ✓ | The tool itself. | |
context | ✓ | What the tool was opened on: { modelId } when it’s opened on a model, and empty when it’s opened from the Tools page. | |
storage | ✓ | JSON kept for this user and this tool, so the window opens where they left it. | |
toolModels | ✓ | The models a tool from the repository brings, by the keys its metadata gives them. | |
fetchToolModels | ✓ | Fetches the tool’s models that aren’t here yet and gives the user their copies. |
Basics
Section titled “Basics”Widgets and tools
thingport.root: HTMLElementThe element to draw into: the panel or the window, with the HTML already in it. The theme is on it as CSS variables (see theme). Draw only inside it; it’s emptied when the script stops.
thingport.root.querySelector("h2").textContent = "Hello";selector
Section titled “selector”Widgets and tools
thingport.selector: stringA CSS selector for root, unique on the page, to scope styles to it.
style.textContent = `${thingport.selector} .row { display: flex; }`;In a widget:
thingport.size: WidgetSizeThe size of the panel in pixels and in grid cells, kept current as the user resizes it.
See WidgetSize.
In a tool:
thingport.size: SdkSizeThe size of root in pixels, kept current as it’s resized.
See SdkSize.
onResize(listener)
Section titled “onResize(listener)”In a widget:
thingport.onResize(listener: (size: WidgetSize) => void): () => voidHears when the panel is resized.
| Parameter | What it is |
|---|---|
listener | Called with the new size. |
Returns: A function that stops it, for the cleanup.
See WidgetSize.
const stop = thingport.onResize(({ cols }) => list.classList.toggle("wide", cols >= 6));In a tool:
thingport.onResize(listener: (size: SdkSize) => void): () => voidHears when root is resized.
| Parameter | What it is |
|---|---|
listener | Called with the new size. |
Returns: A function that stops it, for the cleanup.
See SdkSize.
const stop = thingport.onResize(({ width }) => root.classList.toggle("narrow", width < 400));Widgets and tools
thingport.theme: SdkThemeThingport’s colours and font, light or dark. The same values are on root as CSS variables, so a stylesheet can use them without the script copying anything across. The script runs again when the user changes theme.
See SdkTheme.
canvas.style.background = thingport.theme.paper;settings
Section titled “settings”Widgets only
thingport.settings: Record<string, any>The panel’s settings, as the metadata’s settings declares them, with their defaults filled in. A toggle is a boolean; text, number and choice settings are strings, numbers included. The widget runs again when they change.
const every = Number(thingport.settings.refresh) * 1000;widget
Section titled “widget”Widgets only
thingport.widget: { id: string; slug: string; name: string; version: string; source: "own" | "community" }The widget itself. source is "own" for one the user made, "community" for one installed from the repository.
widgetId
Section titled “widgetId”Widgets only
thingport.widgetId: stringThe widget’s id, as widget.id.
instanceId
Section titled “instanceId”Widgets only
thingport.instanceId: stringThis panel’s id, for a widget that’s on the dashboard more than once and keeps something per panel.
language
Section titled “language”Widgets and tools
thingport.language: stringThe language Thingport is in, as a code like "en" or "lt", already matched to one it has ("pt-BR" gets "pt" where that exists, else "en"). The script runs again when the user changes language, so this is read once rather than watched.
languages
Section titled “languages”Widgets and tools
thingport.languages: SdkLanguage[]Every language Thingport has, English first.
See SdkLanguage.
t(key, vars?)
Section titled “t(key, vars?)”Widgets and tools
thingport.t(key: string, vars?: Record<string, unknown>): stringThe script’s own words, from its locales/<code>.json labels, in the user’s language. A missing word falls back to English key by key, and a key with no words anywhere comes back as itself, so the gap shows.
A number as count picks the plural form: the label has a key per form, <key>.one, .two, .few, .many and .other, and each language gives the ones its own rules use (English one and other, Russian one, few, many and other, the last for fractions such as 1.5), with .other standing in for a form it hasn’t. Thingport before this returns the key itself: a script that must run on one picks the form there, as Intl.PluralRules names it, and asks for <key>.<form>, then <key>.other.
| Parameter | What it is |
|---|---|
key | The label’s key. |
vars | Values for the {name} placeholders in it, and count to pick a plural form. |
Returns: The sentence.
t("rings.ring", { n: 2 }); // "Ring 2", or "Žiedas 2" in Lithuaniant("bar.pieces", { count: 21 }); // "pieces", or "деталь" in Russian, where 21 takes the one formlabels(where?)
Section titled “labels(where?)”Widgets and tools
thingport.labels(where?: ParentNode): voidFills in the script’s words in its markup: data-t sets an element’s text, and data-t-title, data-t-aria and data-t-placeholder fill those attributes. Running it again after adding markup is harmless.
| Parameter | What it is |
|---|---|
where | The element to fill in under: root when left out. |
// <h2 data-t="wall.title">Wall size</h2>thingport.labels();Your library
Section titled “Your library”models
Section titled “models”Widgets and tools
thingport.models: SdkModelsThe user’s models, as the user. A widget usually only reads.
models.list(options?)
Section titled “models.list(options?)”thingport.models.list(options?: SdkModelQuery): Promise<SdkModelPage>A page of the library’s models, newest first.
| Parameter | What it is |
|---|---|
options | What to narrow it to, and which page. |
See SdkModelQuery, SdkModelPage.
const { models, hasMore } = await thingport.models.list({ tags: ["gridfinity"], limit: 20 });models.search(q)
Section titled “models.search(q)”thingport.models.search(q: string): Promise<SdkSearchResult>The best matches for a search, as the search box finds them: models, collections and tags.
| Parameter | What it is |
|---|---|
q | The words to look for. |
See SdkSearchResult.
const { models, tags } = await thingport.models.search("benchy");models.get(id)
Section titled “models.get(id)”thingport.models.get(id: string): Promise<SdkModel>One model.
| Parameter | What it is |
|---|---|
id | The model’s id. |
See SdkModel.
const model = await thingport.models.get(id);models.file(id, fileId?)
Section titled “models.file(id, fileId?)”thingport.models.file(id: string, fileId?: string): Promise<ArrayBuffer>One of a model’s 3D files.
| Parameter | What it is |
|---|---|
id | The model’s id. |
fileId | One of its files; the first when left out. |
Returns: The file’s bytes. Throws when the model has no such file, or when the file is missing from storage.
const stl = await thingport.models.file(model.id);models.relatedFiles(id)
Section titled “models.relatedFiles(id)”thingport.models.relatedFiles(id: string): Promise<SdkRelatedFile[]>The files kept beside a model that aren’t plates: the script it was generated from, a readme, a diagram.
| Parameter | What it is |
|---|---|
id | The model’s id. |
See SdkRelatedFile.
const scad = (await thingport.models.relatedFiles(id)).find((file) => file.name.endsWith(".scad"));models.relatedText(id, fileId)
Section titled “models.relatedText(id, fileId)”thingport.models.relatedText(id: string, fileId: string): Promise<string>One of those files, as text.
| Parameter | What it is |
|---|---|
id | The model’s id. |
fileId | One of its relatedFiles. |
const source = await thingport.models.relatedText(id, scad.id);models.create(input)
Section titled “models.create(input)”thingport.models.create(input: SdkNewModel): Promise<SdkModel>Makes a model of the files given, each one a plate, in a collection when one is given.
| Parameter | What it is |
|---|---|
input | Its name, description, tags, collection and files. |
Returns: The new model.
See SdkNewModel, SdkModel.
const model = await thingport.models.create({ name: "Cube 20 mm", tags: ["generated"], files: [{ name: "cube-20.stl", data: stl }],});models.addFiles(id, files)
Section titled “models.addFiles(id, files)”thingport.models.addFiles(id: string, files: SdkFileInput[]): Promise<SdkModel>Adds files to a model, each a plate.
| Parameter | What it is |
|---|---|
id | The model’s id. |
files | The files to add. |
Returns: The model as it is now.
See SdkFileInput, SdkModel.
models.addImages(id, images)
Section titled “models.addImages(id, images)”thingport.models.addImages(id: string, images: SdkFileInput[]): Promise<SdkModel>Adds pictures (PNG, JPEG, WebP) to a model’s gallery. The first becomes its cover in place of the render.
| Parameter | What it is |
|---|---|
id | The model’s id. |
images | The pictures. |
Returns: The model as it is now.
See SdkFileInput, SdkModel.
const png = await new Promise((done) => canvas.toBlob(done));await thingport.models.addImages(model.id, [{ name: "cover.png", data: png }]);models.replaceFile(id, fileId, file)
Section titled “models.replaceFile(id, fileId, file)”thingport.models.replaceFile(id: string, fileId: string, file: SdkFileInput): Promise<SdkModel>Replaces one of a model’s files with a new one, in the same place in its order.
| Parameter | What it is |
|---|---|
id | The model’s id. |
fileId | The file to replace, one of its files. |
file | The new file. |
Returns: The model as it is now.
See SdkFileInput, SdkModel.
models.update(id, patch)
Section titled “models.update(id, patch)”thingport.models.update(id: string, patch: { name?: string; description?: string; tags?: string[] }): Promise<SdkModel>Changes a model’s name, description or tags. Only what’s given changes; tags replaces the list.
| Parameter | What it is |
|---|---|
id | The model’s id. |
patch | What to change. |
Returns: The model as it is now.
See SdkModel.
await thingport.models.update(model.id, { tags: [...model.tags, "printed"] });models.open(id)
Section titled “models.open(id)”thingport.models.open(id: string): voidLeaves for the model’s page. A tool’s window closes first.
| Parameter | What it is |
|---|---|
id | The model’s id. |
collections
Section titled “collections”In a widget:
thingport.collections: SdkCollectionsThe user’s collections.
In a tool:
thingport.collections: ToolCollectionsThe user’s collections, and a dialog asking them for one.
collections.list()
Section titled “collections.list()”thingport.collections.list(): Promise<SdkCollection[]>The user’s collections, without the built-in Favourites and Browsing History.
See SdkCollection.
const collections = await thingport.collections.list();collections.get(id)
Section titled “collections.get(id)”thingport.collections.get(id: string): Promise<SdkCollection>One collection.
| Parameter | What it is |
|---|---|
id | The collection’s id. |
See SdkCollection.
collections.create(input)
Section titled “collections.create(input)”thingport.collections.create(input: SdkNewCollection): Promise<SdkCollection>Makes a collection.
| Parameter | What it is |
|---|---|
input | Its name, description and tags. |
Returns: The new collection.
See SdkNewCollection, SdkCollection.
const shelf = await thingport.collections.create({ name: "Labels" });collections.models(id, options?)
Section titled “collections.models(id, options?)”thingport.collections.models(id: string, options?: SdkPage): Promise<SdkModelPage>A page of the models in a collection, newest first.
| Parameter | What it is |
|---|---|
id | The collection’s id. |
options | Which page. |
See SdkPage, SdkModelPage.
const { models } = await thingport.collections.models(id, { limit: 10 });collections.add(id, modelIds)
Section titled “collections.add(id, modelIds)”thingport.collections.add(id: string, modelIds: string[]): Promise<void>Puts models from the library into a collection.
| Parameter | What it is |
|---|---|
id | The collection’s id. |
modelIds | The models to put in. |
collections.remove(id, modelIds)
Section titled “collections.remove(id, modelIds)”thingport.collections.remove(id: string, modelIds: string[]): Promise<void>Takes models out of a collection. They stay in the library.
| Parameter | What it is |
|---|---|
id | The collection’s id. |
modelIds | The models to take out. |
collections.pick(options?)
Section titled “collections.pick(options?)”Tools only
thingport.collections.pick(options?: { title?: string }): Promise<SdkCollection | null>Asks the user which collection, or for a new one, as a Save dialog would. A dashboard has no such dialog, so a widget saves into a collection its settings name instead.
| Parameter | What it is |
|---|---|
options | title: what the dialog asks. |
Returns: The collection, or null when the user cancels.
See SdkCollection.
const collection = await thingport.collections.pick({ title: t("save.where") });if (!collection) return;Network
Section titled “Network”fetch(url, init?)
Section titled “fetch(url, init?)”Widgets and tools
thingport.fetch(url: string, init?: RequestInit): Promise<Response>A request to one of the hosts the metadata’s hosts lists, made by the Thingport server, so CORS and the local network aren’t in the way. Answers as fetch does, with the body as text (a binary answer doesn’t survive) and Content-Type its only header. Any other host throws, as does a cloud metadata address. Redirects aren’t followed, the Cookie header isn’t sent, a string is the only body it carries, and it gives up after 15 seconds and cuts an answer off at 5 MB. The editor’s preview of a widget or a tool that hasn’t been saved yet can’t reach any host.
| Parameter | What it is |
|---|---|
url | An http or https address on a declared host. |
init | The method (GET, POST, PUT, PATCH or DELETE), headers and a string body. |
const res = await thingport.fetch("http://octopi.local/api/job", { headers: { "X-Api-Key": key } });const job = await res.json();api(path, init?)
Section titled “api(path, init?)”Widgets and tools
thingport.api(path: string, init?: RequestInit): Promise<Response>Thingport’s own REST API, as the user, signed in as the page is.
| Parameter | What it is |
|---|---|
path | A path under /api, such as /dashboard/summary. |
init | As fetch takes it. |
const summary = await (await thingport.api("/dashboard/summary")).json();Interface
Section titled “Interface”download(file)
Section titled “download(file)”Widgets and tools
thingport.download(file: SdkFileInput): voidHands the user a file to keep, as a browser download.
| Parameter | What it is |
|---|---|
file | Its name and content. |
See SdkFileInput.
thingport.download({ name: "label.stl", data: stl });In a widget:
thingport.ui: SdkUiThingport’s own toast and confirmation.
In a tool:
thingport.ui: ToolUiThingport’s own toast and confirmation, the collection picker, and closing the window.
ui.toast(message, severity?, options?)
Section titled “ui.toast(message, severity?, options?)”thingport.ui.toast(message: string, severity?: SdkSeverity, options?: SdkToastOptions): voidShows a short message in Thingport’s own toast.
| Parameter | What it is |
|---|---|
message | What to say. |
severity | How it looks: "info" when left out. |
options | openModel: a model’s id, for an Open button on the toast that leaves for its page. |
See SdkSeverity, SdkToastOptions.
const model = await thingport.models.create({ name, files });thingport.ui.toast(t("save.done", { name: model.name }), "success", { openModel: model.id });ui.confirm(options)
Section titled “ui.confirm(options)”thingport.ui.confirm(options: SdkConfirmOptions): Promise<boolean>Asks the user to confirm, in Thingport’s own dialog.
| Parameter | What it is |
|---|---|
options | What to ask, and how. |
Returns: Whether they confirmed.
See SdkConfirmOptions.
if (!(await thingport.ui.confirm({ message: t("clear.ask"), destructive: true }))) return;ui.openModel(id)
Section titled “ui.openModel(id)”thingport.ui.openModel(id: string): voidLeaves for a model’s page, as models.open does. A tool’s window closes first.
| Parameter | What it is |
|---|---|
id | The model’s id. |
ui.pickCollection(options?)
Section titled “ui.pickCollection(options?)”Tools only
thingport.ui.pickCollection(options?: { title?: string }): Promise<SdkCollection | null>The same dialog as collections.pick.
| Parameter | What it is |
|---|---|
options | title: what the dialog asks. |
Returns: The collection, or null when the user cancels.
See SdkCollection.
ui.close()
Section titled “ui.close()”Tools only
thingport.ui.close(): voidCloses the tool’s window, as close() does.
achievements
Section titled “achievements”Widgets and tools
thingport.achievements: SdkAchievementsThe user’s achievements: badges for what they do in Thingport, while an admin has them on.
achievements.unlock(key)
Section titled “achievements.unlock(key)”thingport.achievements.unlock(key: string): Promise<boolean>Gives the user a secret badge this widget or tool hides: an easter egg Thingport knows by the script’s slug and key. Thingport shows them the badge the first time; asked again, nothing happens. Resolves false when there’s no such secret for this script, when an admin has achievements off, and in an unsaved draft. Never throws, so an easter egg can’t break the script around it; and as Thingport versions before achievements have no thingport.achievements, call it as thingport.achievements?.unlock(key).
| Parameter | What it is |
|---|---|
key | The secret’s name, as Thingport’s catalogue has it for this script. |
Returns: Whether the user has it now.
root.addEventListener("dblclick", () => thingport.achievements?.unlock("guest"));close()
Section titled “close()”Tools only
thingport.close(): voidCloses the tool’s window.
Libraries
Section titled “Libraries”library(name)
Section titled “library(name)”Widgets and tools
thingport.library<K extends SdkLibraryName>(name: K): Promise<SdkLibraries[K]>A library Thingport carries, for a job a script can’t fit inside itself. Fetched the first time anything asks and shared with every widget and tool after that, so ask only when the script needs it: a panel drawn in HTML shouldn’t wait on a WebAssembly download.
| Parameter | What it is |
|---|---|
name | Which library. |
See SdkLibraryName.
const [{ Manifold }, fonts] = await Promise.all([thingport.library("manifold"), thingport.library("fonts")]);library("three")
Section titled “library("three")”Three.js, the copy Thingport draws models with, plus mergeGeometries and mergeVertices from its BufferGeometryUtils.
const THREE = await thingport.library("three");const box = new THREE.BoxGeometry(20, 20, 20);library("opentype")
Section titled “library("opentype")”opentype.js: reads a TTF or OTF and gives a glyph’s real outline, counters and all.
const opentype = await thingport.library("opentype");const font = opentype.parse(await file.arrayBuffer());library("manifold")
Section titled “library("manifold")”Manifold, started and ready: solid modelling whose results stay watertight, with the 2D cross-sections and offsetting that go with it.
const { Manifold } = await thingport.library("manifold");const ring = Manifold.cylinder(4, 20, 20, 64).subtract(Manifold.cylinder(4, 16, 16, 64));const mesh = ring.getMesh();library("fonts")
Section titled “library("fonts")”The typefaces Thingport carries, under the Open Font License. They are all static faces: a variable font’s outlines are only right once its deltas are applied, which opentype.js doesn’t do.
fonts.list
Section titled “fonts.list”fonts.list: readonly SdkFont[]Every typeface, in the order a picker should show them.
See SdkFont.
const fonts = await thingport.library("fonts");select.append(...fonts.list.map((font) => new Option(font.name, font.id)));fonts.bytes(id)
Section titled “fonts.bytes(id)”fonts.bytes(id: string): Promise<ArrayBuffer>The font file itself.
| Parameter | What it is |
|---|---|
id | One of list’s ids. |
Returns: The TTF’s bytes.
const ttf = await fonts.bytes("pt-sans");fonts.load(id)
Section titled “fonts.load(id)”fonts.load(id: string): Promise<ExternalLibrary>The font parsed by opentype.js, the same Font every widget and tool asking for it gets.
| Parameter | What it is |
|---|---|
id | One of list’s ids. |
Returns: An opentype.js Font.
See ExternalLibrary.
const font = await fonts.load("bebas-neue");const path = font.getPath("HELLO", 0, 0, 72);library("openscad")
Section titled “library("openscad")”OpenSCAD itself, built for the browser, for the models that came with the script they were generated from. A render runs in a worker, so the page keeps drawing, and nothing leaves the browser: the script, the parameters and the result stay in the tab until something saves them. A script may include the libraries in libraries.
openscad.parameters(source)
Section titled “openscad.parameters(source)”openscad.parameters(source: string): Promise<ScadParameters>What parameters a script offers, read by OpenSCAD itself, so it’s the list the script’s author saw. That includes the ones a script declares below its first {, which OpenSCAD alone wouldn’t read but a site’s customizer may.
| Parameter | What it is |
|---|---|
source | The script’s text. |
See ScadParameters.
const openscad = await thingport.library("openscad");const { parameters } = await openscad.parameters(source);openscad.render(source, options?)
Section titled “openscad.render(source, options?)”openscad.render(source: string, options?: ScadRenderOptions): Promise<ScadRender>The model a script makes of a given set of parameters.
| Parameter | What it is |
|---|---|
source | The script’s text. |
options | The parameters, the format and a signal to cancel it. |
Returns: The file, the engine’s log and the time it took. A 3MF unless format says otherwise.
See ScadRenderOptions, ScadRender.
const { bytes, log } = await openscad.render(source, { parameters: { width: 60 }, name: "Box" });thingport.download({ name: "box.3mf", data: bytes });openscad.includedFiles(source, read)
Section titled “openscad.includedFiles(source, read)”openscad.includedFiles(source: string, read: (fileName: string) => Promise<string | null>): Promise<Record<string, string>>The .scad files a script includes or uses, and what those include in turn, ready for render()’s files. A script that came with a model often needs the others kept beside it.
| Parameter | What it is |
|---|---|
source | The script’s text. |
read | Reads a file by its name, without any folder; resolves to null when there’s no such file. |
Returns: Each file’s text, by the path the script asks for it by. What read couldn’t find is left out, and the render’s log says so.
const files = await openscad.includedFiles(source, async (name) => { const file = related.find((candidate) => candidate.name === name); return file ? thingport.models.relatedText(id, file.id) : null;});const { bytes } = await openscad.render(source, { files });openscad.libraries
Section titled “openscad.libraries”openscad.libraries: string[]The OpenSCAD libraries a script may include, by folder name.
openscad.concurrency
Section titled “openscad.concurrency”openscad.concurrency: numberHow many renders to have in flight at once: one fewer than the machine has cores, from one to four.
openscad.writeThreeMf(input, options?)
Section titled “openscad.writeThreeMf(input, options?)”openscad.writeThreeMf(input: SdkMesh | ThreeMfPart[], options?: { name?: string }): Uint8ArrayOne mesh, or several named parts, as the bytes of one 3MF file.
| Parameter | What it is |
|---|---|
input | A mesh, or a list of parts to place side by side (see layoutRow). |
options | The model’s name, which slicers show. |
See SdkMesh, ThreeMfPart.
const file = openscad.writeThreeMf( openscad.layoutRow([ { mesh: a, name: "Lid" }, { mesh: b, name: "Box" }, ]),);openscad.layoutRow(parts, options?)
Section titled “openscad.layoutRow(parts, options?)”openscad.layoutRow(parts: ThreeMfPart[], options?: { gap?: number }): ThreeMfPart[]Lays parts out in a row, in the order given, each standing on z = 0, so a 3MF of them doesn’t have them inside one another.
| Parameter | What it is |
|---|---|
parts | The parts to place. |
options | gap: millimetres between them, 5 when left out. |
Returns: The same parts, each with an at.
See ThreeMfPart.
openscad.meshBounds(mesh)
Section titled “openscad.meshBounds(mesh)”openscad.meshBounds(mesh: SdkMesh): { min: [number, number, number]; max: [number, number, number] }A mesh’s bounding box, in millimetres.
See SdkMesh.
const { min, max } = openscad.meshBounds(mesh);const width = max[0] - min[0];libraries
Section titled “libraries”Widgets and tools
thingport.libraries: SdkLibraryName[]The names library() takes.
See SdkLibraryName.
Tool only
Section titled “Tool only”Tools only
thingport.tool: { id: string | null; slug: string; name: string; version: string; source: "repo" | "own" }The tool itself. id is null in the editor’s preview of a tool not saved yet; source is "repo" for one installed from the repository and "own" for the user’s own.
context
Section titled “context”Tools only
thingport.context: { modelId?: string }What the tool was opened on: { modelId } when it’s opened on a model, and empty when it’s opened from the Tools page.
storage
Section titled “storage”Tools only
thingport.storage: SdkStorageJSON kept for this user and this tool, so the window opens where they left it. In the editor’s preview of a tool not saved yet, it lasts only as long as the preview.
storage.get(key)
Section titled “storage.get(key)”thingport.storage.get(key: string): Promise<any>What’s kept under a key.
| Parameter | What it is |
|---|---|
key | 1 to 200 letters, digits, ., -, : and _. |
Returns: The value as it was kept, or undefined when nothing is.
const last = (await thingport.storage.get("last")) ?? { width: 40 };storage.set(key, value)
Section titled “storage.set(key, value)”thingport.storage.set(key: string, value: unknown): Promise<void>Keeps a value under a key, replacing what was there. At most 1 MB a value as JSON, 20 MB and 2,000 keys a tool.
| Parameter | What it is |
|---|---|
key | 1 to 200 letters, digits, ., -, : and _. |
value | Anything JSON can hold. |
await thingport.storage.set("last", { width: 60 });storage.remove(key)
Section titled “storage.remove(key)”thingport.storage.remove(key: string): Promise<void>Forgets a key.
| Parameter | What it is |
|---|---|
key | The key. |
storage.keys()
Section titled “storage.keys()”thingport.storage.keys(): Promise<string[]>Every key kept.
const drafts = (await thingport.storage.keys()).filter((key) => key.startsWith("draft:"));toolModels()
Section titled “toolModels()”Tools only
thingport.toolModels(): Promise<SdkToolModel[]>The models a tool from the repository brings, by the keys its metadata gives them. An admin may install a tool without them, which is usual where they’re large, so printId is null for one that isn’t here yet. A user’s own tool brings none.
See SdkToolModel.
const joint = (await thingport.toolModels()).find((model) => model.key === "joint");fetchToolModels(keys)
Section titled “fetchToolModels(keys)”Tools only
thingport.fetchToolModels(keys: string[]): Promise<SdkToolModelsFetched>Fetches the tool’s models that aren’t here yet and gives the user their copies. Ask for the few a piece of work needs, and only once the user has agreed to wait for them.
| Parameter | What it is |
|---|---|
keys | The models’ keys. |
Returns: What came, and why the rest didn’t, in the provider’s own words.
See SdkToolModelsFetched.
const { failed } = await thingport.fetchToolModels(["tile-8x8"]);if (failed.length) thingport.ui.toast(failed[0].reason, "warning");SdkTheme
Section titled “SdkTheme”Thingport’s colours and font, as the theme the user has on shows them.
| Field | Type | CSS variable | What it is |
|---|---|---|---|
mode | "light" | "dark" | Which theme is on. | |
primary | string | --tp-accent | The accent colour the user picked. |
primaryContrast | string | --tp-accent-ink | What reads on primary: white for most accents, dark for light ones such as amber. Text and icons on an accent-filled button take this, never paper, which is dark in the dark theme. |
background | string | --tp-background | The page behind the panels and windows. |
paper | string | --tp-paper | The surface of a panel, a window or a card. |
text | string | --tp-text | Body text. |
textSecondary | string | --tp-text-muted | Quieter text: hints, captions, counts. |
divider | string | --tp-divider | Lines and borders. |
error | string | --tp-error | Something failed. |
warning | string | --tp-warning | Something needs a look. |
success | string | --tp-success | Something worked. |
fontFamily | string | --tp-font | The font stack Thingport’s own text is set in. |
SdkSize
Section titled “SdkSize”A size in pixels.
| Field | Type | What it is |
|---|---|---|
width | number | |
height | number |
WidgetSize
Section titled “WidgetSize”A dashboard panel’s size: pixels, and the grid cells it covers.
| Field | Type | What it is |
|---|---|---|
width | number | |
height | number | |
cols | number | Columns of the dashboard’s grid, which is 12 wide on a wide screen. |
rows | number | Rows of the grid, each 64 px tall with 16 px between them. |
SdkLanguage
Section titled “SdkLanguage”A language Thingport has.
| Field | Type | What it is |
|---|---|---|
code | string | Its code, as language gives it: "en", "lt". |
label | string | Named in itself (“Lietuvių”), so it reads from any language. |
englishName | string | Named in English. |
SdkModel
Section titled “SdkModel”A model in the user’s library.
| Field | Type | What it is |
|---|---|---|
id | string | |
name | string | |
description | string | null | |
tags | string[] | |
thumbnail | string | null | A picture of it, an address an <img> can show. |
files | SdkModelFile[] | Its 3D files (plates), in order. |
relatedCount | number | How many files are kept beside it that aren’t plates, so a list can be narrowed without asking for each. |
toolOwned | boolean | Brought by a tool from the repository: it can be read, not changed. |
createdAt | string | null | When it was added, as an ISO 8601 date. |
SdkModelFile
Section titled “SdkModelFile”One of a model’s 3D files.
| Field | Type | What it is |
|---|---|---|
id | string | |
name | string | Its file name, with the extension. |
size | number | In bytes. |
url | string | An address it can be read from as the user, e.g. by fetch. |
SdkRelatedFile
Section titled “SdkRelatedFile”A file kept beside a model rather than being one of its plates: a generator script, a readme, a diagram.
| Field | Type | What it is |
|---|---|---|
id | string | |
name | string | |
type | string | Its MIME type. |
size | number | In bytes. |
url | string |
SdkModelPage
Section titled “SdkModelPage”A page of models.
| Field | Type | What it is |
|---|---|---|
models | SdkModel[] | |
hasMore | boolean | More models match than this page holds: ask again with a larger offset. |
total | number | null | How many match in all, where the server counted them. |
SdkSearchResult
Section titled “SdkSearchResult”What models.search finds, as the search box shows it.
| Field | Type | What it is |
|---|---|---|
models | SdkModel[] | |
collections | { id: string; name: string; modelCount: number }[] | |
tags | { tag: string; count: number }[] |
SdkCollection
Section titled “SdkCollection”One of the user’s collections.
| Field | Type | What it is |
|---|---|---|
id | string | |
name | string | |
description | string | null | |
tags | string[] | |
modelCount | number | |
toolOwned | boolean | A tool’s own collection, which can’t be saved into. |
SdkFileInput
Section titled “SdkFileInput”A file to save or hand over: its name, with the extension, and its content.
| Field | Type | What it is |
|---|---|---|
name | string | E.g. "bin-2x3.stl". |
data | Blob | ArrayBuffer | ArrayBufferView | string | The content. A string is saved as UTF-8 text. |
type? | string | Its MIME type. Left out, a Blob’s own type is used, else application/octet-stream. |
SdkModelQuery
Section titled “SdkModelQuery”Which models a list holds, and which page of them.
| Field | Type | What it is |
|---|---|---|
q? | string | Words to search for, as the models page searches. |
tags? | string[] | Only models with every one of these tags. |
collectionId? | string | Only the models in this collection. |
limit? | number | How many to return: 1 to 200, 50 when left out. |
offset? | number | How many to skip, for the next page. |
SdkPage
Section titled “SdkPage”A page of a collection’s models.
| Field | Type | What it is |
|---|---|---|
limit? | number | How many to return: 1 to 200, 50 when left out. |
offset? | number | How many to skip, for the next page. |
SdkNewModel
Section titled “SdkNewModel”A model to make.
| Field | Type | What it is |
|---|---|---|
name | string | |
description? | string | |
tags? | string[] | |
collectionId? | string | A collection to save it into. |
files | SdkFileInput[] | Its files, each a plate. At least one. |
SdkNewCollection
Section titled “SdkNewCollection”A collection to make.
| Field | Type | What it is |
|---|---|---|
name | string | |
description? | string | |
tags? | string[] |
SdkConfirmOptions
Section titled “SdkConfirmOptions”What a confirmation asks.
| Field | Type | What it is |
|---|---|---|
title? | string | |
message | string | |
confirmLabel? | string | The confirming button’s label: “Confirm” when left out, or “Delete” for a destructive one. |
destructive? | boolean | Shows the confirming button in the error colour, for something that can’t be undone. |
SdkSeverity
Section titled “SdkSeverity”How a toast looks.
type SdkSeverity = "success" | "info" | "warning" | "error";SdkToastOptions
Section titled “SdkToastOptions”What a toast can carry besides its message.
| Field | Type | What it is |
|---|---|---|
openModel? | string | A model’s id: the toast gets an Open button that leaves for the model’s page, as ui.openModel does, and stays up longer so it can be reached. Pass it whenever the toast says a model was saved or changed. An older Thingport instance shows the message without the button. |
SdkToolModel
Section titled “SdkToolModel”A model a tool from the repository brings, as toolModels() lists it.
| Field | Type | What it is |
|---|---|---|
key | string | What the tool’s metadata calls it. |
name | string | |
source | string | null | The page it’s imported from, for one that isn’t a file in the tool’s folder. |
printId | string | null | The user’s copy, to read with models; null while it isn’t here. |
SdkToolModelsFetched
Section titled “SdkToolModelsFetched”What fetchToolModels brought, and what it couldn’t.
| Field | Type | What it is |
|---|---|---|
ready | string[] | The keys that are here now. |
failed | { key: string; reason: string }[] | The rest, each with the provider’s own reason, a daily download limit included. |
ExternalLibrary
Section titled “ExternalLibrary”A library with types of its own, which this file doesn’t repeat: see its own documentation.
type ExternalLibrary = any;SdkLibraryName
Section titled “SdkLibraryName”A library’s name, as library() takes it.
type SdkLibraryName = keyof SdkLibraries;SdkFont
Section titled “SdkFont”A typeface library("fonts") offers.
| Field | Type | What it is |
|---|---|---|
id | string | What bytes and load take. |
name | string | Its name, to show. |
group | string | The kind of face it is, for a picker to group by: “Sans”, “Serif”, “Script”… |
ScadParameter
Section titled “ScadParameter”A parameter an OpenSCAD script offers, as OpenSCAD’s own customizer describes it.
| Field | Type | What it is |
|---|---|---|
name | string | |
group | string | The /* [Group] */ heading it was declared under; “Parameters” for the ones before any heading. |
type | "number" | "string" | "boolean" | "vector" | string | |
initial | unknown | The value the script gives it. |
caption? | string | The comment above the declaration, which explains it. |
min? | number | |
max? | number | |
step? | number | |
options? | { name: string; value: unknown }[] | Where the declaration ends in // [a, b, c]: a choice rather than free entry. |
widget? | "color" | "font" | "file" | A control OpenSCAD has no word for, in the spelling of MakerWorld, whose scripts use them. "color" holds a "#rrggbb" (declared with // color). "font" holds a typeface’s name (// font), of which only the ones in library("fonts") are there to draw with; any other comes out in the plainest. "file" holds the name of a file the script reads (declared with a default called default.png, .svg or .stl), passed to render() in files; until there is one the script gets a plain stand-in. |
accept? | string | For a "file" widget, the file’s extension: ".png", ".svg" or ".stl". |
ScadParameters
Section titled “ScadParameters”What an OpenSCAD script offers.
| Field | Type | What it is |
|---|---|---|
title | string | |
parameters | ScadParameter[] |
ScadFormat
Section titled “ScadFormat”The formats a render can come back as. "mesh" is the geometry alone, with no file built from it.
type ScadFormat = "3mf" | "mesh" | "stl" | "obj" | "off" | "amf";ScadRenderOptions
Section titled “ScadRenderOptions”How to render a script.
| Field | Type | What it is |
|---|---|---|
parameters? | Record<string, unknown> | By parameter name, as parameters() gives them. Anything left out keeps the script’s own value. |
files? | Record<string, Uint8Array | string> | The files the script reads, by the name a "file" parameter was set to, or as includedFiles() gives them. |
format? | ScadFormat | "3mf" when left out. |
name? | string | The title written into a 3MF, which slicers show. Ignored by the other formats. |
signal? | AbortSignal | Cancels the render: the worker running it is let go there and then. |
ScadRender
Section titled “ScadRender”What a render produced: the file, and everything the engine said while making it.
| Field | Type | What it is |
|---|---|---|
bytes | Uint8Array | |
log | string[] | Warnings and errors, in the order they were printed. A typeface Thingport doesn’t carry isn’t among them: it comes out in the plainest without a word. |
seconds | number | Seconds the engine spent. |
mesh? | SdkMesh | The geometry behind the bytes, for the formats Thingport builds itself (3MF and mesh). |
SdkMesh
Section titled “SdkMesh”A triangle mesh, in millimetres.
| Field | Type | What it is |
|---|---|---|
vertices | Float64Array | Flat x, y, z triples. |
triangles | Uint32Array | Flat vertex-index triples. |
palette? | string[] | The distinct colours the script gave the model, as "#rrggbb"; absent where it never coloured it. |
colors? | Uint16Array | One entry per triangle, indexing palette. Present whenever palette is. |
uncolored? | number | The palette entry standing in for the faces the script never coloured, where it coloured some. |
ThreeMfPart
Section titled “ThreeMfPart”One of the things a 3MF holds.
| Field | Type | What it is |
|---|---|---|
mesh | SdkMesh | |
name? | string | What a slicer’s object list calls it. A count belongs here, “8x8 Core Tile x4”, since a 3MF holds one copy of a shape however many are wanted. |
at? | { x: number; y: number; z?: number } | Millimetres from the origin. Left out, the part stays where its mesh is, so several land on top of each other: see layoutRow. |
Feedback
Section titled “Feedback”Something unclear, wrong or missing on this page? Say so here, or react. It’s kept in GitHub Discussions. Something broken? Report it as a bug.