Introducing Story Lantern

The best projects are deeply personal. They solve something that has bothered you for years but has always remained just out of reach. My book collection is one of those things.

I grew up in libraries. Not just the public library, which I frequented almost daily, but in a house whose walls were nearly covered with bookshelves, the books stacked two deep. Somehow my parents managed to keep a mental map of where each volume lay. There was little rhyme or reason that I could figure out. On those shelves, Russian literature mingled with slim philosophical tomes that stood with Victorian erotica, and atlases which crowded art books that shared space with The Whole Earth catalog. It could be bewildering to hunt for anything in that house. Yet if you asked them for something, no matter how vague ("What might you have on Pre-Colombian trade networks, especially focused on precious stones?") you’d receive back several books, each with torn slips of paper covered in hasty notes and slotted beside the relevant passages.

My parents were not academics. My mother was a social worker and my father an engineer. They simply knew their library.

Today, I've a similar problem. When I remarried, my daughter and I cleared out over 1,000 books to convert my office to a bedroom for my stepson. That was easy compared to the sprawl that is my digital collection: over 3,000 unread books, or 4,000+ if you include what I've read. With a physical collection you can arrange the map in space and time, using the texture of paper, color of jacket, position on the shelf, and even the room itself to locate what you are seeking.

A physical library has a geography. The worn, warped, and faintly musty spines invite your fingers to slide down the shelf and brush against the garish colors of the pebbled book covers of small-press poetry collections. Round the atlas of rivers, overstuffed with full-color plates and causing a noticeable bow in the shelf, and you’ll find that short story collection about undocumented immigrants staying afloat in an uncaring US that you’d been hunting for.

A digital collection, however, is so flat that it can be nearly impossible to navigate by feeling.

Story Lantern is my attempt to recover the emotional aspects of navigating my collection using a system that classifies unread titles by fiction/non-fiction, mood, and thematic weight. It tries to make my large unread digital collection genuinely browsable.

What it is built on

I made some very conscious decisions to keep things compact and nimble, guided by a “Projects first. Learning follows.” mindset. For me, it is critical to park my CTO brain and focus on the joy and delight of following curiosity and building things explicitly for myself. I am not looking to scale a SaaS product or hunt for open windows in the market to leap through. It is also a very James-shaped project in that I am using things that are already well-worn patterns for me, like decades of Goodreads data.

The Basic Stack

  • Goodreads
  • Google Books API
  • Python
  • SQLite
  • Ollama
    • qwen2.5:14b
    • phi4:14b
    • gemma3:12b

Like all good software, it runs on the command line.

How it works

This is intentionally simple software:

  1. Ingest new books to the collection
  2. Update and classify the mood and weight of new books
  3. Get randomized book recommendations

Since I am heavily into the Kindle ecosystem, I make use of Goodreads as the foundational data source because importing is as frictionless as Add Your Amazon Books. Judge me all you want but 3,000+ books in my pocket really is a dream for a person like me.

Book data and classification are updated using both the Google Books API, which performs enough like abandonware that 503 may as well be its default HTTP response, and qwen2.5:14b for the mood and weight classifications.

The results have been great...

Total books:              3078
Fiction/Non-Fiction:      3078 (100.0%)
Mood classified:          3078 (100.0%)
Descriptions:             3078/3078 (100.0%)
Reactions:                26 (interested 21 / pass 4 / started 1)

Mood confidence breakdown:
  high     2708
  medium   249
  low      8
  manual   113
  total    3078

The intent of all this wasn't to build yet another book database. The point is to recover the emotional experience of the collection. I want to find that wonderment I had as a child, watching my parents hunt and select volumes in a seemingly haphazard manner while somehow remaining so decisive and opinionated. I want something that can help me navigate my emotional landscape, show me the best places to rest, and point toward the views worth struggling to reach. I want to be surprised by what surfaces.

This is the fun part of playing with local models: you can sprinkle personality into what normally would be a random number generator. To help me surface books, I've created a persona of a haunted librarian who wants to share the treasures scattered throughout my library. They are a little odd and prone to get lost in their thoughts, but each volume they pull from the shelf carries an echo of what it was like to have my folks give me the backstory on how they acquired the copy or where they were when they first read it. My father spoke in breathless and hushed tones about his German tutor in university each time he handled his physics books from that period. You could swear he just returned from a session with her. I'm trying to capture that.

Running python3 lantern.py surprise will surface a book and tiny little tale...

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  The Secret Speech (Leo Demidov #2)
  Tom Rob Smith  ·  Fiction
  Tense / Propulsive  ·  Heavy
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  This volume seems to have shifted its place; it
  was on the Russian history shelves just yesterday.
  The narrative moves with an unsettling
  quickness—it does not linger where one might wish
  it would. It concerns itself with a society
  fracturing after Stalin’s death, and the
  precarious position of families caught within that
  shift. One follows Leo Demidov as he navigates
  this landscape, where those in power are often
  found to be guilty. Perhaps today is suitable for
  an acquaintance with such complexities.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  [i]nterested / [p]ass / [s]tarted it / Enter to skip (i, p, s, ): i

If that feels like it's too much, then slide back into your comfort zone with python3 lantern.py surprise --mood "Cozy / Warm".

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  Ruth
  Kate Riley  ·  Fiction
  Cozy / Warm  ·  Light
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  This one is best read when you have an afternoon
  to give over entirely; it asks for quiet
  attention. The narrative moves at its own pace,
  circling around the central figure of Ruth and her
  place within a community that holds firm beliefs.
  One finds oneself considering the weight of those
  convictions alongside the subtle shifts in
  perception experienced by others—a perspective
  shared with Ron Charles, I believe. It is not a
  book to be rushed; it seems to prefer an unhurried
  reader.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  Filtered by: mood: Cozy / Warm

Where I'd like to take it

I rarely read in random sequences. My TBR piles tend to form around whatever captures my interest.

  • How do the senses shape our perception of reality?
  • What is the deal with trilobites?
  • How does it feel to live as a woman in rural India?
  • I feel like I'm at the bottom of a dry well behind my house and the teenage neighbor stole my ladder.

Sequencing these feelings and interests can be tough as energy and mood shift like weather patterns. Each book can push me deeper into an interest or blow me sideways into something shockingly new. How do I capture that?

I want Story Lantern to reveal a path through that capriciousness. A map of clues I can follow toward what I need (burnout recovery!) or how I am feeling (curious but tired!). Each book should be able to alter the path, while leaving room for the books sliding laterally into the TBR from my daughter, wife, or some new curiosity I suddenly have to chase.

I don't want a reading list. I want a reading journey that changes with me.

What I’m really building is a way to ask my library a vague question and have it come back with three books tucked under its arm and a conspiratorial smile.

James @elwoodicious