LuauDocs has already found your exports, their signatures, and their types. Doc comments add the prose on top: you are not declaring what exists or restating an annotated type; you are explaining what something is for.
Write a comment block above a definition. All three formats are functionally identical and can be mixed freely in the same file:
luau
--[[Creates a state holding `initial`.See [State:Connect] for reacting to changes.]]function Flux.state<T>(initial: T?): State.State<T>
luau
--- Creates a state holding `initial`.--- See [State:Connect] for reacting to changes.function Flux.state<T>(initial: T?): State.State<T>
luau
--[=[Creates a state holding `initial`.Prose here can contain [[ and ]] freely.]=]function Flux.state<T>(initial: T?): State.State<T>
The description is markdown, so lists, links, fenced code, and emphasis all work. Everything beyond that is optional, including tags.
Paragraphs survive the trip:
examples/Flux/State.luau
luau
--[[Runs `callback` whenever the value changes.Returns a function that disconnects the listener again.]]function State:Connect(callback: (any) -> ()): () -> ()
Fields take prose the same way, either above the field or trailing it, whichever reads better in the source:
luau
export type Options = { --[[ How long to wait before giving up. ]] timeout: number, retries: number, -- how many attempts after the first}
On a table-literal member the prose renders as markdown, references included. A type declaration's fields render inside the type's code fence instead, so their prose becomes a -- comment line there: plain text, with links, bold, and code spans stripped. Keep those to a short phrase.
The module's own page takes a description the same way: a doc comment above the definition of the table you return, or at the very top of the file, before the first statement.
luau
--[[A tiny reactive state library.]]local Flux = {}
A bare name is looked up in your project first, then in any @external names you declared, then among Roblox names. The dotted and colon forms only ever resolve inside your project.
The example library writes see [State:Connect] for reacting to changes in a plain doc comment, and the generated entry carries the link.
A reference that resolves to nothing is left exactly as you typed it, unlinked, so a stale [OldName] shows up as plain text rather than a broken link. A module outranks a type sharing its name, so [Signal] means the Signal module even where a type Signal also exists. If a reference is ambiguous (such as two modules named Defaults), LuauDocs refuses to guess, links neither, and emits a diagnostic warning. Qualify it ([Module.State]) to fix that.
Home
Writing Doc Comments
LuauDocs has already found your exports, their signatures, and their types. Doc comments add the prose on top: you are not declaring what exists or restating an annotated type; you are explaining what something is for.
The three styles
Write a comment block above a definition. All three formats are functionally identical and can be mixed freely in the same file:
The description is markdown, so lists, links, fenced code, and emphasis all work. Everything beyond that is optional, including tags.
Paragraphs survive the trip:
ConnectRuns
callbackwhenever the value changes.Returns a function that disconnects the listener again.
Documenting fields
Fields take prose the same way, either above the field or trailing it, whichever reads better in the source:
On a table-literal member the prose renders as markdown, references included. A type declaration's fields render inside the type's code fence instead, so their prose becomes a
-- commentline there: plain text, with links, bold, and code spans stripped. Keep those to a short phrase.Documenting the module itself
The module's own page takes a description the same way: a doc comment above the definition of the table you return, or at the very top of the file, before the first statement.
That comment opens the example's Flux page. A
@classblock's prose does the same job for a class assembled by hand.References that link themselves
A name in square brackets becomes a link:
[Class][Class.member][Class:method][CFrame]A bare name is looked up in your project first, then in any
@externalnames you declared, then among Roblox names. The dotted and colon forms only ever resolve inside your project.The example library writes
see [State:Connect] for reacting to changesin a plain doc comment, and the generated entry carries the link.A reference that resolves to nothing is left exactly as you typed it, unlinked, so a stale
[OldName]shows up as plain text rather than a broken link. A module outranks a type sharing its name, so[Signal]means the Signal module even where atype Signalalso exists. If a reference is ambiguous (such as two modules namedDefaults), LuauDocs refuses to guess, links neither, and emits a diagnostic warning. Qualify it ([Module.State]) to fix that.More than prose
Doc comments render the same markdown as a hand-written guide page, which includes admonitions, tab strips, frames, badges, and inline
{luau}highlighting.When inference gets something wrong, or if you want a member placed somewhere other than where the code puts it, that is what tags are for.