A fast, mobile-friendly documentation browser for the Ruby standard library and Ruby itself. Imports the official Ruby source via RDoc, indexes the result in OpenSearch, and serves polished, search-driven pages for developers who arrive mid-task and need an answer in seconds.
bin/setup— install deps, copydatabase.yml.sample, prepare DB, start dev serverbin/dev— start the Rails dev server on port 3000bin/rails test— run tests (Minitest, fixtures-based; requires PostgreSQL + OpenSearch)bin/rails test path/to/test_file.rb— run a single test filebin/rubocop— lint with RuboCop (rubocop-rails-omakase config)bin/ci— full CI suite (rubocop, bundler-audit, importmap audit, brakeman, tests, seed replant)bin/rails import:ruby[3.4]— import documentation for a specific Ruby versiondocker compose up -d— start PostgreSQL 17 + OpenSearch 2.11. Canonical local setup; running them via Homebrew services also works if you already do that.
- Rails 8.1 (Ruby 3.4.2) — no ActionMailer, ActionCable, ActiveStorage, or ActionText
- Database: PostgreSQL with 3 logical databases (primary, cache via SolidCache, queue via SolidQueue). Migrations:
db/migrate/,db/cache_migrate/,db/queue_migrate/ - Search: OpenSearch via Searchkick. Indexed models:
RubyObject,RubyMethod,RubyConstant - Background jobs: SolidQueue (runs in Puma process in production via
SOLID_QUEUE_IN_PUMA=true) - Assets: Propshaft + importmap-rails + TailwindCSS (tailwindcss-rails)
- Frontend: Stimulus controllers, no React/Vue
- Config:
anyway_configgem, config classes inconfig/configs/, YAML inconfig/ruby.ymlandconfig/theme.yml - Deployment: Kamal to AWS ECR. Production uses Thruster (HTTP/2, asset caching) wrapping Puma
RubyRelease— version records for each Ruby releaseRubyObject— classes/modules, polymorphic viadocumentableassociation toRubyReleaseRubyMethod,RubyConstant,RubyAttribute,RubyPage— belong toRubyObject
Entry point: bin/rails import:ruby[<version>] (e.g. import:ruby[3.4]). All code lives in lib/:
RubyDownloader— fetches and extracts the Ruby source tarball for the targetRubyRelease.RubyDocumentationImporter— orchestrator. Calls the downloader, then runs RDoc against the extracted source withRubyAPIRDocGeneratoras a custom generator. Wrapped in a transaction that wipes prior records for that release.RubyAPIRDocGenerator(lib/rubyapi_rdoc_generator.rb) — writes the parsed RDoc tree intoRubyObject/RubyMethod/RubyConstant/RubyAttribute/RubyPagerecords.
config/database.ymlis not committed —bin/setupcopies fromconfig/database.yml.sample- OpenSearch & PostgreSQL must be running for tests — Rails tests hit a real DB, and
test_helper.rbreindexes searchable models in setup before disabling Searchkick callbacks Currentthread-local state (Current.theme,Current.ruby_release,Current.default_ruby_release) is set per-request- RuboCop config lives in
.rubocop.yml(inherits fromrubocop-rails-omakase); usebin/rubocop -ato autocorrect - Routes use optional
(:version)parameter matchingX.Yordev RubyObjectusescallbacks: :asyncfor Searchkick, so index updates go through SolidQueue
OPENSEARCH_URL— OpenSearch connectionDATABASE_URL,CACHE_DATABASE_URL,QUEUE_DATABASE_URL— PostgreSQL connectionsRAILS_MASTER_KEY— credentials decryptionSOLID_QUEUE_IN_PUMA— run SolidQueue in Puma process (production)
Ruby developers across all experience levels — from beginners learning the standard library to experts looking up a specific method signature. Primary context: they arrive with intent, often mid-task, and need to find and read an API in seconds. Frequently on mobile or a slow connection. The existing Ruby docs ecosystem (ruby-doc.org, legacy RDoc output) is the baseline this project exists to improve on.
Technical but polished. Three words: precise, calm, crafted. The interface should feel like a serious developer tool — quietly confident, fast, and considered — not loud, not marketing-y, not chatty. The Ruby-red accent (#e1175a) anchors identity, but expression comes from typography, spacing, and restraint rather than decoration.
Refined technical. Crisp type, a tight and consistent spacing scale, subtle depth where it aids scanability, and generous room for prose and code to breathe. Light + dark + system themes are first-class; both must feel native, not like one is an afterthought. Code samples are prominent and carry a distinct, legible palette.
References (aim for this feel): MDN, Stripe docs (typography, structure, technical clarity); Dash / DevDocs (speed, keyboard-driven, instant search).
Anti-references (do not look like): legacy ruby-doc.org / raw RDoc output (dated, hard to scan, poor on mobile); marketing/SaaS landing pages (hero gradients, stock illustrations, flashy animation).
- Content leads, chrome recedes. Docs are the product. UI earns its pixels by making docs easier to find, scan, or read — otherwise it disappears.
- Fast perceptually, not just technically. Layouts must not jank on load; interactions should feel instant. Prefer small, cache-friendly pages over clever spinners.
- Mobile and desktop are equal first-class surfaces. Every change gets checked at narrow widths. Touch targets, readable line lengths, and reachable controls are non-negotiable.
- Light and dark parity. Both themes get the same polish. No mode should ship with lower-contrast type, misaligned borders, or unreadable code colors.
- WCAG 2.1 AA, reduced-motion aware. AA contrast in both themes, keyboard navigation, proper semantics and labels, respect
prefers-reduced-motion. Motion is opt-in utility, never decoration. - Restraint over flourish. When a decision is close, pick the quieter option. New visual ideas need a reason tied to a user task, not novelty.