References, links and backlinks
Every block has exactly one canonical home, and can be pointed at from anywhere else. That is the sentence the whole product is built on, and this page is where it becomes something you type.
Five things point at something else, they look alike in a menu, and they behave differently. So the table comes first.
| What you want | What you type | What appears | What happens later |
|---|---|---|---|
| Link a page | @ or [[, then pick the page |
An inline chip with the target’s icon and title | Its icon follows the page; its words do not. It shows up in the target’s Linked from |
| Link a page as ordinary text | Select the words, then ⌘K / Ctrl + K |
An ordinary link, styled like any other | Nothing follows the page. It does not show up in Linked from |
| Embed a page | ![[, then pick the page |
The whole page, in a frame, live and writable | Every change is a change to the page itself. It shows up in the target’s Linked from |
| Reference a block | Copy reference, then / → Paste block reference |
That one block, in a frame, live | Same: the block has one home, and this is a window onto it. It shows up in Linked from and in Referenced blocks |
| Mention a person | @, then pick the person |
Their name as a chip | It lands in their inbox for this workspace. It is not a link and not a backlink |
A reference is never a copy. Nothing is duplicated: what is stored is a pair of identifiers, and everything you see in the frame is read from the page it belongs to, as it is right now. Two people looking at an embed of the same page see each other type in it.
And a reference never grants access. If you may not read the target, the frame says so and stays empty — it does not fetch the content, and it does not name it. This is true all the way down: a page nobody has shared with you cannot be read by embedding it somewhere you can read.
Linking a page
Three ways in, and they insert two different things.
@searches pages and the people in this workspace and inserts whichever row you pick — a page chip or a mention. Pages come first, except when what you have typed starts one of the words of somebody’s name: then that person is on top, because typing a name and pressingEnterhas to mean the person.@on its own, before you have typed anything, lists the first ten members and no pages — a bare@is not a request to list a whole workspace.[[is the same picker restricted to pages. It exists because that is how a page link is written in Markdown, and because![[is built out of it.⌘K/Ctrl+Kover a selected run of text opens the link box: Search pages or paste a link…. Pick a page and the selected words become a link to it; paste anhttp(s)address and they become a link to that. With nothing selected,⌘Kis not the editor’s — it opens search across the workspace, which is what that key does everywhere else in the app.
The picker offers pages and nothing else. A workspace can hold other kinds of document, and workspace search finds them; this picker filters them out, because a link written to something that is not a page resolves to a permanent No access in your document — from a row the picker itself proposed.
Nothing is linked behind your back. A URL you type is text; a URL you paste onto a selection becomes a link on that selection, and a URL pasted into empty space becomes a plain link with a small chooser beside it (below). Automatic linking is off, on purpose: links are made deliberately, through the picker.
The words are written down, the icon is looked up
A page chip stores the target’s id and the title as it read when you inserted it. Rename the page afterwards and the chip keeps the old words. The icon is the other way round: it is never stored on the chip, it is resolved every time the chip is drawn, so it can never be a stale copy of somebody else’s page.
That split is deliberate rather than an oversight in one half. A label is text in your sentence — “see the [[Q3 plan]] for the numbers” should not silently rewrite itself around your grammar — while an icon is only ever a picture of the target, and a wrong one is a picture of nothing.
To follow a chip: click it, or put the caret beside it and press
⌘⏎ / Ctrl + Enter. The same chord opens an embedded page when its frame
is selected rather than being written in — inside the frame you are already in
the target page, so the chord belongs to the block the caret is on there.
Embedding a page
![[ inserts a page embed: a frame carrying the target’s title and an
open ↗, with the target’s whole body inside it, live. You write in it the way
you write anywhere else, and what you write is written on that page — there is
no second copy to reconcile.
What the frame shows is the body and nothing around it: no properties panel, no subpages list, no comments, no breadcrumbs. Those belong to the page, and the page is one open ↗ away.
Referencing a block
A block reference points at one block instead of a whole page.
- Put the caret in the block and press
⌘//Ctrl+/for the block menu. Its first entry is Copy reference. (The same thing is in the/palette as Copy block reference, which is where it used to be the only way in — a feature reachable only by finding it in a nineteen-item list reads as a feature that does not exist.) - A message says Block copied — use “Paste block reference” to embed it.
- Wherever you want it:
/→ Paste block reference.
Which block is copied is the block the caret is in, walked up to the nearest thing that is a block in its own right. So a single list item is a block; a caret in a table cell copies the whole table, because a table is one block; and the first line of a callout, a quote or a toggle is that container’s own text, so it copies the container.
Where the pasted reference is editable depends on what it points at. Three things are drawn read-only — an image, a divider, and another reference — because there is nothing in-place editing could mean for them. Everything else is edited in place: a paragraph, a heading, a list item, a to-do, a callout, a quote, a toggle, a table, a code block. And the edit is an edit of the block at its home. The palette’s own description still says (read-only) for both cases; it describes the first one.
A block reference follows its block. If somebody retypes the target from a paragraph into a heading, the frame redraws as a heading while you are looking at it; if they delete it, the frame says so rather than showing the block that took its place.
Linking to a heading
A heading has a second, lighter way of being pointed at. Hover it — or put the
caret in it, or press Tab from inside it — and a chain appears after its text;
the block menu offers the same thing as Copy link to heading. Either copies an
ordinary URL of the page with the heading’s identifier after a #.
Open that URL and the page scrolls to the heading and flashes it. It is a link, not a reference: it moves the reader, it does not bring the section along, and it is not counted in Linked from.
How deep, and how many
An embed can contain an embed, so two limits exist and both of them are visible when you meet them.
Three levels deep, then a link. Counting the page you actually opened as the ground: an embed on it is one down, an embed inside that is two, and one inside that is three. All three are drawn. A fourth is not: in its place is Embedded pages nested too deep. and an open ↗ to the page itself.
Thirty-two embeds to a page. The budget is shared by the page and everything nested inside it — it caps the embeds on the screen, not the embeds per level. Past it, a frame reads {title} — too many embeds on this page. with an expand button that mounts that one anyway. The budget is a live count rather than a queue: an embed that goes away frees its place for the next one.
A page cannot embed itself, directly or round a loop. A embedding B
embedding A gives the second A a frame reading Circular reference — this
page is already embedded above. One case that looks like a loop and is not: a
block reference on a page to a block of that same page. That is an ordinary
same-page reference and it renders — but only at the top level. Deeper inside an
embed, a reference back to the page you started on really is a loop, and it gets
the placeholder.
When the target is gone, hidden or in the trash
Every one of these has its own sentence, because “you may not see this”, “this no longer exists” and “we could not find out” are three different statements and a reader has to be able to tell them apart.
| What is wrong | An embedded page says | A block reference says |
|---|---|---|
| Nothing is stored as the target | Broken embed (missing target page). | Broken reference (missing target block). |
| You may not read it | No access to this page. | No access to the referenced block. |
| The page it lives on is in the trash | Deleted — restore it at its home page. | Deleted — restore it at its home page. |
| The block was deleted from its page | — | Referenced block no longer exists. |
| It is already embedded further up | Circular reference — this page is already embedded above. | Circular reference — the owning page is already embedded above. |
| It is deeper than three levels | Embedded pages nested too deep. | Referenced block nested too deep. |
| The page has run out of budget | {title} — too many embeds on this page. | Too many embeds on this page. |
The frame’s header is there whichever of these it says, with an open ↗, so a placeholder is usually a way through rather than a wall. Two details. What stands beside the arrow differs by frame: an embedded page names the page — Untitled where you may not read it, which is what the No access row is for — while a block reference’s header says only block reference, because the page it lives on is exactly what the placeholder is declining to name. And the arrow goes somewhere only when there is somewhere to go: with no target stored, or a referenced block that resolved to no page at all, it does nothing.
Nothing is lost while the target is in the trash. Restore the page at its home and every reference to it fills in again — the references were never deleted; they were pointing at something that had been put away.
Linked from
Under the body of a page sits Linked from: the pages that point at this one.
- It lists pages, once each, however many times one of them links here.
- Three kinds of pointer put a page in this list: an inline page chip, a page
embed, and a block reference to any block of this page. An ordinary
⌘Klink does not — that is a link mark on a run of text, and the difference between the two ways of linking a page is exactly here. - A page you cannot open is not listed, and neither is a page in the trash, and neither is this page’s own link to itself.
- The section is not drawn at all when there is nothing to list. It reports; it has no button in it, so an empty one would be a heading and a sentence about absence, and a new page had three of those in a row.
- A failure is drawn: The pages linking here could not be loaded: …, for the same reason. “There is nothing” and “we could not find out” are not the same answer.
Referenced blocks
Backlinks stop one level too high for the question a reader actually has in front of a much-quoted paragraph: where, and how often, is this block used? Referenced blocks answers it, under the backlinks.
One row per block of this page that somebody references. The row is named by the
block’s first 160 characters of text; a block with none of its own — a divider,
an image, a code block — is Block without text. Beside it: Referenced in 3
places. Open the row and it lists the pages, each a real link (so
⌘-click and middle-click open it beside what you are reading), with 2×
against a page that references it twice.
One row is open at a time, and the places are fetched when you open it — a page with twenty referenced blocks costs one request, not twenty-one.
The count is what you may see. A reference sitting on a page you cannot open is neither listed nor counted, so the number always adds up to the links underneath it. An unfiltered total beside a filtered list would name the existence of the pages the permission system is hiding, with the one number nobody thinks to check. A block referenced somewhere else on its own page is counted and listed: it is a place, and you can go there.
What someone outside the workspace sees
A page published to the web is rendered by a different, much smaller renderer, and references do not survive the trip.
- A page chip whose target is also part of the share stays a link. One pointing anywhere else becomes the marker not shared, which carries nothing of the target: a chip’s label is the target’s title as it stood when the link was made, and a private page title in plain sight is exactly the leak publishing it would be.
- A mention becomes the same marker. That the marker does not say which of the two it was is deliberate: “a person” versus “a page you cannot see” is itself information.
- A page embed or a block reference is replaced by the line A reference to another page is not part of this shared page. — every time, including when the target is inside the share.
- An ordinary
⌘Klink to a page loses its link and stays as the words you wrote — including when the target is inside the share. A published page carrieshttp,httpsandmailtoaddresses out and nothing else, and an in-app address is both meaningless to a reader who is not signed in and a page id written down in public.
The point of naming what is missing rather than leaving a hole is that a reader can tell the page is complete-as-published instead of broken. Publishing is on its own page, Sharing, comments and history.
Link embeds
A pasted URL is a fourth kind of pointer, at something outside Basalt entirely.
Paste one into empty space and you get a plain link straight away, with a small
chooser beside it offering three other shapes: Title (the site’s own title as
the link text), Card (a preview with title, description and image) and
Embed (the page itself, in a frame). The plain link is the fourth button and
it is already the state you are in, so it is the way out: press it, press the
× beside it, press Esc, type on, or ignore the whole thing, and you keep
the plain link.
The chooser says in a line that Title, card and embed ask this server to fetch the link — a pasted link on its own costs no outbound request, and only your choice makes this instance call a stranger’s website. A site that refuses to be framed says so instead of showing an empty box.
An instance can also have link previews switched off altogether. The chooser has no way of knowing that before it asks, so it still offers the three; picking one answers No preview available for this link. under the buttons, and the plain link you already have is untouched.
How the two rich forms are spelled in a file is in the Markdown specification.
References in the Markdown
A page is Markdown, and references are part of it, so they survive a download and come back on an upload:
| In the document | In the file |
|---|---|
| A page chip | [[<page id>|Label]] |
| A page embed | ![[<page id>]] on a line of its own |
| A block reference | ![[<page id>#<block id>]] on a line of its own |
| A mention | @[<user id>|Name] |
They address ids, never titles. The bracket syntax is the one other tools
use, but the thing inside the brackets here is a full identifier, so a reference
keeps pointing at the right page after the page is renamed — and so writing
[[Meeting notes]] by hand produces the literal text [[Meeting notes]] and
not a link. Every one of these round-trips exactly: what you download is what
comes back.
What references cannot do yet
- No reference to a range of blocks. Copy reference takes exactly one — a paragraph, a list item, a whole table. To quote three paragraphs you make three references, or you embed the page they are on.
- A copied reference does not leave the tab you copied it in. It is held in the app, not on the system clipboard, so a second window and a second browser tab each have their own, and reloading empties it. If Paste block reference says No block copied yet, that is what happened. Copy it again from the block menu.
[[Page title]]written by hand is not a link. The Markdown form takes an id, so a wiki brought in from elsewhere arrives with its title-based links as text. What the importer does rewrite is described under Import.- An
⌘Klink to a page is invisible to Linked from. Both ways of linking a page are legitimate and only one of them is counted. If you want the target to know, use@or[[. - An embed does not know that you may not edit the target. A page you can read but not write is embedded as a writable frame; the connection to it is read-only, so what you type there is not written to the page, and the frame gives no sign of it beforehand. Open the page itself to see what you may actually do with it.
- A block reference cannot address anything but a block. Not a page property, not a database cell, not a comment, not a heading’s section — a heading link jumps a reader there, it does not bring the section along.
- A public page renders no embed and no block reference, not even one whose target is inside the same share. That is a decision about a renderer served to people who are not signed in, not unfinished work.