How It Works
A look at Docit's architecture and how everything fits together under the hood.
The four-step pipeline
- Register —
doc_for(oruse_docs) creates an Operation for each controller action and stores it in a global Registry. - Generate — When someone visits
/api-docs/spec, Docit's SchemaGenerator combines all registered operations with your Rails routes (via RouteInspector) to produce an OpenAPI 3.0.3 JSON document. - Serve — The Engine serves the configured documentation UI (Scalar or Swagger)
at
/api-docs, pointing it at the generated spec. - Map — The SystemGraph builds a local architecture graph for
/api-docs/system, connecting routes, controllers, actions, docs, schemas, models, and source references.
Key components
| Component | Role |
|---|---|
Docit::DSL | The module that provides doc_for and use_docs to controllers. Auto-included via Engine initializer. |
Docit::Operation | Represents the documentation for a single controller action. It's the DSL receiver — when you call summary, tags, etc., you're calling methods on an Operation instance. |
Docit::Registry | Global store of all registered operations, keyed by controller name + action name. |
Docit::RouteInspector | Introspects Rails routes to find the HTTP method and path for each controller action. |
Docit::SchemaGenerator | Combines operations, routes, and configuration into a complete OpenAPI 3.0.3 spec hash. |
Docit::DocFile | Module mixin for separate doc files. Provides the doc method that delegates to doc_for. |
Docit::Engine | Rails Engine that mounts the UI controller, auto-includes the DSL, and serves assets. |
Docit::SystemGraph | Builds the local system map used by /api-docs/system and /api-docs/system.json. |
The System Architecture page
Visit /api-docs/system for an interactive map of your entire Rails application. It's built
from the same data Docit already collects — routes, controllers, models, services, jobs, mailers, schemas,
and your doc_for blocks — visualised as a draggable, zoomable diagram.
What you can do on it
- Inspect — Click any node to see what it is, the file it lives in, and which other nodes it connects to.
- Rearrange — Drag nodes to lay the system out the way you think about it. Drag empty canvas to pan; scroll to zoom.
- Connect — Use Connect mode to manually link two nodes — useful for relationships Docit can't statically detect.
- Explain with AI — Pick the controllers, endpoints, models or services you care about and let Docit produce a beginner-friendly walkthrough of how they work together.
- Export — Save a high-resolution PNG of the current view for design docs, RFCs, or onboarding decks.
Node types
| Type | What it represents |
|---|---|
| route | An HTTP entrypoint — the URL pattern that browsers and clients hit. Includes the HTTP method. |
| controller | A Rails controller class. Groups the actions that respond to its routes. |
| action | A single controller method. Marked documented or undocumented based on whether you've written a doc_for block. |
| doc | A Docit documentation block. Pulled straight from your doc_for/use_docs definitions. |
| schema | A reusable schema defined with Docit.schema. |
| model | An ActiveRecord model with its associations. Discovered at runtime. |
| service, job, mailer | Source nodes scanned from app/services, app/jobs, and app/mailers. |
How AI Explain works
Click AI Explain in the toolbar. The side panel switches to a node picker grouped by type. As you tick controllers, actions, models, or services, the diagram dims everything except your selection and its direct neighbours — so you see exactly the slice you're investigating. Hit Generate Explanation and Docit sends a compact subgraph to your configured AI provider along with a prompt structured for junior engineers. You get back a Markdown-formatted explanation: overview, step-by-step request flow, component breakdown, relationships, things to watch out for, and a Mermaid flowchart of the selected area.
Run rails generate docit:ai_setup first to configure an AI provider (OpenAI, Anthropic, or Groq).
Configuration
# config/initializers/docit.rb
Docit.configure do |config|
config.system_graph_enabled = true # default: true
config.system_graph_excluded_paths = [
"app/controllers/admin", # paths to skip during analysis
"app/services/legacy"
]
end Auto-inclusion
You never need to manually include Docit::DSL in your controllers. The Engine has an initializer
that automatically includes it in ActionController::API and ActionController::Base
when Rails loads.
Route introspection
Docit needs to know the HTTP method and path for each documented action. It uses RouteInspector
to query the Rails router at spec-generation time. In development, it eager-loads the app first to ensure
all routes are available.
Spec generation flow
# Simplified flow when GET /api-docs/spec is hit:
spec = {
openapi: "3.0.3",
info: { title, version, description, license, contact, termsOfService },
servers: [...],
tags: [...],
paths: {},
components: { securitySchemes: {...}, schemas: {...} }
}
Registry.all.each do |operation|
routes = RouteInspector.routes_for(operation.controller, operation.action)
routes.each do |route|
spec[:paths][route[:path]][route[:method]] = build_operation(operation)
end
end Operation ID generation
Every endpoint gets an operationId in the spec. If you set one explicitly with
operation_id "myCustomId", that's used. Otherwise, Docit auto-generates one from the
action and controller name: index_users, create_auth, etc.