A self-hosted vinyl, CD and cassette collection manager. Your database is the source of truth; Discogs is the metadata source.
Live demo · Quick start · Build it yourself · Features · License
Cratefolk keeps track of the vinyl records, CDs and cassettes you own, the ones you want, and the ones you're selling. Add a release by searching Discogs (one search box for name, catalog number or barcode) and Cratefolk stores the metadata and cover in your own SQLite database, so your collection keeps working, and stays yours, even if Discogs changes or goes away.
It runs on your own machine, NAS or VPS with one docker compose up. No subscriptions, no ads, no
third party holding your collection.
Try the live demo → — a static build with sample records and a mocked, browser-only backend (see Demo mode), so you can click around without installing anything.
- 💿 Vinyl, CDs and cassettes — one search box for artist/album, catalog number or barcode (vinyl by default, or include every format), or scan the barcode with your phone's camera; the exact pressing, tracklist, label and cover are saved locally, and CDs and cassettes get a small badge on their cover. Not on Discogs? Add the record by hand, with your own cover photo and tracklist (you can edit or delete these later). Adding a record you already own asks first
- 🗂️ Every copy is its own entry — own two copies of a record? Grade each one separately (media and sleeve, Goldmine scale) and add notes
- 📦 Crates — group records any way you like ("Jazz", "90s", "Listening room"); a copy can live in several
- 💡 Trivia on every record — a "Did you know?" box with facts from the album's Wikipedia article, falling back to the artist's, then to facts worked out from the record itself, so there is always something to read. It's fetched when you add a record, and links to its source
- 🔍 Instant search and filters — search artist, title, label, catalog number or barcode as you
type (press
/to jump to it), filter by format, decade and country, sort, and resize the covers with a slider - ❤️ Wishlist — track the pressings you're after, see the current Discogs marketplace price and number of copies for sale, and move a record to your collection with one click ("Got it")
- 🏷️ For sale — mark any copy as for sale with an asking price, filter your collection by it, and share a public "records I'm selling" page with grades and prices
- 🔗 Share links — a public, read-only link for your whole library, a single crate, your wishlist or your for-sale list. Notes stay private, and you can revoke a link at any time
- 📈 Stats — records by decade, format, genre, artist and label, what you added recently, and the value of your for-sale copies
- 🔄 Discogs sync — connect your own Discogs account (Account → Discogs, with a personal access token; Cratefolk never asks for your password). "Sync now" merges your collection and wantlist both ways: records missing on either side are added, and for copies on both, grades and notes follow whichever side changed since the last sync (Cratefolk wins if both did). New records, wishlist items, grades and notes are also sent to Discogs as you make them, which you can switch off. Deletions only sync if you turn on "Also sync deletions"; otherwise nothing is ever deleted on either side, and a record you delete here simply won't come back at the next sync
- 📊 Excel export — download your collection, a crate, the for-sale list or the wishlist as
.xlsx - 👥 Multiple users — the admin creates accounts (and can set a password or hand out a one-time reset link), or opens registration so people can sign up themselves; everyone gets their own private collection
- 🤝 Browse and share with friends — opt in to let other users browse your collection or wishlist (read-only, never your grades, notes or prices), and mark copies you co-own with someone, which then show in both your collections
- 📰 Friends' activity feed — a collapsible sidebar feed of what friends add, wishlist, put up for sale and sell (only what they share, and they can opt out), plus a "Mark as sold" button for your own copies
- 💱 Prices in your currency and a light/dark theme that follows your system
- 🐳 One container — the API, the web app and an SQLite database, nothing else to run
You need Docker with the Compose plugin. The image is
published to GitHub Container Registry for linux/amd64 and linux/arm64, so it runs on a regular
PC, a Raspberry Pi and most NAS boxes.
-
Get the compose file and the example settings:
git clone https://github.com/blindpassasjer/cratefolk.git cd cratefolk cp .env.example .envDon't want to clone? You only need docker-compose.yml and a
.envfile next to it. -
Edit
.env:ADMIN_EMAILandADMIN_PASSWORD— your admin login (required)DISCOGS_TOKEN— a personal access token from discogs.com/settings/developers. It works without one, but Discogs then allows fewer requests per minute and withholds search thumbnails, so setting it is recommendedCOOKIE_SECURE=true— only if you serve Cratefolk over HTTPS
-
Start it:
docker compose up -d
-
Open http://localhost:6170 (or
http://<your-server>:6170) and sign in with the admin account from step 2.
That's it. The database is created and migrated automatically on first start.
- The admin account is created from
ADMIN_EMAIL/ADMIN_PASSWORDon every start, and its password is re-synced from the environment, so changing the variable and restarting is how you reset it. - Sign-up is closed by default: the admin creates accounts under Users, and can switch registration on there if you want people to create their own accounts.
- To use another port, change the left side of
'6170:6170'underports:indocker-compose.yml. - If you use
env_file: .env, do not putDATA_DIRorPORTin it, and keepDATA_DIR: /dataunderenvironment:so nothing can redirect the database outside the data folder.
git pull # if you cloned the repo, to pick up compose file changes
docker compose pull
docker compose up -dDatabase migrations run automatically when the container starts. Releases are tagged X.Y.Z; the
latest tag always points at the newest release, and you can pin a version in docker-compose.yml
(for example ghcr.io/blindpassasjer/cratefolk:0.3.0) if you prefer to upgrade deliberately.
Everything is stored in a plain folder next to your docker-compose.yml, not in an opaque Docker
volume, so you can browse, back up or move it like any other files:
| What | Where |
|---|---|
| Users, records, copies, crates, wishlist, share links (SQLite) | ./data/cratefolk.db |
| Cover images fetched from Discogs | ./data/covers/ |
| Key that encrypts users' Discogs tokens | ./data/secret.key |
Stop the container so the database isn't being written to, copy the folder, and start it again:
docker compose stop
cp -a data "data-backup-$(date +%F)"
docker compose startdata/secret.key is what protects the Discogs tokens stored in the database, so keep your backups
private. Without it the saved tokens can't be read and users would have to connect Discogs again.
To restore, stop the container, put the backed-up folder back as ./data, and start it again.
Moving Cratefolk to a new machine is the same thing: copy data/ over, along with your .env.
Cratefolk speaks plain HTTP on port 6170. To serve it over HTTPS, put a reverse proxy with a
certificate in front of it (Caddy, Traefik, Nginx Proxy Manager, or your NAS's built-in one all work)
and set COOKIE_SECURE=true in .env so the session cookie is only sent over HTTPS.
HTTPS is also required for barcode scanning: browsers only allow camera access on secure pages (or
localhost), so the scan button is hidden when Cratefolk is served over plain HTTP.
| Variable | Default | Description |
|---|---|---|
ADMIN_EMAIL |
— (required) | Email of the admin account, created on every start |
ADMIN_PASSWORD |
— (required) | Password of the admin account, re-synced on every start |
DISCOGS_TOKEN |
empty | Discogs personal access token for searching; raises the rate limit and enables search thumbnails. Syncing uses each user's own token, set under Account → Discogs |
SECRET_KEY |
generated | Optional passphrase for encrypting users' Discogs tokens. By default a random key is created in data/secret.key |
COOKIE_SECURE |
false |
Set to true when served over HTTPS |
TRUST_PROXY |
false |
Set to true only behind a reverse proxy that sets X-Forwarded-For; used for login rate limiting |
PORT |
6170 |
Port the server listens on. Preset in the Docker image, only set it for local runs |
DATA_DIR |
./data |
Where the database and covers are stored. Preset to /data in the Docker image |
WEB_DIR |
../web/dist |
Where the built web app is served from. Preset in the Docker image |
Pick whichever fits: build the Docker image from source, or run it directly with Node.js.
Handy if you want to run a modified version or a commit that isn't released yet. You only need Docker and Git.
git clone https://github.com/blindpassasjer/cratefolk.git
cd cratefolk
cp .env.example .env # then set ADMIN_EMAIL and ADMIN_PASSWORD
docker compose up -d --build--build makes Compose build the image from the Dockerfile in this folder instead of
pulling the published one. To build the image on its own:
docker build -t cratefolk .To build for another architecture (for example a Raspberry Pi from a PC), use
docker buildx build --platform linux/arm64 -t cratefolk ..
You need Node.js 20 or newer and npm.
git clone https://github.com/blindpassasjer/cratefolk.git
cd cratefolk
npm ci # install dependencies
npm run build # builds the web app and the server
export ADMIN_EMAIL=admin@example.com
export ADMIN_PASSWORD=change-me-please
export DISCOGS_TOKEN=... # optional, but recommended
npm start # http://localhost:6170The server serves the built web app itself, so there is nothing else to run. Data is stored in
apps/server/data/ unless you set DATA_DIR to somewhere else (use an absolute path). To keep it
running in the background, use a process manager such as systemd or pm2.
better-sqlite3 is a native module. npm ci normally downloads a prebuilt binary; if there isn't one
for your platform it compiles from source, which needs a C/C++ toolchain (build-essential and
python3 on Debian/Ubuntu).
The live demo is a static build deployed to GitHub
Pages by .github/workflows/deploy-demo.yml on every push to
main. GitHub Pages can only serve static files, so the demo build replaces the real API client in
apps/web/src/api.ts with a mock
(apps/web/src/demo/mockApi.ts) that runs entirely in your browser:
- A catalogue of sample records stands in for Discogs search. Covers are loaded from the Cover Art Archive when you're online, with generated artwork as the fallback, so no cover images are bundled.
- Your changes (adding records, grading copies, crates, for-sale prices, share links) are saved to
localStorageon your own device. Nothing is sent to a server. - Any email and password signs you in, and Excel export isn't available.
- Reset demo data in the banner at the top starts over.
Build it yourself with:
npm run build:demo # output in apps/web/dist, served from /cratefolk/or run it as a dev server (served from /) with npm run dev:demo. If you fork the repo, set
VITE_DEMO_BASE to your Pages subpath (for example VITE_DEMO_BASE=/my-fork/) and enable
Settings → Pages → Source: GitHub Actions on your fork.
If you change the shape of an API response, update the mock to match, or the demo will drift from the real app.
npm install
export ADMIN_EMAIL=admin@example.com ADMIN_PASSWORD=change-me-please
npm run dev # API on :6170, web on :5173 (proxies /api)Open http://localhost:5173. Layout: apps/server (Hono + SQLite), apps/web (React + Vite +
Tailwind). npm run typecheck checks both. Database migrations live in
apps/server/src/db.ts and run on start.
React 18 · Vite · Tailwind CSS 4 · Hono · SQLite (better-sqlite3) · Zod · TypeScript. One small codebase, one container, no external services beyond the Discogs API.
Cratefolk is free and open source. If it's useful to you, you can buy me a coffee or Vipps me.
Issues and pull requests are welcome. The codebase is small enough that most changes are straightforward to review.



