Electron / Intermediate / 15 min read
Notion: how does an Electron app copy rich text?
Use REA to follow Notion’s reported clipboard path, from the renderer through IPC to the system clipboard. Apply the method to your own Electron app.
On this page
A source-backed map of the text and HTML payload, the process boundary and the clipboard writer.
You will needREA, an Electron app you can inspect, and its app.asar or extracted JavaScript. No native engine is needed.
01. Start with the payload, not the whole app
Copying bold text feels like one operation. In Electron, the editor, the bridge exposed to a web page, and the process allowed to write to the operating system may be different pieces of code. Your job is to connect them.
The official Notion investigation followed Desktop 7.6.1. Its reported route passes text and HTML through a clipboard API and an IPC receiver. The graph alone did not resolve the entire route: direct reading of wrapper code supplied missing links. This tutorial applies that investigation method; it is not a new capture of Notion.
Use REA to inspect /absolute/path/app.asar. Investigate only copying rich text. Find the renderer call, preload bridge, IPC channel, receiving handler and final clipboard write. For each link, show its file and source range. Mark dynamic or missing links as unresolved. Do not run the application.02. Find the shipped entry points
Work on a copy of the application files. On macOS, Electron packages often put app.asar under Contents/Resources; Windows and Linux packages commonly use a resources folder. Confirm the path instead of assuming every application uses the same layout.
Keep any app.asar.unpacked companion directory beside the archive. Review parse failures, skipped files and the discovered main entry before trusting the map. An incomplete inventory can hide the receiver you need.
npx -y [email protected] analyze-javascript-application "/absolute/path/app.asar" --json > app-analysis.json03. Cross the renderer-to-main boundary
Ask the agent to inspect the actual source around contextBridge, clipboard and ipcRenderer.invoke references returned by the analysis. A bridge may expose a generic function whose channel is passed through a variable. Searching the graph for the literal channel can return nothing even when the wrapper source contains it.
The upstream Notion report identified the channel notion:clipboard:write by reading the packaged API object, then connected its receiver to Electron clipboard.write. Record the equivalent names from your own version; do not paste historical offsets into a different release.
- Renderer: which event constructs the copy payload?
- Preload: which public API forwards it, and how is the channel supplied?
- Main process: which handler receives it, and how is the sender checked?
- Sink: which text, HTML or custom fields reach the clipboard API?
04. Test one formatting feature
In a disposable document, copy a short sentence containing one bold word. Paste it into a rich-text editor and a plain-text editor. Record both outputs. Repeat with a link, a line break and non-ASCII characters. These checks distinguish plain text fallback from preserved formatting.
A matching source route does not prove that your operating system accepted every format. The upstream investigation also used separately cached web modules; it did not record a same-version desktop copy session. Keep that distinction in your own report.
Build a small copy-payload function for my own app using the behavior we established. Keep plain text and HTML separate. Add tests for bold text, links, line breaks and Unicode. List any custom clipboard formats that remain unexplained; do not claim full Notion compatibility.05. When the trace stops at a wrapper
Inspect the wrapper definition and its call site together. If a channel name is assembled at runtime, record the expression rather than inventing a literal value. If a native addon performs the write, the JavaScript analysis ends at that boundary.
Your finished result should be a short route with evidence for each hop, plus the formatting tests you actually ran. That is enough to rebuild a useful copy feature without pretending to recreate the editor.
Commands checked against REA 6.4.0. Target-specific results depend on your artifact and provider. Read the upstream source and scope →
New to the tool? What is REA? · How we check our guides