Piezario
A desktop app for makers to organize a personal catalog of 3D models and work out what a print actually costs. No database, no import step — the folder on your disk is the database.
Overview
Piezario is a desktop app for keeping a personal catalog of 3D models and pricing the prints that come out of them. The name is Spanish — pieza + -ario, “a personal collection of parts”, the way a recetario is your collection of recipes.
It’s deliberately narrow. It isn’t a storefront, it isn’t a design tool, and it isn’t something you publish. It organizes the parts you already have on disk, and it tells you what each one costs you to make.
- Source: github.com/jcarranz97/piezario — ships as a Linux AppImage and a Windows
.exe
The one idea: the folder is the database
Point Piezario at a folder and it renders whatever is there. There’s no import step, no database, no admin panel, no sync. You edit a README, hit refresh, and the app has changed.
One rule drives the whole catalog:
A folder with no subfolders is a model. Its parent folders are its categories.
So models/keychains/ysisi-nametag/ is the model Ysisi nametag in the category
keychains, and nesting can go as deep as you like. Everything else is derived rather
than declared:
| Derived | From |
|---|---|
| Category | Ancestor folder names |
| Title | title: in frontmatter → folder name |
| Description | description: → the README’s first paragraph |
| Cover image | cover: → a *preview* / cover.* image → any image |
| File kinds | File extensions |
| Capability badges | Which kinds of file are present |
A model with no README at all still shows up — just with less on its card. That property is the whole point: the catalog can never get out of sync with the disk, because the disk is the catalog.
What’s in it
Six tabs. Three are folder-driven:
- Models — the catalog itself, filtered and searched entirely client-side.
- Fonts — a flat
fonts/folder rendered as a Google-Fonts-style specimen browser, for the typefaces my generator scripts draw text with. - Icons — nested
.svgfiles as a resizable preview browser, with an optional Search online mode that reaches into svgapi.com’s public-domain library and saves a chosen icon straight into the folder.
Three are driven by a catalog.yaml and are editable in-app — filaments (your spools,
by product and color), supplies (rings, chains, glue, priced per unit), and the global
cost settings. Writes go through a single comment-preserving writer, so hand-written
notes in the YAML survive being edited by the app.
Costing a print properly
This is the part I actually built it for. Piezario follows the Print Farm Academy method:
landed = raw materials + purchased materials + packaging + labor + machine
price = landed × (1 + tax) × (1 + markup)
Two details make the numbers honest:
Raw materials carry a waste buffer. Filament weight × an efficiency factor (1.1 by default) × the per-kg rate. A slicer quotes you the cost of a print that succeeds; across a hundred parts, failures, jams and defects eat more filament than any file admits.
Machine time is a real cost. Print time × an hourly rate covering the printer wearing itself out plus the power it draws — not free just because you already own the printer.
The weights and times aren’t typed in by hand. A .3mf is a ZIP, so the app reads the
sliced files in each model’s out/ folder directly. Files sitting loose in out/ are the
Estimate — your reference print — while each subfolder is a real sale batch summed on
its own.
The bug that justified the 3MF parser
Reading those files bought something I didn’t plan for. Bambu Studio records which extruder each part uses, so when a folder holds several variants of the same model, Piezario can compare them and check they agree about what each tool means.
If paw is tool 2 in one file and tool 3 in another, opening them together silently
prints one of them in the wrong color — and you find out four hours later, holding it.
Now it’s a warning on the page instead.
How it’s built
| Layer | Technology |
|---|---|
| App | Next.js 16 (App Router) + React 19 + Tailwind v4 + HeroUI v3 |
| Shell | Electron 33 |
| Thumbnails | a small numpy/matplotlib CLI that renders cover.png from an STL |
| Packaging | electron-builder → AppImage + Windows .exe, built in GitHub Actions |
Everything runs locally; there is no backend service and nothing leaves the machine.
The interesting constraint is that Piezario can’t be a static export. It reads the
tree with node:fs, opens files in your desktop’s own apps, and writes back to READMEs
and catalog.yaml — so the desktop build runs the real Next server inside Electron,
launched with Electron’s bundled Node via ELECTRON_RUN_AS_NODE. The window just loads
http://127.0.0.1:<port>. That’s also why the packaged app needs no separate runtime
installed: Electron already ships one.
Pages are force-dynamic for the same reason. The catalog changes while the server is
running, so a cached render would be showing you a folder that no longer exists.
The whole thing is wired from one environment variable — CATALOG_CONFIG points at a
catalog.yaml, and the app resolves models/, fonts/ and icons/ relative to it. The
app has no dependency on any particular catalog, which is what lets you point it at any
folder without touching code.
Status
Early but usable — it builds, packages, and I’m running it against my own catalog.
Releases are cut by tagging: a GitHub Action builds the AppImage on Linux and the .exe
on Windows and attaches both, so I never need a Windows machine to ship a Windows build.
Most of the work so far has been the unglamorous desktop-integration layer that decides
whether an app feels native or broken: running without the Chromium sandbox so the
AppImage starts on modern Linux, fixing a blank and laggy window under Wayland, matching
desktop scaling so the text isn’t tiny, and setting StartupWMClass so the taskbar icon
is right.
Next up is filling out the catalog side and getting more of the pricing surfaced where I actually need it — at the moment I still open a slicer more often than I’d like.