Skip to content
Stephanie Wilkinson edited this page May 12, 2026 · 2 revisions

Progressive Auth Implementation Guide

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.

The core technical change

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.

Implementation steps

Before starting, read the Constraints page — it covers RAM limits, rate limiting, and session TTL concerns that affect every step.

Foundation (Steps 1–2)

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

OAuth + Routes (Steps 3–4)

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

Views + Homepage (Steps 5–7)

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

Conversion Layer (Steps 8–9)

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)

Polish (Steps 10–13)

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

Execution order

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

What changes and what doesn't

See Changes Summary for a full breakdown of changed files, unchanged systems, and shared components.

Before you start

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.

Clone this wiki locally