Loading...
ServicesWorkApparelStudioMoremiFuturecraftBlogContactStart Your Order
← All work
CASE STUDY / API orchestration / interaction design

RabbitHole.

Follow what you love across culture.

A favourite film often leads to a book, an album or another story with the same feeling. RabbitHole turns that instinct into a product: choose what you liked, follow a theme across catalogues and save the discoveries in your own named universe.

ROLE

Product concept · Art direction · Front-end development

Try RabbitHole ↗
RabbitHole: A starting point for curiosity
A starting point for curiosityThe featured thread introduces a theme while the catalogue separates Watch, Read and Listen.
01 / THE PROBLEM

Your taste crosses categories.
Most search tools don’t.

Most recommendation lists stop at a media category. People have a feeling or a specific favourite in mind, then have to search separate film, book and music services to continue exploring.

Who it’s for

Curious readers, film lovers and music listeners looking for connected discoveries rather than another isolated list.

What shaped the build

The initial experience should work without accounts or a database. Independent APIs have different formats, availability and artwork coverage, so one failed provider must not empty the whole interface.

02 / The decisionsWhat changed, and why
01

Ask what someone loved.

The soundtrack, visual world and story of a film point to different kinds of discovery.

A taste-choice dialog narrows theme and catalogue queries. Results explain whether the connection is editorial, thematic or a metadata match.

02

Make collecting feel personal.

A generic favourites list is easy to forget; a named collection gives people a reason to return and share.

Save a universe locally, mark items watched/read/listened, calculate exploration progress and export a 1080 × 1350 canvas taste card.

03

A failed cover should still look intentional.

Cross-provider results have uneven artwork, and cultural discovery depends on a readable visual rhythm.

Provider-host image validation and original typographic cover fallbacks preserve titles and hierarchy. Featured threads use manual, swipe and keyboard controls.

RabbitHole: The connection behind the pick
The connection behind the pickA result’s detail explains its source and provides a path into the next discovery.
03 / THE HARD PART

Different providers should not dictate the product’s reliability.

A film request can fail while book results succeed. Meanwhile, someone can submit another search before the first one returns.

I used allSettled for partial success, request generations for stale-response protection, in-memory caching and provider adapters that reduce different payloads to one view model.

Inside
the build.

Implementation details from the existing portfolio case study. Expand the parts you want to explore.

Catalogue searchFour independent requests. One readable result set.
  1. Start a query

    Bound and clean the input, create a request generation and show loading feedback. A short client-side pacing window reduces accidental repeated searches.

    dist/app.js
  2. Fan out

    Search Open Library books, TVmaze television, Apple movies and Apple albums concurrently with Promise.allSettled. Requests have timeouts; Apple uses a cleaned-up JSONP callback.

    dist/app.js
  3. Normalise

    Provider-specific adapters produce a shared record with ID, title, creator, type, source, artwork, URL and a connection reason. Results are interleaved and deduplicated by ID.

    dist/app.js
  4. Render what survived

    Discard stale generations so an older response cannot overwrite the current query. Cache successful requests and show partial results with an explicit unavailable-source message.

    dist/app.js
Save & shareA universe can travel without a user account.
  1. Collect locally

    Save up to 60 normalised discoveries in local storage. Item state and a bounded custom name persist on this browser.

    dist/app.js
  2. Track exploration

    A separate set marks items watched, read or listened to. Board statistics reflect the actual saved and explored state.

    dist/app.js
  3. Share a snapshot

    Serialize up to 30 saved items into a UTF-8/base64 URL fragment. The recipient receives a snapshot, not a live collaborative board.

    dist/app.js
  4. Validate the import

    Incoming records are length-bounded and normalised. Provider links and images are allowlisted, and provider text is escaped before rendering.

    tests/functional.cjs
Tools & connectionsWhat connects to what

Open Library

Book search, authors, subject metadata and covers.

The adapter requests a small field set and produces the common discovery record.

TVmaze

Television search and show metadata.

HTML summaries are stripped; source links and image hosts are validated.

Apple Search API

Movie and album discovery via JSONP.

Unique callback names, script cleanup and timeouts handle the transport; the current query uses the US storefront.

Firecrawl

A server-side companion-source route for featured titles.

Allowlisted seed IDs constrain searches. The route returns up to three HTTPS links with CDN caching and a safe unavailable response.

Browser APIs

Local storage, Canvas export, Web Share and clipboard.

No account or cloud board sync. Shared links expose their snapshot to people who receive them.

Quality & limitsWhat was checked, and what remains

Functional checks cover the real interaction code.

The test suite executes app.js in a simulated browser environment and checks saving, removal, filtering, taste-card drawing, board progress and snapshot sharing/import.

Failure and hostile inputs are exercised.

Tests cover partial API failure, rejected javascript links, disallowed image hosts, length limits and escaped provider text. These checks are not a substitute for a full browser visual suite.

The recommendation claim stays precise.

Current connections use editorial themes, a person’s chosen facet and catalogue metadata. There is no embedding recommender or trained personalisation model in the audited repository.

JavaScriptOpen LibraryTVmazeApple Search APIFirecrawl API routeCanvasLocal storage
04 / THE RESULT

A working product.
A clear next step.

The live product offers cross-media discovery, local collecting and shareable taste cards. The audited repository uses lightweight browser JavaScript, not a React application. The portfolio case study uses React and Motion; that presentation stack is separate from the product’s implementation.

What comes next

Measure whether visitors follow a thread, save a result and return to their collection. Validate the quality of theme matches and Apple result coverage before adding account sync or a more complex recommendation model.

Explore RabbitHole ↗

Adapted from Miracle’s portfolio case study. The source audit describes the build at commit 0dea117; it is not a claim that every integration is currently enabled.

NEXT CASE STUDY

Party Crashers ↗

From scattered flyers to a useful plan.

Something similar in mind?

Bring the goal. We’ll work out the right scope.

Start a project ↗