Reference

Components

Every DocsUI component — shown live where it makes sense, with its calling code and args.

Shell#

The whole HTML document you're looking at right now.

DocsUI::Shell is the top-level page: the topbar (brand + ThemeSwitcher), the Sidebar, the content column, and the auto TOC. It yields the page body. Page renders it for you — you rarely construct it directly.

DocsUI::Shell(title: "My guide", on_page: :panel) do
  # page body
end
ArgTypeDefaultDescription
titleString, nilnilDocument + topbar title. Falls back to the site brand.
on_pageSymbol, falsefalseTOC placement — :panel / :toggle / :sidebar / false.

Page#

The base class you subclass for every docs page — including this one.

Subclass DocsUI::Page, set title/eyebrow with the class-level DSL, and implement #content (and optionally #lead). The page wraps your content in the Shell with a Header masthead and auto TOC.

class Views::Docs::Pages::Guide < DocsUI::Page
  title   "My guide"
  eyebrow "Reference"
  on_page :toggle          # :panel | :toggle | :sidebar | false

  def lead = "One-sentence summary."
  def content = DocsUI::Section("Hello") { prose { p { "..." } } }
end
ArgTypeDefaultDescription
titleString (class DSL)Sets the document + masthead title.
eyebrowString (class DSL)nilSmall kicker above the h1 (e.g. the group).
on_pageSymbol (class DSL)config defaultTOC placement — :panel / :toggle / :sidebar / false.
#leadinstance methodnilMuted summary paragraph under the h1.
#contentinstance methodThe page body — call kit components here.

Section#

An anchored section wrapper — this description is its description: arg.

Every block on this page is a DocsUI::Section. It renders a <section id> with an <h2>, an optional muted description: lead, then your block. The id auto-slugs from the title (feeding the TOC), or pass id: to override it.

DocsUI::Section("Getting started", id: "start", description: "Read me first.") do
  prose { p { "Section body." } }
end
ArgTypeDefaultDescription
titleStringThe h2 text; auto-slugs into the anchor id.
idString, nilslug of titleOverride the section anchor.
descriptionString, callable, nilnilMuted lead paragraph under the h2.

Prose#

A typographic wrapper for hand-authored HTML.

Prose gives hand-authored text a consistent reading rhythm without a typography plugin.

  • lists,
  • inline code,
  • links — all styled.

The call that produced the block above:

prose do
  p { "Prose gives hand-authored text a consistent reading rhythm." }
  ul { li { "lists," }; li { "inline code," }; li { "links." } }
end
On a DocsUI::Page use the lowercase prose do … end helper — a method call, no parens needed. The kit form DocsUI::Prose() do … end also works, but bare DocsUI::Prose do is a SyntaxError, so it needs the empty ().
ArgTypeDefaultDescription
blockPhlex blockHand-authored HTML — p, ul/li, code, strong, a, plain text.

Code#

A Rouge-highlighted code block with an optional filename bar.

app/models/user.rb
class User < ApplicationRecord
  has_many :posts
end

The call that produced the block above:

DocsUI::Code(source, lexer: :ruby, filename: "app/models/user.rb")
ArgTypeDefaultDescription
sourceStringThe code to highlight.
lexerSymbolinferredAny Rouge language — :shell, :yaml, :erb, :python, :go, etc. Overrides the filename guess; ruby when neither is given.
filenameString, nilnilOptional filename bar above the block. Also selects the language (*.yml → yaml, Dockerfile → docker, *.sh → shell).

Example#

Multi-language tabbed code with a sticky, global language choice.

client.rb
Anthropic::Client.new.messages.create(model: "claude-opus-4-8", messages: msgs)
client.py
anthropic.Anthropic().messages.create(model="claude-opus-4-8", messages=msgs)

The call that produced the tabs above:

example do |ex|
  ex.code(:ruby, filename: "client.rb")   { ruby_source }
  ex.code(:python, filename: "client.py") { python_source }
end
ArgTypeDefaultDescription
blockPhlex blockYields an object with #code — one call per language.
ex.code langSymbolThe Rouge language for this tab.
ex.code filename:String, nilnilOptional filename bar for this tab.
ex.code lexer:SymbollangOverride the Rouge lexer if it differs from the tab label.

Table & PropTable#

Reference tables — generic headers+rows, and a name/type/default/description preset.

DocsUI::Table renders headers + rows in the kit's daisyUI look. A cell is a String (plain, escaped), a [:code, "x"] pair (inline <code>), or a [:md, "…"] pair (inline Markdown). DocsUI::PropTable is the preset every args table on this page uses — the same shape, first column auto code-styled, default Option/Type/Default/Description headers.

CellRenders as
brandplain, escaped text
%w[dark light]inline code
a bold noteinline markdown

The call that produced the table above:

DocsUI::Table(
  [ "Cell", "Renders as" ],
  [
    [ "brand", "plain, escaped text" ],
    [ [ :code, "%w[dark light]" ], "inline code" ],
    [ [ :md, "a **bold** note" ], "inline markdown" ]
  ]
)
Every args table on this page is a DocsUI::PropTable — pass just the rows; the headers default to Option/Type/Default/Description (override with headers:).
OptionTypeDefaultDescription
DocsUI::Table headersArrayHeader labels — one per column.
DocsUI::Table rowsArrayRows; each a cell array (String / [:code, x] / [:md, …]).
DocsUI::PropTable rowsArrayRows; the first cell is auto-wrapped in <code>.
DocsUI::PropTable headers:ArrayOption/Type/Default/DescriptionOverride the header labels.

Endpoint, FieldTable & ErrorTable#

The API-reference kit — a method+path line, a fields table, and an error table.

