@johnmorrisdotca/hako-devices

中文文档
0.6.1发布于 2026/11/01MITTypeScriptES Module零依赖构建来源已验证

Hako Devices 箱: line drawings and 3D views of Raspberry Pis, Macs, PCs, phones, tablets, game consoles, NAS boxes and classic machines, as a web component, with tags to filter 2,200+ machines by CPU, brand and more, and a typed way to assemble machines fr

原始使用文档
文档目录14 节
  1. One minute
  2. What is in it
  3. Build computers from parts
  4. Styles
  5. To scale
  6. A live screen
  7. React
  8. No logos, and a word on trademarks
  9. Filter by what a machine is
  10. The machine list as JSON
  11. Groups and colours
  12. Coming soon
  13. Help fill it in
  14. The rest

Hako Devices 箱

Line drawings and 3D views of computers, that you drop into a page and assemble from parts.
Boards, hats, cases, NAS boxes, desktops, laptops, tablets, game consoles, old phones and more: a .svg and a .glb for each, a web component that shows the drawing first and crossfades to 3D, and a typed model that checks whether a machine really goes together.

CI npm MIT licence TypeScript

Open the demo → · Build from parts · The element · To scale · Styles

A gallery on a night-blue page: groups of line drawings such as single-board computers, desktops, laptops and classic machines, each a bunch of its machines.

The part builder: a small computer in a finned case with a touch screen hat, in 3D, beside its choices and the code to copy.

One minute

npm install @johnmorrisdotca/hako-devices three
<script type="module">
  import "@johnmorrisdotca/hako-devices/element";
</script>

<hako-device key="pi4"></hako-device>
<hako-device build='{"board":"pi4","case":"armor","hat":"pitft-28"}'></hako-device>

That is all a page needs with a bundler. The drawing shows at once; when the element comes on screen and the browser can draw WebGL, the 3D view takes over without a jump. Drag to turn it, or use the arrow keys. With no WebGL, under Save-Data, or on any failure, the drawing stays.

Build one from a script, in Node or a browser:

import { build } from "@johnmorrisdotca/hako-devices/build";

const machine = build({ board: "pi4", case: "armor", hat: "pitft-28" });
machine.report.ok; // true
machine.glb().bytes; // a .glb file's bytes
machine.svg("thin"); // the drawing

Ask whether it fits without building, with no three.js at all:

import { check } from "@johnmorrisdotca/hako-devices";

const report = check({ board: "pi4", case: "argon", hat: "pitft-28" });
report.ok; // false
report.issues[0].message; // "Faceted metal case (Argon ONE style) closes over the header, so a hat cannot reach it."

What is in it

