Skip to content

Latest commit

 

History

91 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PrintVault

PrintVault

I had about 460 files in a folder called "3d print files". Half a dozen subfolders named "files". No idea which settings I'd used on anything I'd already printed. When I finally got a proper index of it there were 78 zips I'd never extracted, holding 414 printable models that nothing had ever shown me.

This is what I built to dig myself out. It's free, GPL-3.0, and runs either in your browser or as a desktop app.

Live at https://printvault.magikh0e.pl/

Get it

Nothing to install if you just want to try it: open printvault.magikh0e.pl in Chrome, Edge, Brave or Opera and point it at a folder.

If you would rather look before handing over a folder, there is a demo at /app/?demo. It fills the app with an invented library so you can click around. It runs entirely in memory, so it cannot see or change a real library in the same browser, and it disappears when you close the tab.

The desktop app is worth it if you have a lot of files, keep them on a network share, or are tired of re-granting folder access every session. Grab an installer from Releases:

Platform File
Windows .msi or .exe
macOS .dmg (universal, Intel and Apple Silicon)
Linux .AppImage, .deb or .rpm

The builds aren't code signed, because certificates cost more than this project does. Windows SmartScreen will want "More info" then "Run anyway", and macOS will want a right-click then Open the first time. If that bothers you, build it yourself from source below; it's the same thing.

Windows and Linux have both been run against a real library, Linux on Ubuntu. macOS builds cleanly in CI but nobody has pointed it at a folder yet, so treat that one as untested and tell me if something breaks.

What it does

Point it at a folder and it reads what's already there. Nothing gets moved, renamed, or reorganised into somebody else's idea of a good structure.

It renders a 3D preview for every model, so you're looking at pictures instead of filenames, and reuses the plate render your slicer already embedded when there is one.

It pulls settings out of your sliced gcode: time, grams, layer height, nozzle, infill, material, profile name. Works with PrusaSlicer, OrcaSlicer, BambuStudio, Creality Print and Cura. Creality Print and Bambu bury the gcode inside their .3mf project files, so it digs that back out. Log a print when it comes off the bed and the form is already filled in, which means six months later you can still see what you ran and whether it worked.

It reads inside zips you never extracted, listing and previewing what's in them without unpacking anything. It'll extract them too, and checksums every file it writes. The desktop build does the same with 7z, which a browser has no way of opening.

It finds duplicate downloads and proves they're identical with SHA-256 before touching anything. By default it moves the copies to a quarantine folder rather than deleting them, because a browser can't use the Recycle Bin and I didn't want that on my conscience.

There's filament tracking by what's actually left on the spool, and a print queue that adds up grams and hours so you know whether you can finish something before you start it. Start on a queued row sends the file to the printer rather than just noting that you meant to. If you want the number first, the cost button works out filament and running cost for however many copies you're planning.

Everything you type, meaning tags, collections, notes and ratings, exports to a JSON backup that restores anywhere. It matches on folder name and relative path rather than internal ids, so moving to a new machine or re-adding the folder still finds everything. Restore before you scan and the metadata waits in the database until the files show up.

No account, nothing uploaded, no server involved.

How it's put together

index.html            the whole app, one self-contained file
desktop/              Tauri shell
  build.mjs           copies index.html into dist/, syncs version numbers
  serve.mjs           dev-only static server with correct MIME types
  make-icon.mjs       generates every app icon from raw pixels
  src-tauri/          Rust backend

The same index.html runs in a browser and inside the desktop shell. It picks its filesystem layer when it loads, either the File System Access API or native calls through Tauri, and the other 96% of the code doesn't know or care which. No build step, no bundler, no dependencies.

Adding ?demo to the URL is handled the same way, one seam rather than a parallel code path. The Demo module swaps the storage layer for plain Maps before anything opens IndexedDB, then generates a library into it: models, files, prints, spools, a queue and a few deliberate duplicates. Everything above that layer runs exactly as it normally does, which is the point. Nothing is shipped to support it either. The previews are real WebGL renders of meshes built from primitives in code, so there are no screenshots baked into the file.

Two consequences worth knowing if you're changing it. The demo can't reach a real library, because DB.open never runs, so a visitor poking at the demo cannot see or overwrite an actual index in the same browser profile. And anything that touches disk is stubbed to refuse with an explanation, since there is no folder behind any of it.

Self-hosting the web version

It's one file, so any static web server will do. From the folder containing index.html:

python -m http.server 8000

Then open http://localhost:8000/. Any other port is fine if that one's taken.

It has to be served, not opened directly. A file:// path won't work, because browsers only hand out folder access in a secure context, meaning https or localhost. Chromium only for the folder part (Chrome, Edge, Brave, Opera), since Firefox and Safari don't implement the API.

Building the desktop app

You need Rust and Node 20+. On Linux you also need the WebKitGTK development packages:

sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev \
  libayatana-appindicator3-dev librsvg2-dev libssl-dev

Then:

cd desktop
npm install
npm run tauri:dev      # with frontend hot reload
npm run tauri:build    # installers land in src-tauri/target/release/bundle/

There's no frontend build step. build.mjs copies index.html into dist/ and stamps its version into the shell, so the two can't drift. Icons are generated by make-icon.mjs rather than committed, so if tauri:build complains about a missing icon, run that first.

tauri:dev serves the frontend through serve.mjs rather than Tauri's own dev server, which hands index.html back as application/octet-stream and leaves WebView2 showing a blank window.

Why bother with the desktop build

Almost everything annoying about the browser version is the browser, not the app.

Browsers forget folder access between sessions, so every visit starts by clicking Scan to re-grant it. Roots are stored as paths here, and paths survive a restart.

Speed is the bigger one. A browser has to open every file individually just to learn how big it is. One Rust call returns the whole listing with sizes and timestamps, which on a network share is the difference between minutes and seconds.

Archives are unpacked in Rust too, so entry bytes never cross into JavaScript. That fixes large entries running the browser out of memory, and gets you bzip2 and zstd, which browsers can't inflate at all.

And Firefox and Safari don't implement the File System Access API, so the web version can't work there no matter what. The desktop build doesn't care.

Support

Free and open source, built and maintained in my own time, with no accounts, tracking or ads. If it's saved you a failed print or a few gigabytes, a beer helps keep it going.

Buy me a beer

Bug reports and folder layouts that break the scanner are just as useful.

Something broken goes in Issues. Anything else, questions, a folder structure you can't get grouping sensibly, or a look at what your own library turned out to contain, goes in Discussions.

Licence

GPL-3.0-or-later, see LICENSE.

About

A free, local-first library manager for anyone whose 3D print folder has got away from them: it indexes what you already have, where it already is, and never uploads a thing.

Topics

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Used by

Contributors

Languages