WINDER

Library Format

A Winder library is a plain folder a human can read without the app. No database, no proprietary bundle, no export button — because nothing is ever locked in.

This chapter is the reference. Every file Winder writes is documented here, so you can read a library with a script, repair one by hand, or write a tool that speaks the same format.

The tree

Winder Library/
  library.json                ← format marker
  settings.json               ← scan geometry, output quality, last gear
  albums.json                 ← the album labels
  WDR-260504-0009-F.jpg       ← a frame on no roll, loose at the root
  WDR-260504-0009-F.json      ← its sidecar
  Rome, May '26/              ← a roll; the folder name IS the roll name
    roll.json                 ← id, created date, film, camera, scan
    WDR-260504-0001-A.jpg     ← left half of scan 0001
    WDR-260504-0001-A.json    ← that frame's sidecar
    WDR-260504-0001-B.jpg     ← right half
    WDR-260504-0001-B.json
  Roll 260806/                ← a roll nobody named: dated folder
    roll.json                 ← …and { "name": "" } inside
  .trash/                     ← everything deleted lands here

Four things live at the root, and everything else is either a roll folder or a loose frame.

FileWhat it is
library.jsonThe format marker. Its presence is what makes a folder a library
settings.jsonScan geometry, output quality, remembered gear
albums.jsonAlbum definitions — id, name, created date
roll.jsonOne per roll folder: identity, film, camera, scan
<frame>.jsonOne per photograph, beside it

Frame filenames

WDR-260504-0001-A.jpg
    │      │    └── half: A = left, B = right, F = whole frame
    │      └─────── counter within the day, zero-padded to four
    └────────────── date filed, yyMMdd

Chronological in any file browser, which is the point of being a file-first app. The sidecar is the same name with a .json extension.

Recognised image extensions: .jpg, .jpeg, .png, .webp, .bmp, .tif, .tiff. Winder writes JPEG; it will read and file the rest.

library.json

{
  "version": 2,
  "app": "winder",
  "createdAt": "2026-05-04T10:22:31.004"
}

A folder containing this file is a Winder library, and pointing the app at one adopts it as-is rather than nesting another library inside it.

Format versions

VersionShape
1One folder per album, with album.json inside carrying a cover
2Folders are rolls (roll.json); albums are labels in albums.json

A version 1 library migrates on the first scan: each folder holding an album.json is read as a roll and rewritten as roll.json, carrying the id and creation date across and dropping cover. The superseded album.json is then deleted — leaving it would have every later scan read a file that no longer describes anything — and library.json is brought up to version 2.

Rules Winder holds itself to

These are the guarantees a second tool reading or writing the folder can rely on.

Writes are atomic. Every JSON file is written to <name>.tmp and renamed into place. A sync client never observes half a file. Frame EXIF rewrites use the same dance.

Nothing is hard-deleted. Deleting a frame or a roll renames it into .trash/, with a timestamp appended for rolls. Emptying that folder is the user's business. Deleting an album is the exception that proves the rule: an album owns no files, so it only ever removes a word.

The folder is the truth, re-read on every resume. Winder rescans the tree each time the app comes back to the foreground, because another device may have edited it. Nothing is cached across a launch.

A broken file never costs a photograph. A corrupt sidecar, an unparseable albums.json, a hand-mangled settings.json — each falls back to defaults and the photographs still load. A missing id is regenerated and written back.

Unknown keys survive. Winder reads the keys it knows and defaults the rest. Album ids in a sidecar that name no album in this vault are kept exactly as written: they match nothing, so they cost nothing, and a sync that restores the definition restores the membership with it.

Paths are never persisted. A frame's location on disk and its roll membership are read from where the file actually is. Move a .jpg and its .json into another roll's folder and the frame has changed rolls.

What is not in the library

Anything about the app rather than the photographs stays on the device: theme, language, app icon, how many columns the stream shows on this screen, and the bookmark that says where the library is. A phone and a Mac reading one library each keep their own.

Updated 2026-08-06