DocsUI::Endpoint renders an HTTP method badge (coloured per verb) plus a monospace path, inline — so it drops straight into a Section description. FieldTable and ErrorTable are keyword-schema presets over Table for an object's fields and an endpoint's errors.

Create a webhook endpoint#

POST /api/webhook_endpoints

Registers a destination URL for outbound event notifications.

NameTypeRequiredDescription
urlstringHTTPS destination URL.
descriptionstringOptional internal label.
eventsarrayEvent types, e.g. payment_link.paid.
ScenarioStatusTypeParam
Missing or invalid API key401authentication_error
Non-HTTPS URL422validation_errorurl
Unknown event name422validation_errorevents

The calls that produced the block above:

DocsUI::Section("Create a webhook endpoint",
  description: DocsUI::Endpoint.new(:post, "/api/webhook_endpoints")) do
  render DocsUI::FieldTable.new([
    { name: "url", type: "string", required: true, description: "HTTPS destination URL." },
    { name: "events", type: "array", required: true, description: [:md, "e.g. `payment_link.paid`."] }
  ])
  render DocsUI::ErrorTable.new([
    { scenario: "Non-HTTPS URL", status: "422", type: "validation_error", param: "url" }
  ])
end
Verb → colour is a frozen Hash of literal badge classes (GET → success, POST → primary, PATCH/PUT → warning, DELETE → error). An unknown verb renders a neutral badge — no raise.
CallTypeDefaultDescription
DocsUI::Endpoint.new(method, path)Symbol/String, StringMethod badge + monospace path; renders inline.
DocsUI::FieldTable.new(fields)Array<Hash>Each: { name:, type:, required: false, description: }.
DocsUI::ErrorTable.new(errors)Array<Hash>Each: { scenario:, status:, type:, param: nil }; Param column auto-hidden.
Section(description:)String, proc, or componentnilNow also accepts a Phlex component instance.

RequestExample & JsonResponse#

The API-docs kit — declare a request once, get every client tab; render a Ruby hash as a JSON response.

DocsUI::RequestExample turns one structured request declaration (method:/path:/body:) into a DocsUI::Example with one tab per configured client — curl, javascript, ruby, python by default (a site adds its own, e.g. a cli tab). DocsUI::JsonResponse renders a Ruby Hash as pretty-printed JSON — no hand-rolled deep_stringify.

The calls that produced the block above:

render DocsUI::RequestExample.new(
  method: :post,
  path: "/v1/payment_links",
  body: { amount: 4900, currency: "usd", description: "Pro plan" }
)
render DocsUI::JsonResponse.new(
  { id: "plink_1a2b3c", object: "payment_link", amount: 4900,
    currency: "usd", url: "https://pay.example.com/plink_1a2b3c", active: true }
)
The client set, base URL, and example auth header are config: c.api_clients (defaults + your overrides), c.api_base_url, and c.api_auth_header. Override a default token to swap in an SDK-flavored snippet; add a new token (e.g. cli) to append a tab.
CallTypeDefaultDescription
RequestExample method:/path:Symbol/String, StringThe HTTP verb and path (path is appended to c.api_base_url).
RequestExample body:Hash, nilnilRequest payload; deep-stringified into each snippet. Omit for a GET.
RequestExample query:/headers:Hash{}Query params and extra headers merged into every snippet.
RequestExample clients:Array<Symbol>, nilall configuredFilter/order the tabs (e.g. [:curl, :ruby]).
JsonResponse.new(body)Hash or StringHash → pretty JSON with string keys; String → passed through.
JsonResponse filename:String"response.json"The code block's title-bar filename.

Callout#

note / tip / warning — a daisyUI alert with a lucide icon.

This is a note callout.
A tip callout — for handy asides.
A warning callout — for gotchas.

The calls that produced the boxes above:

DocsUI::Callout(:note)    { "This is a note callout." }
DocsUI::Callout(:tip)     { "A tip callout." }
DocsUI::Callout(:warning) { "A warning callout." }
ArgTypeDefaultDescription
levelSymbol:noteAlert style — :note / :tip / :warning.
titleString, nilnilOptional heading above the body.
blockPhlex blockThe callout body.

Icon#

A lucide icon by name; extra attributes pass through.

The calls that produced the icons above:

DocsUI::Icon("rocket", class: "size-6")
DocsUI::Icon("book-open", class: "size-6")
DocsUI::Icon("paintbrush", class: "size-6")
Icons no-op gracefully if rails_icons isn't configured — nothing renders, no error.
ArgTypeDefaultDescription
nameStringThe lucide icon name, e.g. "rocket".
**attributesHash{}Extra HTML attributes (class:, etc.) passed to the icon.

OnThisPage#

The auto-TOC — the panel Shell renders from your on_page setting.

The TOC is built from the page's Section anchors. You don't construct it — Shell renders it based on the page's on_page setting. Set the mode per page or as a config default.

class Views::Docs::Pages::Api < DocsUI::Page
  on_page :toggle   # :panel | :toggle | :sidebar | false
end
ArgTypeDefaultDescription
modeSymbol:panelPlacement — :panel (aside) / :toggle (button) / :sidebar.
titleString"On this page"The TOC heading.

ThemeSwitcher#

The theme dropdown — built from your config, rendered by Shell.

The dropdown in the topbar is a DocsUI::ThemeSwitcher. It lists DocsKit.configuration.themes — which must match the daisyUI @plugin block in your Tailwind entry. Shell renders it for you.

config/initializers/docs_kit.rb
DocsKit.configure do |c|
  c.themes = %w[dark light synthwave dracula night]
end
ArgTypeDefaultDescription
(none)No args — reads DocsKit.configuration.themes.