Repository navigation
Home
Restructures Yonderbook's UX around progressive authentication. The homepage becomes a functional interface where visitors connect their Goodreads account via OAuth, pick a library, and see which want-to-read books are available — all without signing up. Accounts become about persistence (saving preferences, notifications, BookMooch sync), not about getting in the door.
Right now, the Goodreads OAuth callback (/login in app.rb) requires @user to exist and calls Goodreads.fetch_user(request_token, @user.id), which exchanges the OAuth token AND saves to the database in one operation. The anonymous flow needs to split these apart: exchange the token (always), save to the database (only if logged in). For anonymous users, the credentials live in the session cache until they create an account.
Before starting, read the Constraints page — it covers RAM limits, rate limiting, and session TTL concerns that affect every step.
| Step | Description | Files touched |
|---|---|---|
| Step 1: Split fetch_user | Extract exchange_token from fetch_user
|
lib/goodreads.rb, spec/lib/goodreads_spec.rb
|
| Step 2: Session credential helpers | Add helpers for session-based Goodreads credentials | lib/route_helpers.rb |
| Step | Description | Files touched |
|---|---|---|
| Step 3: Anonymous OAuth callback | New /search-callback route for anonymous OAuth |
app.rb |
| Step 4: Anonymous search routes | Full /search/* route tree mirroring authenticated flow |
app.rb |
| Step | Description | Files touched |
|---|---|---|
| Step 5: New homepage | Replace welcome page with search tool interface | views/search.erb |
| Step 6: Shelf and library picker views | Anonymous variants of shelf/library picker views |
views/search/*.erb, views/shelves/overdrive.erb
|
| Step 7: Update root route | Serve search interface at / for anonymous visitors |
app.rb |
| Step | Description | Files touched |
|---|---|---|
| Step 8: Signup prompts | Contextual signup, email capture, and analytics teaser | views/availability.erb |
| Step 9: Credential migration | Migrate session Goodreads credentials on account creation |
app.rb (Rodauth config) |
| Step | Description | Files touched |
|---|---|---|
| Step 10: Navigation update | Conditional nav for anonymous vs authenticated | views/layout.erb |
| Step 11: Loading state | Background async fetch with loading/polling UI |
app.rb, lib/route_helpers.rb, views/search/loading.erb
|
| Step 12: SEO meta tags | Keyword-targeted titles, descriptions, robots directives |
views/search.erb, views/layout.erb
|
| Step 13: Integration specs | Full integration test suite for anonymous flow | spec/web/anonymous_search_spec.rb |
Minimum viable version: Steps 1–7 + rate limiting. That gets anonymous search working with Goodreads OAuth from the homepage. Everything after is conversion optimization and robustness.
- Foundation (Steps 1–2): ~45 min
-
OAuth + routes (Steps 3–4): ~2–3 hours. Add rate limiting (
Rack::Attack) as part of this step. - Views + homepage swap (Steps 5–7): ~2 hours. After this, anonymous search works end to end.
- Conversion layer (Steps 8–9): ~1.5 hours
- Polish (Steps 10–13): ~2 hours
See Changes Summary for a full breakdown of changed files, unchanged systems, and shared components.
cd ~/code/yonderbook
claude
Orient Claude Code with this context message:
This is Yonderbook, a Ruby/Roda app. All routing is in app.rb (there
is no routes/ directory). Views: ERB in views/. Core modules:
lib/goodreads.rb (Goodreads API + OAuth), lib/overdrive.rb (library
availability), lib/cache.rb (TupleSpace session cache),
lib/route_helpers.rb (shared helpers), lib/auth.rb (OAuth consumer).
Auth: Rodauth (accounts, sessions, password reset, email auth). The
session uses Roda's sessions plugin keyed by session['session_id'].
Hosted on Render with 512MB RAM — memory efficiency matters.