Roam is an outliner: use the graph — short blocks, nesting, and links — rather than dumping flat prose. Every example below is shown in code so it stays literal; type it without the backticks to make it live.
Every example is shown in code so it stays literal — type it without the backticks to make it live.
- A page is a tree of blocks (one bullet = one block); the block tree is the data model.
- Roam also renders the tree through view types (document / bullet / numbered) and components (
{{[[kanban]]}},{{[[table]]}},{{diagram}},{{[[mermaid]]}}) — the tree is the substrate, not the only shape.
- Roam also renders the tree through view types (document / bullet / numbered) and components (
- Escape rule — when documenting markup, wrap every example in
inline codeor a fenced block. Bare[[refs]],#tags,{{[[TODO]]}},Name::, and[[>]] [[!TIP]]render LIVE and create stray pages, backlinks, checkboxes, and attributes. - Soft line break — Shift+Enter keeps text in the same block (no new bullet); this is how a pipe-separated tag-footer row sits under a block.
- Page reference
[[Page Name]]- Bidirectional link (type
[[to insert); creates the page if absent and collects backlinks in its Linked References. - Plain-text mentions of a page's name appear under its Unlinked References, where you can link them in one click.
- Multi-word names are fine.
- Bidirectional link (type
- Block reference
((uid))- Points to one block; its text renders inline.
[[finds pages,((finds blocks. - uids are usually 9 chars but can be any length (imported uids vary); preserve them, never invent duplicates (collisions fail import).
- Points to one block; its text renders inline.
- Tag
#tag/#[[multi word]]- A page reference styled as a grey tag; conventionally placed at the start or end of a block.
- Alias
[label]([[Page]])/[label](((uid)))/[label](https://url)- Custom display text over a page, block, or URL (default block-alias text is
*). Cmd/Ctrl+kturns selected text into an alias; hover an alias to preview the target.
- Custom display text over a page, block, or URL (default block-alias text is
- Bold
**text**. Italics__text__— double-underscore is ITALICS in Roam, not bold. Highlight^^text^^. Strikethrough~~text~~. - Headings
#/##/###(H1–H3 only); a heading is still a block and can carry children and refs. - Inline
code(single backticks); fenced code block with a language tag (javascript,css,clojure) held in one block (/code block). - Math
$$KaTeX$$— can compose inner$$...$$from child blocks. - Blockquote — start a block with
>(>then a space). - Image
or/upload.---on its own block is a horizontal rule. Blocks can be left/center/right/justified.
((uid))references one block (text renders inline). An embed renders a live, editable COPY — distinct concepts; do not conflate.- Create a ref — right-click the bullet → Copy Block Ref, or Alt-drag a block, or type
((. Navigate withCtrl-o(jump) /Ctrl-Shift-o(sidebar). - Context-menu "Replace With" modes
text— dead copy, link severed.embed— live portal; edits propagate.original— moves the canonical block here, leaving a ref behind.alias— hyperlink.text and alias— text + back-pointer; best for drafting.- Plus "Apply Children" as text or as references.
- Embed variants
{{embed: ((uid))}}— the block plus its children.{{embed-children: ((uid))}}— children only.{{embed-path: ((uid))}}— with a clickable breadcrumb path.
- Styled blockquotes with a type icon and color.
- Create with
[[>]] [[!NOTE]](canonical) or> [!NOTE];/Calloutinserts one; click the icon to change type. - Title = first line; body = next line via Shift+Enter (same block).
- Foldable — append
+(expanded) or-(collapsed) to the type, e.g.[[!TIP]]+; click the header to toggle. Works in heading blocks too. - 12 types: NOTE INFO SUMMARY TIP SUCCESS QUESTION WARNING FAILURE DANGER BUG EXAMPLE QUOTE.
- Aliases: tldr/abstract, hint/important, check/done, help/faq, caution/attention, fail/missing, error, cite.
- Custom type → "note" styling +
.rm-callout--{type}class +--callout-color/--callout-bgvars (style via a{{[[roam/css]]}}block).
Every example is shown in code so it stays literal — type it without the backticks to make it live.
- Invoke via
/nameor by typing{{[[name]]: arg}}. - Video
{{[[video]]: url}}— YouTube / Vimeo / Loom (paste a URL and click play to auto-convert)./video. - Table
{{[[table]]}}- Renders nested children as a grid: each first-level child is a row, and each deeper level within it is the next cell across (columns), so the first row reads as headers.
- Cells can hold rich blocks ("complex cells") and columns are sortable.
- Example (nesting depth = columns; first row reads as headers):
{{[[table]]}} - Action - QWERTY - Colemak - Select Block Up - k - h
- Kanban
{{[[kanban]]}}- 1st-level children = columns (can be
[[page]]refs); their children = cards; deeper nesting = card detail. - Cards are directly editable; Enter splits a card; drag-and-drop moves cards and rewrites the nesting; the board can be opened in the sidebar.
- 1st-level children = columns (can be
- Mermaid
{{[[mermaid]]}}- Diagram source in child blocks; the first child sets the type, and any diagram mermaid.js supports works (flowchart, sequenceDiagram, gantt, stateDiagram-v2, and so on).
- Per-diagram theme: first line
%%{init: {"theme":"forest"}}%%. Graph-wide theme: a{{[[roam/css]]}}block setting--mermaidjs-theme(reload required).
- Diagram
{{diagram: Title}}— a 2D canvas; every node IS a real block and appears in that block's references (not canvas-only); nodes can be images or{{[[video]]}}. Has a legacy version. - Mentions
{{[[mentions]]: [[Page]]}}— inlines a page's linked + unlinked references (/mentions);{{children-mentions: [[Page]]}}inlines the children of those mentions. - Calc
{{calc: 4 + 5}}— block-ref args scrape the FIRST number from the referenced block (3from "My 3 apples"):{{calc: ((uid)) + ((uid))}}. - roam/render
{{roam/render: ((codeUid))}}— renders a referenced code block as a component (some take extra arg refs). JS/JSX must be ES5 (noconst/imports/exports); full component docs live in Roam's dev graph. - roam/css
{{[[roam/css]]}}— a child fencedcssblock applies graph-wide styling. iframe{{iframe: https://url}}embeds a live webpage. - Hiccup — a block starting with
:hiccuprenders a Clojure/Hiccup vector as HTML, e.g.:hiccup [:iframe {:width "600" :height "400" :src "https://..."}]. (Real Roam feature, but NOT in the help-graph export — verify against Roam's dev docs before relying.) - More components
{{[[video-timestamp]]: ((videoUid)) HH:MM:SS}}—/video timestamporCmd/Ctrl+Alt+tunder a video; newer ones embed a ref to the video so they stay linked, older bare ones still work but do not auto-update.{{character-count}}/{{word-count}}— slash-inserted; count the containing block, not the page; word-count also sorts in All Pages.{{date}}—/datecalendar that inserts a date-page ref.{{encrypt:CIPHERTEXT}}— a password-protected block; password unrecoverable and exports/backups are NOT encrypted; not graph-wide encryption.{{[[streak]]: [[Goal]]}}— heatmap of how often a ref appears in daily notes; also takes query logic, e.g.{{[[streak]]: {or: [[DONE]] [[Solutions]]}}}.{{[[slider]]}}(or/→ Slider) — an inline rating control for polls; on Multiplayer graphs others can click to add their rating; used as an attribute value likecertainty:: {{[[slider]]}}or in templates, and its state is captured/re-applied by templates.
Every example is shown in code so it stays literal — type it without the backticks to make it live.
- Form
{{query: {and: [[A]] {not: [[B]]}}}}(the{{[[query]]: ...}}form also renders;/queryinserts). - Clauses
{and:}/{or:}match a block (or its parent) containing the refs;{not:}excludes; operands can mix[[page refs]]and((block refs)).{search: text}is a sub-clause nested inside{and:}/{or:}, never standalone; multiple can combine, e.g.{{query: {and: {search: June} {search: mobile}}}}.{between: [[start]] [[end]]}works on Daily Notes pages ONLY; accepts[[today]][[tomorrow]][[yesterday]][[last week]][[next week]][[last month]][[next month]].{created-by: [[User]]},{edited-by: [[User]]},{by: [[User]]}.
- Queries also have UI controls for sorting and filtering, plus a "Nest under parent results" display option.
- A
:qblock, written inline after:q(optionally with a quoted title) OR with a fencedclojure[:find ... :where ...]query.- A scalar find (
(count ?b) .) shows inline; a relation renders as a table; a var whose name containsuidrenders as a clickable block/page view.
- A scalar find (
- Special symbols
current/*— page/block id, uid, title;main-window-*variants for sidebar queries that auto-refresh when the main window changes.ms/*— millisecond bounds for:create/time/:edit/time; offsets likems/+1M-start, absolutems/=2025-01-01-start(notems/+1W-endis notms/+7D-end).dnp/*— resolve to a daily-note page-title STRING, not a timestamp (e.g.dnp/today,dnp/=2025-01-01).
- Inbuilt rules (custom rules NOT supported):
(created-by)(edited-by)(by)(refs-page)(block-or-parent-refs-page)(created-between)(edited-between)(in-dnp-between)(refs-dnp-between)(in-or-refs-dnp-between)(in-dnp)(refs-dnp)(in-or-refs-dnp). - Works via the frontend
window.roamAlphaAPI.data.q; the backend/api/graph/{name}/qdoes NOT support these additions. - Raw datascript schema (what
:whereclauses match): pages have:node/title; blocks have:block/string(text),:block/uid,:block/order(position under parent),:block/page,:block/children(immediate),:block/parents(all ancestors),:block/refs(outgoing refs),:block/heading(1–3),:block/text-align,:children/view-type(bullet/document/numbered); both carry:create/time/:edit/time(epoch ms) and:create/email/:edit/email(the attribution behindcreated-by/edited-by). Pull a tree:[:find (pull ?e [* {:block/children [*]}]) :where [?e :node/title "Page"]].
Every example is shown in code so it stays literal — type it without the backticks to make it live.
Name:: value(double colon) creates a queryable attribute page; a single:or**bold:**does not. Values can be text,[[page]],#tag, embeds, or child blocks.- The help graph uses empty-value attributes as section labels (
## Community Videos::,Articles::,Key Commands::) — a convention, not required syntax. - A page-level
Type:: #TypeNameattribute (multi-type allowed, e.g.Type:: #Project #Blog) shows a chip by the page title that opens a typed-fields sidebar panel. - The attribute-table macro
{{=: ...}}is barely documented — verify before relying on it.
- Any
#.classnameadds that CSS class to the block; Tailwind + Blueprint ship built in (#.bg-blue-500,#.text-xl,#.bp3-card). #.rm-E— shows immediate children inline (first level only; re-tag to go deeper).#.rm-g— hides the container and promotes children up one level (use[[.rm-g]]to keep it visible).#.rm-hide— collapses the block to a thin bar until clicked open (for hiding metadata)..rm-gridis NOT a documented class.
Every example is shown in code so it stays literal — type it without the backticks to make it live.
- Date pages use Roam's English ordinal format, e.g.
[[February 8th, 2021]],[[January 1st, 2021]].[[today]]resolves dynamically;/dateor{{date}}inserts a date. - Date pages are normal pages; blocks written on or referencing them are found via linked references and date queries. Daily Notes are Roam's default landing page and primary capture surface.
- A few heading blocks (often
[[refs]]) with content nested under;---divides sections. - The help graph's "card" idiom (a help-graph convention, not a universal rule):
### Title by [[Author]]→ a child media/link → a soft-break footer row of#[[topic]]tags. - Reuse with
((refs))/{{embed:}}when identity or edit-propagation matters; copy text when you want an independent copy.
"Multiplayer" is a concept cluster — sharing, roles, attribution, comments, reactions, versions — and most of those features never use the word.
- Sharing & roles: a graph can be shared read-only, publicly editable, or with specific emails as readers/editors, by URL or email (three-dot menu → Share; a person needs a Roam account first). Your own MCP token also carries an access level (read-only / read-append / full) that caps what you can write.
- Attribution: every block records who created and last edited it (queryable via the
created-by/edited-by/{by:}rules). An agent writes as a distinct user — the "AI user", surfaced asaiUserDisplayNamebyget_graph_guidelines— so its writes are attributed and visible to collaborators like any other user's. - Shared-graph mechanics: edits and deletions are visible to every collaborator, and Roam's undo does not reliably reverse bulk or API-driven changes. A block can hold multiple drafts/versions (
Ctrl/Cmd+,). - Comments are a separate thread on a block (
add_comment/get_comments), distinct from child blocks. Reactions are emoji on a block.{{[[slider]]}}lets collaborators rate/vote.
For feature details, recent changes, and the API, Roam's documentation lives in two public graphs you can open and search like any other graph:
- Help — https://roamresearch.com/#/app/help (features, FAQ, and a detailed changelog)
- Developer documentation — https://roamresearch.com/#/app/developer-documentation (the backend API and extension development)