Panels
Explanation
The Panels Application turns a wiki page carrying a Panels.PanelClass xobject into a UI extension, and the skin templates ask for those extensions when they draw the columns beside the content. Nothing about a Panel is hard-coded: a Panel is a document, and its position is a preference.
The manager is what makes the order predictable: it collects every UIExtension registered on platform.panels, keeps those whose document is named in the preference, and then sorts them back into the order the preference lists them in. So a Panel's position comes from the configuration string and never from the order the components happened to register in.
While a Panel renders, the Panel's own document is bound to $paneldoc and $doc still refers to the page the Panel is displayed on. This is deliberate, and it is what lets a Panel test where it is being shown. The values a Panel's content may rely on are listed in Panel Content Macros and Variables.
A Panel is rendered through the asynchronous renderer, so the "Asynchronous rendering", "Cached" and "Context elements" properties of Panels.PanelClass are the ones inherited from the async class rather than anything specific to Panels. The cache key is built from the context elements the Panel declares.
FAQ
Can a Panel be contributed from Java instead of a page?
Yes. Register a UIExtension component on the platform.panels extension point whose getId() parses as a document reference, and it is picked up like a wiki Panel.
Why does my Panel see the wrong document in $doc?
Because $doc is the page the Panel is displayed on, by design. The Panel's own document is $paneldoc.
Where is the extension point for adding a Panel to a column from an extension?
There is none: the columns are driven by the leftPanels and rightPanels preferences, so an extension that wants a Panel displayed has to write them.
More
To find more about the current topic, you can search or use the table below and filter the columns to narrow your choices.