EntryWhatNeeds
@johnmorrisdotca/hako-devicesThe catalogue (DEVICES, catalogue(), statusOf), the parts (PARTS), the fit check (check), the camera rule (frameFor), mapping helpers (piKey, macKey, nasKey, pcKey, deviceKeyOf), styles, scale helpers, screen picturesNothing
.../tagsFACETS, tagsOf(key), matchesPicks(key, picks), facetCounts(keys, picks): filter machines by what they are. Its own entry because the table is largeNothing
.../buildbuild(description), buildDevice(key), buildPart(id): one mesh and one drawing. toGlb, Drawing, Boxthree
.../element<hako-device> and <hako-lineup>: load three only when a 3D view is wantedthree for 3D
.../reactA thin <HakoDevice> wrapperreact
.../machines.jsonThe machine list as static JSON: key, name, maker, family, status, tags and, for drawn devices, size and portsNothing
.../assets/*Ready files: pi4.glb, pi4.svg, pi4.thick.svg, parts/armor.glb, coming-soon.svgNothing

Build computers from parts

A description names a base and what goes on it. Parts attach by mount: a hat on a 40-pin header, a case around a board's sockets, a screen module on a hat's display header, a board on a display's back, a drive in a bay, a stand under a tablet. Each is checked by real millimetres and mount type, and one description makes the mesh and the drawing, so they never disagree.

import { build } from "@johnmorrisdotca/hako-devices/build";

build({ board: "pi3b", hat: "oled-bonnet" });
build({ board: "pi-zero-2w", case: "unipi" });
build({ board: "pi-zero-2w", solderHeader: true, hat: "oled-bonnet" });
build({ board: "pi5", cooler: "active-cooler", hat: "poe-plus" });
build({ base: "nas-4bay", drives: ["hdd-35", "hdd-35", null, null] });
build({ base: "ipad", stand: null });

docs/parts.md has every part and every rule.

Styles

A drawing style is one small table of settings: line weight, colours, fills. thin is the default and thick the other, and every device and part is made in each, so another style is one entry. See docs/styles.md.

<hako-device key="pi4" drawing-style="thick"></hako-device>

style="thick" works too, but style is HTML's global attribute and a strict content security policy reports it, so drawing-style is the one to use.

To scale

By default each drawing fills its own picture, so a small board looks as big as a tower. With scale="real" it has its true size, and <hako-lineup> stands machines side by side on one baseline. Lines keep the width their style sets at any size. See docs/scale.md.

<hako-device key="pi-zero" scale="real" unit="2px/mm"></hako-device>
<hako-lineup keys="pi-zero,pi5,nas-2bay" unit="1px/mm" ruler labels></hako-lineup>

A live screen

Paint a device's screen with your own words or your own canvas. See docs/element.md.

const device = document.querySelector("hako-device");
device.paintScreen({ title: "Kitchen", lines: ["3 screens are on"], status: "good" });
device.paintScreen((ctx, width, height) => ctx.fillRect(0, 0, width, height));

React

React keeps key for itself, so the wrapper's prop is device:

import { HakoDevice } from "@johnmorrisdotca/hako-devices/react";

<HakoDevice device="pi4" drawingStyle="thick" />;
<HakoDevice build={{ board: "pi4", case: "armor", hat: "pitft-28" }} />;

No logos, and a word on trademarks

No mesh or drawing carries a logo, a mark or brand printing. There is a neutral print option, so you can paint your own words on a device at your own risk:

<hako-device key="mac-studio" print="Studio One"></hako-device>

Product names appear only as plain descriptive words in the catalogue and the docs. All trademarks belong to their owners, and this project is not affiliated with, sponsored by or endorsed by any of them. The drawings and meshes are original work drawn from plain geometry and published sizes.

Filter by what a machine is

Every machine on the list has a brand and a type, and most a decade. Where a source gives them, it also has its CPU and CPU maker, cores, memory, operating system, screen, ports, wireless, weight, generation and parts. A fact with no source is left out, never guessed, so a filter by CPU leaves out machines nobody has sourced yet.

import { catalogue } from "@johnmorrisdotca/hako-devices";
import { matchesPicks } from "@johnmorrisdotca/hako-devices/tags";

const intelLaptops = catalogue().filter(({ key }) => matchesPicks(key, { type: ["Laptop"], cpuMaker: ["Intel"] }));

The machine list as JSON

Every machine is also one static file, for a page or a script that wants the list and no code: @johnmorrisdotca/hako-devices/machines.json, and https://johnmorrisdotca.github.io/hako-devices/machines.json on the demo site (it allows other sites to read it). Each machine has its key, name, maker, family, status, mesh, tags and, for a drawn device, size in millimetres and ports. docs/machines.md has every field, and what is left out and why.

When machines are added, the list is regenerated and published with them. Run pnpm wishlist and then pnpm machines, and commit data/machines.json with the machine. pnpm check fails when the file is out of date, so a machine cannot go in without it; the build ships the file in the package and every push to main puts it on the demo site.

Groups and colours

groupLayout and groupSample lay out a group's picture, a few of its machines in a bunch. FINISHES lists a machine's other colours, each a device of its own. See docs/assets.md.

Coming soon

The catalogue also lists machines with no mesh yet (status: "planned"). They have a name and no shape: the gallery and <hako-device key="..."> show the one "Coming soon" picture for each, and catalogue(), statusOf(key) and catalogueCounts() say which is which. docs/wishlist.md is the list.

Help fill it in

This list has gaps, and you can help close them. Thousands of machines are listed, and many are missing a size, a CPU, a year or a date. Most are still waiting for a drawing, and some drawings are missing details a real owner would spot at once. If you know a machine, or have one on your desk, you can make this better:

  • Add a fact you can source: a size, a CPU, a release or end-of-support date, or where a button or camera really sits.
  • Correct something wrong: a wrong fact matters more than a missing one, so these come first.
  • Add a machine that is missing, or a whole product line nobody has listed yet.
  • Look at a drawing beside the real thing and tell us what is off.

A blank is always fine. A guess never is: every fact names the page it came from, so please link yours. Open an issue with the machine, the fact and the link, or send a pull request following CONTRIBUTING.md.

Want to draw machines? Building machines has the steps, the mistakes to avoid and ready prompts for directing a coding agent to the same standard.

The rest

CONTRIBUTING.md · SECURITY.md · CHANGELOG.md · NOTICE.md · MIT licence

版本与发布记录

@johnmorrisdotca/hako-devices 共发布 8 个版本,首次发布于 2026/10/31;过去 12 个月发布了 8 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.6.1latest2026/11/012 天前
0.5.02026/10/313 天前
0.4.02026/10/313 天前
0.3.02026/10/313 天前
0.2.02026/10/313 天前
0.1.12026/10/313 天前

关于 @johnmorrisdotca/hako-devices 的常见问题

@johnmorrisdotca/hako-devices 是什么?

Hako Devices:树莓派,mac,个人电脑,手机,平板电脑,游戏机,NAS盒子和经典机器的线条图和3D视图,作为web组件,带有标签,可按CPU,品牌等过滤2,200多个机器,并以输入方式组装机器

如何安装 @johnmorrisdotca/hako-devices?

在项目目录运行 npm install @johnmorrisdotca/hako-devices,或使用 pnpm add / yarn add / bun add。

@johnmorrisdotca/hako-devices 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@johnmorrisdotca/hako-devices 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@johnmorrisdotca/hako-devices 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@johnmorrisdotca/hako-devices 可以商用吗?

@johnmorrisdotca/hako-devices 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@johnmorrisdotca/hako-devices 还在维护吗?

最新版本 0.6.1 发布于 2026/11/01(2 天前);至今共发布 8 个版本,其中过去 12 个月发布了 8 个;首次发布于 2026/10/31。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。