Gallery › robotparts › robotparts actuators
robotparts actuators
Every actuator in robotparts.dev's catalog (1,149 rows, release 2026.10.25) in one .base file: seven tables, a cards
gallery of the 150 photographed parts and two pivots over the same rows, with the McMaster rail on the left. Tick a
brand and every view reads the same rows.
The .base file and its data
Every tab above is one entry of this file; the views read these rows. ⋯ in the toolbar copies the current view as YAML.
# Actuators: robotparts' 1,149 actuators, one .base file, many views. The five table views are the table lane's
# presets (robotparts lane/tables @ ab5ba92, presets/actuators.base); the pivots are data-ui's, and so are the three
# views that show how a record opens (`open:`, docs/CONTRACT.md amendment 2026-10-26 (open modes)). Obsidian Bases
# grammar plus data-ui's keys (docs/CONTRACT.md §5). Check it: node bin/data-ui.mjs check <this file>
data: actuators.json
# how a record opens in every view that does not say: the side peek, docked as a split view from 1100 px of width
open: { mode: side, splitAt: 1100 }
facets:
- brand
- form
- drivetrain
- buses
- level
- { property: peak_torque, as: range }
- { property: mass, as: range }
- { property: price, as: range }
- { property: torque_density, as: has }
properties:
model: { displayName: Model }
brand: { displayName: Brand }
form: { displayName: Form }
drivetrain: { displayName: Drivetrain }
peak_torque: { displayName: Peak torque }
rated_torque: { displayName: Rated torque }
max_speed: { displayName: Max speed }
mass: { displayName: Mass }
gear_ratio: { displayName: Ratio }
voltage: { displayName: Voltage }
od: { displayName: OD }
length: { displayName: Length }
buses: { displayName: Bus }
torque_density: { displayName: Peak N·m/kg }
price: { displayName: Price from }
sellers: { displayName: Sellers }
level: { displayName: Level }
views:
- type: table
name: By brand
order: [model, form, peak_torque, rated_torque, max_speed, mass, gear_ratio, voltage, od, length, buses, price]
groupBy: { property: brand, direction: ASC }
sort:
- { property: peak_torque, direction: DESC }
summaries: { peak_torque: Max, mass: Min, price: Min }
- type: table
name: Brand › form
order: [model, peak_torque, mass, gear_ratio, voltage, price]
groupBy: { property: brand, direction: ASC }
subGroupBy: { property: form, direction: ASC }
sort:
- { property: peak_torque, direction: DESC }
summaries: { peak_torque: Max, price: Min }
fold: closed
- type: table
name: Torque density
filters: '!torque_density.isEmpty()'
order: [model, brand, torque_density, peak_torque, mass, price]
sort:
- { property: torque_density, direction: DESC }
display: { torque_density: bar }
- type: table
name: Geared CAN under $150
filters:
and:
- 'drivetrain == "geared"'
- 'buses.contains("can")'
- 'price < 150'
order: [model, brand, price, peak_torque, mass, gear_ratio, voltage]
sort:
- { property: price, direction: ASC }
display: { price: bar }
- type: table
name: All, flat
order: [model, brand, form, drivetrain, peak_torque, rated_torque, max_speed, mass, gear_ratio, voltage, od, length, buses, torque_density, price, sellers, level]
sort:
- { property: brand, direction: ASC }
- { property: model, direction: ASC }
- type: table
name: Expand in place
open: expand
order: [model, brand, form, peak_torque, mass, gear_ratio, price]
sort:
- { property: peak_torque, direction: DESC }
- type: table
name: Row links
open: { mode: link, url: url }
order: [model, brand, form, peak_torque, mass, price]
sort:
- { property: brand, direction: ASC }
- { property: model, direction: ASC }
- type: cards
name: Gallery
open: expand
filters: '!photo.isEmpty()'
order: [model, brand, peak_torque, mass, price]
image: photo
imageFit: contain
imageAspectRatio: 0.75
cardSize: 180
sort:
- { property: peak_torque, direction: DESC }
- type: pivot
name: Brand × form
order: [brand]
splitBy: [form]
value: { property: null, summary: Count }
sort:
- { property: brand, direction: ASC }
- type: pivot
name: Torque by drivetrain × form
order: [drivetrain]
splitBy: [form]
value: { property: peak_torque, summary: Median, display: dist }
// actuators.json: 1,149 rows, 608 KB; the first 3
{
"id": "actuators",
"title": "Actuators",
"titleProperty": "name",
"linkProperty": "url",
"source": "robotparts dist/site/v2/catalog.json, release 2026.10.25 (lane/tables @ ab5ba92); mass from each spec's own unit; photo: robotparts media/photos.jsonl, 150 of 1725 copied at 240 px",
"properties": {
"name": {
"type": "text",
"hidden": true
},
"model": {
"type": "text",
"width": 190
},
"brand": {
"type": "text",
"width": 120
},
"form": {
"type": "text",
"width": 140,
"display": "badge"
},
"drivetrain": {
"type": "text",
"width": 104
},
"buses": {
"type": "list",
"width": 120
},
"level": {
"type": "number",
"width": 58
},
"url": {
"type": "text",
"hidden": true
},
"torque_density": {
"type": "number",
"unitText": "N·m/kg",
"width": 130,
"derived": "peak torque / mass, by robotparts"
},
"price": {
"type": "number",
"unitText": "USD",
"decimals": 0,
"width": 120
},
"sellers": {
"type": "number",
"width": 70
},
"peak_torque": {
"type": "number",
"unitText": "N·m",
"width": 126
},
"rated_torque": {
"type": "number",
"unitText": "N·m",
"width": 126
},
"max_speed": {
"type": "number",
"unitText": "rpm",
"width": 126
},
"mass": {
"type": "number",
"unitText": "g",
"width": 126
},
"gear_ratio": {
"type": "number",
"unitText": ":1",
"width": 126
},
"voltage": {
"type": "number",
"unitText": "V",
"width": 126
},
"od": {
"type": "number",
"unitText": "mm",
"width": 126
},
"length": {
"type": "number",
"unitText": "mm",
"width": 126
},
"photo": {
"type": "text",
"hidden": true,
"display": "image",
"note": "robotparts' primary photo, resized; only the parts this case copied have one"
},
"step_up": {
"type": "text",
"hidden": true,
"derived": "the next photographed part of the same brand up in peak torque (build_examples.py)",
"note": "an edge for the graph view: among the parts with a photo here, the brand's next one up in peak torque"
}
},
"rows": [
{
"id": "aifitlab-8541438771336",
"name": "Steadywin GIM4305-10",
"brand": "Steadywin",
"model": "GIM4305-10",
"form": "integrated actuator",
"drivetrain": "geared",
"buses": [
"can",
"rs485"
],
"level": 4,
"url": "https://robotparts.dev/actuator/aifitlab-8541438771336/",
"peak_torque": {
"value": 3.82,
"basis": "seller",
"source": "aifitlab.com"
},
"rated_torque": 1.05,
"max_speed": 402,
"mass": {
"value": 150,
"basis": "seller",
"source": "aifitlab.com"
},
"gear_ratio": 10,
"voltage": 24,
"od": 53,
"length": 26,
"torque_density": 25.467,
"price": 70,
"sellers": 1,
"photo": "photos/aifitlab-8541438771336.webp",
"step_up": "aifitlab-8542347853960"
},
{
"id": "aifitlab-8542347853960",
"name": "Steadywin GIM6010-8",
"brand": "Steadywin",
"model": "GIM6010-8",
"form": "integrated actuator",
"drivetrain": "geared",
"buses": [
"can",
"rs485"
],
"level": 1,
"url": "https://robotparts.dev/actuator/aifitlab-8542347853960/",
"peak_torque": {
"value": 11,
"basis": "seller",
"source": "aifitlab.com"
},
"rated_torque": 5,
"max_speed": 420,
"mass": {
"value": 388,
"basis": "seller",
"source": "aifitlab.com"
},
"gear_ratio": 8,
"voltage": 24,
"od": 80,
"length": 40,
"torque_density": 28.351,
"price": 70,
"sellers": 1,
"photo": "photos/aifitlab-8542347853960.webp",
"step_up": "aifitlab-8542620287112"
},
{
"id": "aifitlab-8542620287112",
"name": "Steadywin GIM8108-8",
"brand": "Steadywin",
"model": "GIM8108-8",
"form": "integrated actuator",
"drivetrain": "geared",
"buses": [
"can",
"rs485"
],
"level": 1,
"url": "https://robotparts.dev/actuator/aifitlab-8542620287112/",
"peak_torque": {
"value": 22,
"basis": "seller",
"source": "aifitlab.com"
},
"rated_torque": 7.5,
"max_speed": 320,
"mass": {
"value": 396,
"basis": "seller",
"source": "aifitlab.com"
},
"gear_ratio": 8,
"voltage": 48,
"od": 92,
"length": 55,
"torque_density": 55.556,
"price": 85,
"sellers": 1,
"photo": "photos/aifitlab-8542620287112.webp",
"step_up": null
}
],
"imageProperty": "photo"
}skin.css, README.md
/* robotparts' skin: its own tokens (site/static/site.css, release 2026.10.25), then the one block that maps them onto
data-ui's --data-* (docs/SPEC.md §10). The gallery scopes a skin to .data-ui-skin; on robotparts.dev the same
mapping sits at :root. */
.data-ui-skin {
--bg: #ffffff; --bg2: #f6f7f8; --hover: #f1f5fb; --ink: #15181c; --ink2: #545c66;
--rule: #d9dde2; --rule2: #e9ebee; --accent: #0a5bb5; --on-accent: #ffffff; --warn: #9a3412;
--sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Liberation Sans", sans-serif;
--mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", "DejaVu Sans Mono", monospace;
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) .data-ui-skin {
--bg: #111317; --bg2: #181b20; --hover: #1a2433; --ink: #e6e8eb; --ink2: #a4abb4;
--rule: #30353c; --rule2: #252930; --accent: #6ea8ec; --on-accent: #0b1220; --warn: #f0a070;
}
}
:root[data-theme="dark"] .data-ui-skin {
--bg: #111317; --bg2: #181b20; --hover: #1a2433; --ink: #e6e8eb; --ink2: #a4abb4;
--rule: #30353c; --rule2: #252930; --accent: #6ea8ec; --on-accent: #0b1220; --warn: #f0a070;
}
/* the mapping: this is all a vanilla app writes */
.data-ui-skin {
--data-bg: var(--bg); --data-fg: var(--ink); --data-muted: var(--ink2); --data-subtle: var(--bg2);
--data-border: var(--rule); --data-rule: var(--rule2); --data-hover: var(--hover); --data-accent: var(--accent);
--data-on-accent: var(--on-accent); --data-warn: var(--warn); --data-font: var(--sans); --data-mono: var(--mono);
--data-radius: 6px;
}
# robotparts actuators
Every actuator in robotparts.dev's catalog (1,149 rows, release 2026.10.25) in one `.base` file: seven tables, a cards
gallery of the 150 photographed parts and two pivots over the same rows, with the McMaster rail on the left. Tick a
brand and every view reads the same rows.
- **App:** robotparts
- **Replaces:** robotparts' hand-rolled category table, its Rows view and its left rail (`site.js`), and the table
lane's prototype page.
- **Shows:** grouping two levels deep with fold and summaries, bars in cells, Bases filter expressions, pivots
(counts, and a median with its distribution), rich cells (peak torque and mass carry their basis and source),
the rail's disjunctive counts and readable URL.
- **Data:** `actuators.json`, written by `gallery/tools/build_examples.py` from robotparts' catalog. Mass comes from
each spec's own unit, so the CubeMars AKE40-6 KV90 reads 140 g (the lane's prototype read 140,000 g). `photo` (hidden)
names 150 of robotparts' primary photos in `photos/`; the actuator-charts case reads these same rows.
- **Skin:** `skin.css` maps robotparts' own tokens onto `--data-*`, light and dark.
- **How a record opens** (`open:`, docs/CONTRACT.md amendment 2026-10-26 (open modes)): the file's default is
`open: { mode: side, splitAt: 1100 }`, so a click opens the side peek, docked beside the table when the element is at
least 1100 px wide, over it when narrower, full screen on a phone; ↑/↓ step through the rows and Back closes it.
*Expand in place* and the *Gallery* say `open: expand` (a band under the row; the card grows), *Row links* says
`open: { mode: link, url: url }` (the row is a link to the part's robotparts.dev page). Everywhere the part's name is
a real link, and a double-click or Enter opens its page.
The original UI it replaces
robotparts' hand-rolled category table, its Rows view and its left rail (site.js), and the table lane's prototype page.
What it shows
grouping two levels deep with fold and summaries, bars in cells, Bases filter expressions, pivots (counts, and a median with its distribution), rich cells (peak torque and mass carry their basis and source), the rail's disjunctive counts and readable URL.
Data
actuators.json, written by gallery/tools/build_examples.py from robotparts' catalog. Mass comes from each spec's own unit, so the CubeMars AKE40-6 KV90 reads 140 g (the lane's prototype read 140,000 g). photo (hidden) names 150 of robotparts' primary photos in photos/; the actuator-charts case reads these same rows.
Skin
skin.css maps robotparts' own tokens onto --data-*, light and dark.