Dr Lily Geidelberg

Put Reading Shelf on your website

A little book that opens into what you’re reading, with your recently finished books tucked underneath. Use it on your own site, with your own books.

Lily’s live shelf · click the book to try it

Let your agent set it up

Copy this into the agent building your website. Give it the books you’re reading and anything you’ve finished recently; it can handle the files and the placement.

Add Reading Shelf to my website using this installation guide:
https://lilygeidelberg.com/reading/install.md

Use my own books, not Lily’s feed, and match my existing site.
Start with a JSON file hosted on my site. Keep the collapsible,
pulsing book-and-arrow control. Ask me for any missing book details.
Show me how to update my books afterwards.
Read the agent guide

The file-based version needs no account, API key or database. Your site must allow custom JavaScript and a public JSON file.

Already use Goodreads?

Keep changing books on Goodreads and let your website follow along. Paste your public profile link to preview your shelf and get an embed for your own books. No Goodreads password or API key.

Public profiles only. Shows up to 24 current books and 100 recent reads, with Goodreads book links and covers. Feeds are cached for an hour; Goodreads may also delay updates. It is one-way: the widget cannot change Goodreads. Reviews and ratings are not imported, and unknown dates stay blank.

This option uses the read-only Goodreads adapter hosted here. It depends on Goodreads’ public RSS feed remaining available. For a self-hosted adapter, see the agent guide.

Or add it yourself

  1. Create your book list

    Save reading.json in your site’s public files, so it is available at /reading.json. Replace the example title and author with your own. For an empty shelf, use "books": [].

    See the starter JSON
    {
      "schemaVersion": 1,
      "revision": 1,
      "name": "Your name",
      "updatedAt": null,
      "books": [
        {
          "id": "book-1",
          "title": "Your book title",
          "author": "Author name",
          "status": "reading",
          "workId": "",
          "cover": "",
          "url": "",
          "startedAt": null,
          "finishedAt": null,
          "progress": null,
          "note": ""
        }
      ]
    }
  2. Add the shelf to your page

    Put these two lines where you want the book icon. The script supplies the widget; src points to your book list. If your site lives under a subpath, include it: for example, /portfolio/reading.json.

    <script type="module" src="https://lilygeidelberg.com/reading/reading-shelf.js"></script>
    <reading-shelf collapsible src="/reading.json"></reading-shelf>

    You can also download the component and host it yourself. It is one file, with no runtime dependencies. In a server-rendered framework, load it in the browser, not on the server.

  3. Change books whenever you like

    Update and publish reading.json, or tell your agent what changed. Keep each book’s id stable. To finish one, change its status to "finished" and set finishedAt to its finish date in YYYY-MM-DD format. Add your next book with a new ID and "status": "reading".

    Increase revision with each edit and set updatedAt to the edit’s actual ISO timestamp. Keep earlier books in the list; the shelf sorts finished books into history for you.

    The widget checks for changes every 30 seconds while the page is visible, and when someone returns to the tab. Publishing the JSON is still your responsibility; it does not write changes back to your site.

Make it fit your site

The shelf inherits your typeface, and its colour options let you match your site. Its styles stay inside the component, so they do not restyle the rest of your page.

collapsible
Start with just the pulsing book and arrow. Click to open the shelf.
open
Add alongside collapsible to start expanded. Remove collapsible entirely to keep the books visible.
variant="profile"
A narrower, single-column layout for a sidebar or profile.
fallback-src
An optional backup JSON URL. Keep it up to date; a fallback is not a live backup service.
Preview the profile layout and colour options

For an explicit colour match, set these on the element in your stylesheet. --reading-background and --reading-font are also available.

reading-shelf {
  --reading-ink: #26282c;
  --reading-muted: #5c5f66;
  --reading-line: #e2e2e0;
}

The pulse indicates a current reading list, not that someone is online. It settles when opened and is disabled for people who prefer reduced motion.

Want an editor or API-driven updates?

Use a JSON file to get started. If you want to change books in a browser without republishing files, your site needs its own persistent API and a private editor. An agent can build that on your existing host using the Reading Shelf API contract.

This is a reusable widget, not a hosted account service. Lily’s API and editor manage Lily’s books only; they do not create a shelf for you.

How an agent updates a connected shelf

On your own API, read the shelf first, then send an action with your private write key and the quoted current revision. This example’s host, key, book ID and revision are placeholders.

GET https://your-site.example/api/reading

PATCH https://your-site.example/api/reading
Authorization: Bearer YOUR_PRIVATE_WRITE_KEY
If-Match: "3"
Content-Type: application/json

{"action":"finish","id":"BOOK_ID"}

The contract supports starting, finishing, editing, adding history and undoing changes. “Finish & next” can be one atomic action. If the API returns 412, re-read and reconcile the change before retrying.

Keep write keys in your server or agent’s secret storage. Never put them in the embed, a URL, public JSON or public JavaScript. Your reading list and notes are public; only editing is private.

Reference & troubleshooting

The shelf is not appearing

Open your JSON URL directly: it should return JSON, not a login page or your homepage. Check the script has type="module", that the host allows custom scripts, and that the book records use "reading" or "finished" for their status.

If the feed is on another domain, it must allow cross-origin reads with Access-Control-Allow-Origin. A restrictive Content Security Policy also needs to allow the component’s script, its stylesheet inside the component, the feed connection and any cover image hosts. The agent guide has the details.

Adding covers, progress and notes

cover is a public HTTPS image URL or a path such as /covers/my-book.jpg. url is an optional book link. Relative paths resolve against the feed URL. Leave unavailable covers and links empty.

progress is a number from 0 to 100, or null if you do not want to track it. note is an optional short public thought. Leave unknown dates as null; do not invent reading history.

I want to embed Lily’s shelf instead

This is a read-only view of the same shelf shown in the demo. It will show Lily’s books on your website, not your own.

<script type="module" src="https://lilygeidelberg.com/reading/reading-shelf.js"></script>
<reading-shelf collapsible src="https://lilygeidelberg.com/api/reading"></reading-shelf>