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
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.
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.+
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
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
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
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.+
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
Track exploration
A separate set marks items watched, read or listened to. Board statistics reflect the actual saved and explored state.
dist/app.js
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
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.
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.