Org chart
About org charts
An org chart (organizational chart) maps the formal reporting structure of an organization — who manages whom, which teams sit under which leaders, and where open roles and external advisors fit in. HR teams reach for them during headcount planning; founders use them before board meetings; operations managers circulate them when restructuring. Unlike a generic flowchart, an org chart treats people (and positions) as the primary entities, with the hierarchy encoded by indentation or explicit edges.
Schematex follows general org-chart conventions with extensions for open/unfilled positions, matrix (dotted-line) reporting, and assistant relationships. There is no single ISO standard for org charts; the conventions implemented here are drawn from HR practice and software-industry norms. For the authoritative academic background see Fayol (1916) and the Wikipedia article on org charts.
1. Your first org chart
The smallest useful org chart: a three-level hierarchy with one open role.
Four rules cover 80% of usage:
- Start with the keyword
orgchart, optionally followed by a quoted title. - Each person is a node —
id: "Name" | "Title" | "Department" [props]. The|separates the name, title, and department fields. - Indentation determines hierarchy — each extra two (or more) spaces moves a node one level deeper under the nearest less-indented node above it.
- Declare open roles with
open id:ordraft id:, and external advisors withadvisor id:.
Comments must start with
#on their own line (inline trailing//is also stripped).
2. Nodes
A node line has the form [kind] id: fields [props]. The id must match [A-Za-z][A-Za-z0-9_-]*.
2.1 Fields (pipe-separated)
The part after the : and before the optional [props] block is split on |:
alice: "Alice Zhang" # name only
alice: "Alice Zhang" | "VP Engineering" # name + title
alice: "Alice Zhang" | "VP Eng" | "Platform" # name + title + department
alice: "Alice Zhang" | "VP Eng" | "Platform" | "x@co.com" # + info line| Position | Content | Notes |
|---|---|---|
| 1st | Name | Quoted or unquoted |
| 2nd | Title / job level | Optional |
| 3rd | Department | Optional |
| 4th | Info line | Optional; also settable via note:, email:, phone:, location: props |
2.2 Node kinds
The optional kind keyword before the id changes how the node is rendered:
| Keyword(s) | Kind | Meaning |
|---|---|---|
| (none) | person | Regular person |
role, open | role | Open / unfilled position |
draft, tbh | draft | Planned position, not actively recruiting |
advisor, external | advisor | External advisor, board member, or contractor |
2.3 Node properties
Properties go in [key: value, …] at the end of a node line.
| Property | Values | Effect |
|---|---|---|
role: | see table below | Role icon displayed in the avatar |
icon: | same as role: | Alias for role: |
department: | text | Overrides the department field |
status: | new | leaving | on-leave | Status pill on the card |
avatar-color: | hex color (e.g. "#7B1FA2") | Avatar background color |
gender: | male | female | Avatar silhouette (used when no role icon is set) |
note: | text | Info line (first one wins) |
email: | text | Info line |
phone: | text | Info line |
location: | text | Info line |
assistant-of: | node id | Renders this node as an assistant to the named node |
matrix: | space- or comma-separated node ids | Adds dotted matrix lines from those nodes to this one |
reports: | node id | Explicit parent override (instead of indentation) |
open | (bare flag) | Marks node as open; equivalent to using role kind keyword |
draft or tbh | (bare flag) | Marks node as draft; equivalent to draft kind keyword |
external | (bare flag) | Marks node as external; equivalent to advisor kind keyword |
Role icons — the role: value resolves to a display icon. Accepted keywords (case-insensitive):
| Keywords | Icon |
|---|---|
ceo | CEO |
cto | CTO |
cfo | CFO |
coo | COO |
cmo | CMO |
cpo | CPO |
vp | VP |
engineer, engineering | Engineer |
designer, design | Designer |
sales | Sales |
hr | HR |
legal | Legal |
ops, operations | Ops |
marketing | Marketing |
product | Product |
data | Data |
advisor | Advisor |
intern | Intern |
vacant | Vacant |
3. Hierarchy
Hierarchy is expressed by indentation — the most common pattern. Each node becomes a child of the nearest node above it that has a smaller indent. Tabs are treated as two spaces.
ceo: "CEO"
cto: "CTO" # child of ceo (indent 2)
eng: "Engineer" # child of cto (indent 4)
cfo: "CFO" # child of ceo (indent 2, same level as cto)Alternatively, use the reports: property to set a parent explicitly regardless of indentation:
orgchart "Flat file"
ceo: "CEO"
cto: "CTO" [reports: ceo]
eng: "Engineer" [reports: cto]4. Edges
Two kinds of edges exist. Most reporting lines come from the indentation hierarchy automatically. You can also write them explicitly — or add matrix (dotted) lines.
| Operator | Edge kind | Meaning |
|---|---|---|
from -> to | report | Solid reporting line |
from -.-> to | matrix | Dotted matrix (indirect) reporting line |
Explicit edges require that both node ids are already declared. A report edge created explicitly is not duplicated if the same relationship is already implied by indentation.
Edge labels are supported:
pm1 -.-> design [label: "product partnership"]5. Configuration
config: lines adjust layout and orientation. Each goes on its own line.
| Config key | Values | Default | Effect |
|---|---|---|---|
direction | TD, LR | TD | Top-down or left-right flow |
layout | tree, list, directory, compact | tree | Visual layout mode |
Layout notes:
tree— standard hierarchical tree with branching connectors. Best for most org charts.list/directory/compact— compact indented directory view. Good for large headcount lists where tree branching becomes unwieldy.
Tree layout (default) — avatar cards with branching connectors and department color-coding. Best for teams up to ~30 people.
List layout — compact directory rows with indent guides. Best for large teams where tree branching becomes unwieldy.
6. Labels & comments
- Title:
orgchart "Acme Corp"— first line only. - Name field: first pipe-delimited field after the colon; may be quoted (
"Alice Zhang") or unquoted (Alice). - Title/department fields: second and third pipe-delimited fields.
- Info line: fourth pipe-delimited field, or set via
note:,email:,phone:, orlocation:props. First one encountered wins. - Comments:
#at the start of a line (after leading whitespace). Inline//is also stripped.
7. Reserved words & escaping
Reserved at line start: orgchart (header), config:, role, open, draft, tbh, advisor, external.
Reserved operator tokens — avoid these sequences inside ids: ->, -.->
ID rules: must match [A-Za-z][A-Za-z0-9_-]*. Names with spaces go in the quoted name field, not the id.
Strings with spaces in props values (e.g. department: "Platform Eng") must be double-quoted.
8. Common mistakes
| You wrote | Parser says | Fix |
|---|---|---|
alice: Alice Zhang (unquoted name with space) | Parses Alice as the name, Zhang is lost or misread | Quote the name: alice: "Alice Zhang" |
open1 open: "TBH" | open after the id is not a kind keyword; fails id regex | Kind keyword comes first: open open1: "TBH" |
alice -> bob before either node is declared | OrgchartParseError: Edge references unknown node | Declare nodes first, then write edges at the end |
config: direction = top-down | Unknown value ignored; direction stays TD | Use TD or LR |
config: layout = compact | Accepted — maps to list layout | Correct; compact, directory, and list all work |
alice [matrix: bob charlie] | Space-separated ids in matrix: — both are added | Also works with commas: matrix: "bob, charlie" |
Node id with a space: fe lead | Parser takes fe as the id; lead fails | Use underscore: fe_lead |
| Duplicate id | OrgchartParseError: Duplicate node id | Each node needs a unique id |
9. Grammar (EBNF)
document = header (blank | comment | config | edge | node)*
header = "orgchart" ( WS quoted-string )? NEWLINE
quoted-string = '"' any-char-but-quote* '"'
config = "config" WS ":" WS key WS "=" WS value NEWLINE
key = "direction" | "layout"
node = INDENT* kind? id ":" WS fields ( "[" node-attrs "]" )? NEWLINE
kind = "role" | "open" | "draft" | "tbh" | "advisor" | "external" | "person"
fields = field ( "|" field )*
field = quoted-string | unquoted-text
node-attrs = node-attr ("," node-attr)*
node-attr = "role:" role-keyword
| "icon:" role-keyword
| "department:" text
| "status:" ( "new" | "leaving" | "on-leave" )
| "avatar-color:" quoted-hex
| "gender:" ( "male" | "female" )
| "note:" text
| "email:" text
| "phone:" text
| "location:" text
| "assistant-of:" id
| "matrix:" id-list
| "reports:" id
| bare-flag
bare-flag = "open" | "draft" | "tbh" | "external"
edge = id WS edge-op WS id ( "[" edge-attrs "]" )? NEWLINE
edge-op = "->" | ".->" // -.-> for matrix
edge-attrs = "label:" quoted-string
id = [A-Za-z] [A-Za-z0-9_-]*
comment = ( "#" | "//" ) any NEWLINEAuthoritative source: src/diagrams/orgchart/parser.ts. If this diverges from the parser, the parser wins — please open an issue.
10. Roadmap
Planned — not yet parseable. Do not use these in generated DSL today; the parser will reject or ignore them.
assistant-of:visual rendering — the property is parsed and stored in the AST but the renderer does not yet draw the assistant elbow connector.- Config
coloring— department-based color themes (coloring: department). - Config
compactsize tiers — explicit card-size control (size: small | medium | large). span:node width — spanning a node across multiple sibling columns in tree layout.- Photo / avatar URL —
avatar: "https://…"to display a real headshot. - Export to HRIS formats — JSON/CSV structured output alongside the SVG.
Track in the GitHub issues if you need any of these sooner.