Skip to content

ryanpolasky/rycord

Repository files navigation

rycord

my record collection, in 3d.

Rycord turns my Discogs collection into a cache-first 3D record room. Albums sit on a Kallax-style shelf in a rainy cafe scene, with real cover art, procedural spines, a turntable, and an RGB strip controlled by the remote on the floor.

This is built for a single personal collection, so upstream data is treated as local library data once fetched. Cache files are plain JSON or images under data/, which makes them easy to mount in Docker, edit by hand, or back up.

quickstart

npm install
cp .env.example .env.local
npm run dev

The dev server runs at http://localhost:3030.

Set DISCOGS_USER in .env.local to load a different public collection. Add DISCOGS_TOKEN if the collection is private or you want authenticated Discogs requests. If Discogs is unavailable and no cache exists yet, Rycord falls back to bundled synthetic records.

configuration

See .env.example for the full commented list.

var required purpose
DISCOGS_USER no Discogs username for the shelf
DISCOGS_TOKEN no Personal token for authenticated requests
RYCORD_HIDDEN_RELEASE_IDS no Comma/space-separated release IDs to hide
RYCORD_ADMIN_PASSWORD no Password for hidden settings-cog admin tools
RYCORD_REFRESH_TOKEN no Secret required for manual Discogs refreshes
RYCORD_DATA_DIR no Cache root, defaults to ./data
LASTFM_API_KEY no Description fallback after Wikipedia
OPENROUTER_API_KEY no Final AI fallback for album descriptions
OPENROUTER_MODEL no Comma-separated OpenRouter model chain
MULTIPLY_RECORDS no Dev-only shelf density test multiplier

cache model

Normal app loads read local cache first. Rycord only calls upstream APIs when a needed cache file does not exist yet.

path contents
data/collections/*.json Normalized collection entries and raw Discogs rows
data/hidden-releases.json Optional display blacklist of Discogs release IDs
data/releases/*.json Release metadata, notes, tracklist, durations, raw payload
data/descriptions/*.json Wikipedia, Last.fm, or OpenRouter description payloads
data/palettes/*.json Derived cover palettes
data/covers/* Proxied cover image binaries and metadata

Description lookup order is:

  1. Wikipedia
  2. Last.fm
  3. OpenRouter

Delete an individual cache file to force Rycord to fetch that item again.

hide records from the room

To keep a release tracked in Discogs but hide it from Rycord, add its Discogs release ID to either:

RYCORD_HIDDEN_RELEASE_IDS=12345,67890

or create data/hidden-releases.json:

["12345", "67890"]

The filter applies to both the collection shelf and wantlist mode.

refresh from Discogs

Rycord does not auto-refresh Discogs data. Normal app loads use the local cache forever unless refresh=1 is passed with RYCORD_ADMIN_PASSWORD or RYCORD_REFRESH_TOKEN.

You can also double-click the settings cog, enter RYCORD_ADMIN_PASSWORD, and refresh the collection or wantlist from the hidden admin panel.

Use refresh=1 when you intentionally want to re-pull your Discogs collection:

curl -H "Authorization: Bearer YOUR_ADMIN_PASSWORD" \
  "http://localhost:3030/api/collection?user=YOUR_DISCOGS_USER&refresh=1"

Refresh the wantlist the same way:

curl -H "Authorization: Bearer YOUR_ADMIN_PASSWORD" \
  "http://localhost:3030/api/wantlist?user=YOUR_DISCOGS_USER&refresh=1"

The collection request rewrites data/collections/<user>.json, compares old cached release IDs against the current Discogs collection, and prunes albums you no longer own from:

  • data/releases
  • data/descriptions
  • data/palettes
  • data/covers

The response includes source and prunedReleaseIds.

docker data volume

Mount data/ into the container so the collection survives rebuilds:

volumes:
  - ./data:/app/data

If you want the cache somewhere else locally, set RYCORD_DATA_DIR.

scripts

  • npm run dev: Next dev server on port 3030
  • npm run build: production build
  • npm start: run the production server on port 3030
  • npm run typecheck: TypeScript check

project map

app/
  page.tsx                    Load records and palettes, then mount SceneLoader
  layout.tsx                  Root metadata and global styles
  api/
    collection/route.ts       Collection response, refresh, and prune endpoint
    cover/[id]/route.ts       Same-origin cached Discogs cover proxy
    release/[id]/route.ts     Cached release details and tracklists
    description/[id]/route.ts Cached Wikipedia, Last.fm, OpenRouter descriptions

components/
  Scene.tsx                   R3F room, shelf layout, camera, post effects
  VinylRecord.tsx             Pull-out record interaction and front/back jacket
  InfoPanel.tsx               Active record metadata, notes, tracklist, actions
  Room.tsx                    Floor, wall, baseboard, rug
  RoomProps.tsx               Wall art, plant, book stack, mug, other decor
  RGBStrip.tsx                Addressable LED strip
  Remote.tsx                  In-scene controls for the LED strip
  Paper.tsx                   Pickup-style note from me on the floor
  Turntable.tsx               Centerpiece player
  Shelf.tsx                   Procedural Kallax-style grid

lib/
  dataCache.ts                Disk cache helpers
  discogs.ts                  Discogs client, collection cache, refresh pruning
  cachedAssets.ts             Cover and palette disk cache
  palette.ts                  Sharp-based palette extraction
  releaseDetails.ts           Client-side release detail loader
  covers.ts                   Synthetic fallback records
  ledStore.ts                 Shared state for the remote, paper, and LED strip

current limits

  • Desktop-first scene, with MobileGate for narrow or touch viewports
  • One configured collection at a time
  • One room theme
  • No audio playback

note from ryan

I know the commit history is short - I have a bad habit of writing wild commit messages on projects when I don't think they'll go live. This one turned out nicely though, and I wanted to share it. Thus, I went ahead and squashed the commits down to just the few you see. Apologies if you wanted to see my process of iterating for some reason. Check my other projects out for that.

About

Rycord turns my Discogs collection into a cache-first 3D record room.

Resources

Stars

Watchers

Forks

Contributors

Languages