Shareable workspace URLs
Updated
A tab the user can see must have an address they can copy. Pasting that address after sign-in must reopen the same tab, not the dashboard.
Why /workspace is not enough#
/workspace is the mode: the dock, as opposed to the dashboard /.
It is not a link to a document. Opening a sales order used to leave the
address bar on /workspace, so a colleague who received that URL landed
on an empty dock (or on whatever tabs their browser had saved).
Address bar = the active tab#
| What is open | Address bar |
|---|---|
| Document record | /data/doc/{typeId}/{docId} |
| Dictionary record | /data/dict/{dictId}/{recordId} |
| Document journal | /data/doc/{typeId} |
| Dictionary list | /data/dict/{dictId} |
| Register totals | /data/totals/{regId} |
| Virtual total / custom report | /data/vt/{id}, /data/report/{id} |
Tool page (/logs, /scripts, …) |
that path, unchanged |
| Metadata designer / user / script editor | /workspace?open=meta:… (see trap) |
Unsaved draft (:new:) |
/workspace — drafts are not shareable |
/data/… and every PAGE_REGISTRY path keep the dock visible (isDockPath).
/dataentities is a tool page; only the /data/ prefix is a record URL.
/workspace?open= remains an incoming alias for records (and the share
form for tabs whose pretty path would collide with a list page). Prefer the
pretty path when you mint a link.
The route for /scripts still mounts PromoteRegistryPage. If the tab
already exists it only focuses — it does not navigate away — so switching
back to Scripts writes /scripts and does not loop.
Login ?next=#
Unauthenticated layout and the HTTP 401 interceptor send the browser to
/login?next= + the current path. After a successful sign-in the SPA goes
there instead of /.
sanitizeReturnTo refuses anything that is not a same-origin relative path:
protocol-relative //host, absolute URLs, javascript:, and /login
itself (a loop). A crafted next cannot ship the user off-site after they
type a password.
Restore#
Refresh still rebuilds tabs from the per-user pref. The pasted URL is
applied after that set: missing tabs from the last session come back, then
the linked tab is focused. Closing the last tab writes /workspace.
Traps#
Do not put a document on
/documents/:id. Runtime records are not React routes with their own page component. The dock is the page;/data/is only an address for a tab id the restorer already knows how to rebuild.
Drafts are not links.
docrec:{type}:new:{n}has nothing on the server. Sharing it would 404 the recipient. The address bar falls back to/workspace.
/{entity}?id=is the list page's inline designer, not themeta:tab. Double-clicking a row opensmeta:{entity}:{id}in its own tab. Writing that as/dictionaries?id=would collide with the grid-first deep link and with Promote'spage:/dictionaries?id=tab. Those tabs share as/workspace?open=.
nextis not a redirect API. Only the login page reads it, and only throughsanitizeReturnTo. A 401 on/loginitself does not bounce.
AOT is not a URL. Developer → AOT (and QuickSearch) toggle a session overlay. The address bar stays on whatever was already there — a record,
/scripts, the dashboard. Opening a tab inside AOT does not rewrite it either (homeRoute={null}). A real navigation (Dashboard, Workspace, a tool page, a record) hides the overlay. Old/idebookmarks redirect to/workspace; they do not reopen the designer. The overlay is a second dock — those tab ids never write/data/or?open=.
What's not there yet#
- Split layout (side-by-side groups) is not encoded in the URL.
- Popped-out panel windows have no shareable address.
Where next#
- Auth and API gates — cookies, 401, what login actually issues.
- Record change history — another address
(
/record-history) that now survives login the same way.