Repository navigation
v3.0.0
3.0.0
Cinemory learns to talk to an assistant, to be read without a mouse, and to
show you where the things on your watchlist actually are. Fifty commits since
2.0.0.
Updating from 2.0.0 needs one step on the database — see the bottom.
An MCP connector
An assistant can now read this catalog during an ordinary chat: what you have
watched, what is waiting, and the numbers behind it — no pasting exports, no
guessing. Off until you switch it on in Settings, and revocable in a click.
- The credential travels in an
AuthorizationorX-API-Keyheader, or in the
URL for connectors that store nothing else. It is hashed at rest and shown
once. - A read-only token is the default. A write-capable one can add to the
watchlist, mark something watched, and correct where and when — never delete.
The scope is part of the hashed string, so it cannot be edited in the URL. - A missing or wrong credential gets
401with a challenge on the plain
address, and a plain404on the URL-with-token form, where the address is
the credential.
See docs/mcp.md.
Import from Letterboxd
The one export that knows more than the streaming services do: the release
year, your star rating, and the day you actually watched something rather than
the day you logged it. diary.csv, ratings.csv, watched.csv and
watchlist.csv are all read. Rewatches fold into one row, keeping the most
recent viewing.
Keep the file names Letterboxd gave them: watched.csv and watchlist.csv are
identical inside, and the name is the only thing that says which half of the
catalog a title belongs in.
Where to watch what is waiting
Every title in "To watch" now says where it is streaming right now in your
region, from TMDB. Asked a screenful at a time and remembered for half a day,
so a long watchlist costs one request rather than hundreds. Rentals and
purchases are left out — that is not an answer to what to watch tonight.
Restore a backup
The export has always written a full JSON dump and nothing could read it back.
Now Settings → Restore from a backup does: it adds the titles the catalog
does not have and leaves the rest alone, so it rebuilds an empty instance and
merges into a live one without overwriting anything.
A new sign-in screen
- Your own posters drift past in columns behind a glass card — the catalog is
recognisable before you are in, and does nothing until you are. A catalog
with fewer than 50 posters gets an animated terminal instead, and Settings
→ Sign-in screen forces either. - The code is six boxes, one per digit, and submits itself on the sixth.
- Sign out, which was not possible before: it clears the session and the
offline copy of the catalog with it. - Use a different authenticator — a new phone, a lost one, a QR code that
was photographed. It asks for a code from the authenticator in use before it
will hand out a new secret, and writes nothing until a code from the new app
comes back.
Offline, and saying so
Browsing without a network already worked; now the app admits it. A status line
says the catalog on screen is the saved copy, and writes that cannot reach the
database say so instead of failing silently.
Keyboard and screen readers
The grid was a pointer-only surface. Now:
Tabwalks the page (it used to be captured and sent to the search field on
every press, which left the cards, the filters and the settings link
unreachable without a mouse),/jumps to the search from anywhere.- A card takes focus, has a name, and answers to
Enter— which opens its
actions — andShift+Enter, which picks it out for a batch. - Dialogs keep the keyboard inside them and hand it back where it came from.
Also new
- Finish an interrupted import from Settings: a closed tab or a lost
connection used to leave the rest of the catalog without posters for good. - Search by words: every word has to appear, in any order — "wars empire"
finds The Empire Strikes Back — and typing a title with its accents works. - Marking something watched breaks the card into pixels on its way out, and
the same in reverse when it goes back to the watchlist. - Series seasons are edited from the dialog, with the total fetched from
TMDB rather than typed. - Setup moved out of the README into docs/, written to be
followable without a terminal, plus a security policy, contributing
guidelines and a code of conduct.
Fixes
- Missing posters showed nothing while there was plenty to fix: the filter
that skips "ignored" titles was written asNOT (tmdbId = -1), which in SQL
is null rather than true for a title TMDB never matched — so exactly the
titles that needed linking by hand were the ones hidden. - The genre filter answered confidently with nothing when the catalog held
no genres. - The genre and sort dropdowns could not be used in the desktop filter
panel: the panel closed on the way to an option and unmounted the list before
the click landed. - The sideways rows of platform pills would not move with a mouse wheel.
- The header turned into the compact layout at the width where the desktop
one stopped fitting, instead of wrapping onto two rows. - A date that is not a date is refused on the app's own write routes, not
only on the MCP ones:new Date("some time in 2021")is the first of January
2021, not an error. - The poster routes answer 404 rather than 500 when given an id that is not
there.
Under the hood
- 199 tests, up from 68. The API routes that write are covered now — every
test asserts the database did not move when a request was refused. - The catalog page is three times smaller: it only sends the columns the
grid reads. Measured on a 1,366-title catalog, 227 KB → 75 KB gzipped. - An error boundary, so a crash is a page with a way back rather than
Next's bare "Application error". docs/schema.sqlis generated from the migrations, and a test fails if it
goes stale — it is what someone with no checkout pastes into their database.- The code, its comments and the database schema are English throughout.
Updating from 2.0.0
npm install first: this release adds ogl, mcp-handler and the MCP SDK.
Two migrations landed since 2.0.0. If your database has neither, run both — in
the Turso SQL console:
ALTER TABLE "Settings" ADD COLUMN "mcpTokenHash" TEXT;
ALTER TABLE "Settings" ADD COLUMN "mcpTokenCreatedAt" DATETIME;
ALTER TABLE "Settings" ADD COLUMN "loginBackground" TEXT NOT NULL DEFAULT 'auto';Or, with the repository checked out and the two Turso values in a .env:
npm run db:migrate-turso, which is safe to re-run. Pasting
docs/schema.sql again works too: it stops harmlessly at what
already exists.
Do this before the new code goes live — until the columns are there, the
app errors on every page load. Nothing else is needed: your catalog is
untouched by this release.