Type to search documentation...

How It Works

A look at Docit's architecture and how everything fits together under the hood.

The four-step pipeline

  1. Registerdoc_for (or use_docs) creates an Operation for each controller action and stores it in a global Registry.
  2. 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.
  3. Serve — The Engine serves the configured documentation UI (Scalar or Swagger) at /api-docs, pointing it at the generated spec.
  4. Map — The SystemGraph builds a local architecture graph for /api-docs/system, connecting routes, controllers, actions, docs, schemas, models, and source references.

Key components

ComponentRole
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

TypeWhat it represents
routeAn HTTP entrypoint — the URL pattern that browsers and clients hit. Includes the HTTP method.
controllerA Rails controller class. Groups the actions that respond to its routes.
actionA single controller method. Marked documented or undocumented based on whether you've written a doc_for block.
docA Docit documentation block. Pulled straight from your doc_for/use_docs definitions.
schemaA reusable schema defined with Docit.schema.
modelAn ActiveRecord model with its associations. Discovered at runtime.
service, job, mailerSource 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.