Sidecars

Links & Browser

Open app-owned tabs, pair installed Windows apps in a shared bar, manage bookmarks and present public-text companions.

0.6.0-alpha.2Alpha capabilityDeclared targets: Windows, Androiduk.capp.sidecar.links

Open a tab from your application

Links & Browser keeps the application in a permanent first tab and opens websites or supported bundled text files beside it. Switching back does not intentionally reload the application. Use it for product documentation, reference sites and explicit website handoffs—not to grant remote pages your application's capabilities.

Select uk.capp.sidecar.links, build and install the updated target package. The application interface is window.capp.links; the typed SDK capability name is links. The package ID, SDK name and individual methods are different identifiers.

For a complete lifecycle-aware button and fallback, use the executable example in Build with Sidecars. This smaller helper is for an existing button handler; it is not an automatic page-load action:

js
async function requestDocumentationTab() {
  const links = window.capp?.links;
  if (typeof links?.open !== 'function') {
    return { requested: false, reason: 'Links is unavailable in this environment.' };
  }
  try {
    await links.open('https://c-app.uk/developer-docs/', { mode: 'tab' });
    return { requested: true };
  } catch {
    return { requested: false, reason: 'The tab request failed. Use the visible browser link.' };
  }
}

Await it from a person-operated Open documentation tab button and render the result as text. Prevent repeated clicks while pending and keep an ordinary user-operated HTTPS link beside it. Requested does not mean loaded. A native page can fail after the request returns; the tab host reports that state. Never automatically open a second destination after an uncertain result.

First successful composition

  1. Select Links and choose your link policy. On Windows, choose the intended top-bar mode; on Android, check the target's Links settings.
  2. Compile/package/install so both shell assets and native browsing commands belong to the same build.
  3. Open an HTTPS documentation link. Confirm a new tab appears and the app's existing state remains when you select App again.
  4. Close the page tab, then exercise bookmarks and an intentional Open in browser action separately.
  5. Test a site that cannot work in the embedded/native surface and confirm that its failure is visible and the app remains usable.

Selection provides the window controller; it is not a universal cross-frame object lookup. Use the API exposed in your registered application surface or the SDK's require('links'). Wait for capability readiness rather than reaching into arbitrary parent frames.

Application API

The exact SDK types describe arguments for the v1 bookmark/tab interface. Use await on request paths even when an installed implementation returns immediately. Companion support is an additive runtime extension; check its methods/flags rather than assuming the base TypeScript declaration includes it.

MethodInput and resultImportant boundary
status()Policy, storage status, active tab and optional native-browsing stateNot proof a destination loaded
open(url, {mode})Request tab, browser or inline choiceExplicit mode is the action the person selected
newTab(url?)Returns {tabId} for a new page/blank tabNative load can complete later; the tab limit applies
tabs()Current tabs, including {id:'app', kind:'app'}Session list, not a durable history store
selectTab(id) / closeTab(id)Select/close a declared tabThe app tab is permanent
view(url)Requests navigation; reports native, file, embedded or browser-requiredRequested mode is not final-URL attestation
show() / hide()Open saved links / return to the appHiding does not destroy page tabs
openExternal(url)Explicit default-browser requestThe external browser has its own session/security state
list({query, folder}) / save(record) / remove(id)Read, create/update and delete saved linksApp/device storage; not a hosted bookmarks service
export() / import(json) / refresh()Versioned JSON interchange and reload of stored stateImport validates/merges; refresh handles other local changes

maxTabs bounds extra page tabs, excluding App: 1–12, with default 8. Closing the final extra tab on mobile hides the strip without reloading App. Session page history is not restored after restart; saved links are separate.

Bundled tools in New Tab

Links 0.5.0-alpha.1 adds an app directory when built with compiler 0.5.0 and the matching factory. Declare tools in the source component's capp-internal-apps.json using protocol capp.internal-apps.v1, then compile a new release and package it with Links selected. Old releases retain their original directory, including no directory. This is an additive low-level runtime extension; feature-detect window.capp.links.supports.internalApps before calling listInternalApps() or openInternal(id).

A packaged-page entry names an included HTML document and explicit asset closure; an app-route entry names a hash route in the existing main app. Tools use singleton tabs, retain edits while switching, and can veto close/reload through window.capp.surface.registerLifecycle. Tab snapshots may now include kind: 'internal-app' beyond the base SDK's older tab-kind union. The main app is always retained. Viewing New Tab does not start tools, services or AI models.

Bundled tools are co-trusted application code, not an installation mechanism or a sandbox for arbitrary third-party pages. Their minimal injected client exposes lifecycle and limited Links actions; it does not forward the owner's native, service or AI administration APIs. Remote website and inert file tabs retain their separate boundaries. Installed Windows/Android acceptance remains pending; package and Chromium evidence does not certify native behavior.

The default handled-link action is a new in-app tab. Preserve explicit ask, tab, browser and off choices. ask presents a choice; off disables normal automatic link interception rather than granting a destination new permissions.

Ordinary internal routes and hash navigation stay in App. For individual anchors, data-capp-link="tab|browser|ask|ignore" provides an explicit routing choice. Avoid competing click handlers that request the same destination twice. _blank, modifier-click and middle-click handling are part of the owner controller; remote pages do not receive the owner's shortcuts.

allowEmbeds controls in-app website surfaces despite its historical name. allowHttp is a separate opt-in for public HTTP sites. Bundled app files have their own local-file path and are not a reason to enable public HTTP. Reject unsupported schemes and credential-bearing URLs instead of rewriting a mistyped scheme into something that happens to load.

Windows can integrate the tab strip into the custom Browser tabs title row, retain a separate strip with App bar, or retain native window chrome. Android can hide the strip with only App present. A build-page visual preview does not execute native window controls.

Native websites, previews and bundled files

EnvironmentWebsite surfaceLimits to explain to users
Installed WindowsSeparate native WebView2 children beneath app-owned controlsSeparate incognito profile; remote downloads can require the browser
Installed AndroidNative Android website views inside the active tab rectangleCookies can persist; no incognito guarantee; restricted files, uploads and permissions
Ordinary browser previewOpaque, sandboxed iframeMany sites refuse framing; the displayed address is the requested URL, not an attested final URL
Bundled text fileInert text/file tab from the owner originNo script or HTML execution; bounded to 2 MiB

Remote native pages do not receive the cApp, wallet or owner command bridge. Android website views do not receive a JavaScript interface or Tauri plugin loader. Ordinary site JavaScript still runs within that website surface; this is not a content-trust endorsement.

Bundled text is fetched from the owner's app origin without credentials or redirects and rendered as text. Reading a .mjs, Markdown, JSON or HTML file is not execution or installation. The installed save action uses a system dialog rather than a path supplied by the webpage.

An installed native-browsing failure does not silently downgrade to an iframe or unauthenticated transport. Login, uploads, protected media, downloads and site permissions may need the normal browser. For managed application sign-in on Android, use Android Auth, not an assumed shared session between a Links tab and Custom Tabs.

Saved links are app/device-scoped and unencrypted. Respect the configured retention and maxLinks limit; inspect status().storage for ready, session-only, unavailable or damaged storage. Do not overwrite damaged data blindly or infer that a successful in-memory view was persisted.

The public interchange format is capp.links.v1. This example passes the saved-links schema:

json
{
  "protocol": "capp.links.v1",
  "links": [
    {
      "id": "capp-docs",
      "url": "https://c-app.uk/developer-docs/",
      "title": "cApp Developer Docs",
      "folder": "Reference",
      "notes": "Public guides and API reference",
      "pinned": true
    }
  ]
}

Pass the JSON text to links.import(json). Import merges by canonical URL, skips existing URLs and does not overwrite their records. It validates the proposed import before committing; the selected link limit and HTTP policy still apply even when JSON Schema accepts a document. Export before a deliberate bulk change and never put credentials in a saved URL or note.

Companion handoff

Feature-detect links.supports.companion, links.openCompanion and links.status().companionAvailable. openCompanion({id, url, title, body, copyLabel, copyText}) opens an HTTPS page beside a text-only app-owned card, outside the native webpage bounds. It reports {opened:true, tabId, id} or an explicit skipped result/reason.

Keep the ID stable for the site, purpose and public value. Supply only intentionally shareable text, never keys, passwords or session material. The remote page receives neither the supplied card text nor app authority. Clipboard writes require the person's Copy action; there is no automatic paste or clipboard-read service.

clearCompanion() clears the card; selectTab('app') returns to the mounted app. The owner emits capp:links-companion-return on return, closure or clearing. Remove your event listener when its owner leaves. Return does not prove the website action completed. Re-read the application's postcondition before proceeding.

Troubleshooting

SymptomCheck and next step
links is absentWait for readiness and check the installed selection/registered app surface. Do not infer it from the package name alone.
Tab request succeeds but page is blank or failsInspect the tab-host error and test the explicit browser path. A requested URL is not a successful load.
Native command unavailableRebuild/install with the selected native composition; do not add an iframe fallback to the installed app.
No mobile strip at startupExpected with only the App tab. Open an extra tab to show it.
Import fails despite valid JSONCheck duplicate IDs, URL policy, canonical duplicates, current storage and the selected link limit.
Companion is skippedCheck current availability, in-app browsing policy and remaining tab capacity. Keep the app checkpoint useful.
Sign-in state differs from the system browserThese surfaces have separate session/profile behaviour; use the proper Auth flow.

Share a bar across installed Windows apps

Links 0.6.0-alpha.1 adds an opt-in shared app bar. In each app's selected Links configuration enable Share a workspace bar with other installed Windows apps, choose the same Workspace group, and keep automatic joining enabled. Rebuild the cApp owner, then freshly Compile/Package/install each app. Choose Windows Browser tabs for a single title/tab row. Existing packages and ordinary browser pages do not acquire workspace support from a configuration edit alone.

The next running app joins that group in the same Windows login session. Select its tab to switch to its live window. Each app keeps its own process, unsaved documents, storage and service ownership. The source hides only after the receiver acknowledges visibility; a failed switch leaves the source available. Duplicate launches focus the existing instance. A workspace holds up to eight apps.

Drag an application tab out to give it its own window. App workspace in the app menu, or Workspace in the separate Links strip, offers detach and explicit Join. The app's website and internal tabs move with its window; individual page tabs cannot move between processes. Two detached apps can join again. Membership is session-only, and crash recovery restores access to surviving apps, not unsaved content from a process that exited.

Defaults are workspaceEnabled: false, workspaceGroup: "creative-suite", and workspaceAutoJoin: true. A group is a 1–64 character lowercase label beginning with a letter/digit, with dots, underscores and hyphens allowed thereafter. It is an explicit pairing choice, not an authentication secret. Native IPC stays on the current user's machine and login session; no network listener or app authority is shared. Existing asset-folder connections are separate.

The runtime tabs() list may include opaque workspace-app and workspace-page rows. Selection returns to the owning app; closing another app's tabs through closeTab() is refused. The private workspace controller is not a product API. Android and browser preview retain their existing local tab behavior. Source, package and browser-fixture checks do not establish native Windows focus, display scaling, crash recovery or installed model residency; those checks remain pending.

Windows page zoom

Links 0.6.0-alpha.2 and MCP 0.24.27 enable native page zoom by default in freshly packaged Windows app WebViews and website tabs. Use Ctrl+scroll, Ctrl+plus/minus, and Ctrl+0 to reset. Websites can consume their own wheel gestures; this does not change site trust, permissions or download policy. Rebuild/restart the owner and create an updated Windows package. Other platforms retain their current behavior; installed WebView2 interaction still requires target validation.

Configuration reference

These are the selected package's configuration fields. String credential values and installation-specific defaults are never published here. A field's presence does not bypass its runtime policy.

FieldTypeMeaning and constraints
titletextSaved links title
startupselectOpen behaviour. Choices: closed, open
showLaunchercheckboxShow saved links shortcut
remembercheckboxSave links on this device
maxLinksnumberMaximum saved links. Bounds: 1 to 500
allowEmbedscheckboxAllow in-app website tabs
allowHttpcheckboxAllow unencrypted HTTP links
linksJsontextareaPublic defaults distributed with this app. Each row has url and optional title, folder, notes and pinned. Used only before local links exist.
maxTabsnumberMaximum open tabs. Bounds: 1 to 12
linkHandlingselectWhen an app link is clicked. Choices: ask, tab, browser, off
workspaceEnabledcheckboxShare a workspace bar with other installed Windows apps
workspaceGrouptextApps with the same group can join. Use lowercase letters, digits, dots, dashes and underscores. Each app keeps its own runtime and data.
workspaceAutoJoincheckboxJoin an existing workspace when this app starts

Component changelog

added0.6.0-alpha.2Permalink

Links

Enables native Ctrl+scroll and keyboard page zoom in newly generated Windows website tabs. App WebViews receive the matching default through MCP 0.24.27. Other platforms and existing trust boundaries are unchanged; rebuild the owner and package an updated application.

Public component note; package availability and installed acceptance are separate.
added0.6.0-alpha.1Permalink

Links & Browser

Adds opt-in Windows app workspaces: automatic same-session grouping, live app/page selection, application-tab drag-out and explicit rejoin. Each app retains its own process, unsaved state and services. Individual page tabs stay with their app. Rebuild the owner and freshly Compile/Package each app. Source/package/browser-fixture checks pass; native Windows validation remains pending.

Public component note; package availability and installed acceptance are separate.
added0.5.0-alpha.1Permalink

Links & Browser

New Tab lists explicitly declared tools from the compiled release. Bundled documents use singleton tabs with retained state and close/reload guards; routes reuse the main application. Discovery does not start services or models. Requires compiler 0.5.0 and the updated factory; installed Windows and Android acceptance remains open.

Public component note; package availability and installed acceptance are separate.
baseline0.4.1-alpha.1Permalink

Links & Browser

App-owned tabs, saved links and bounded companion handoffs.

Documentation snapshot, not a historical release date.
View component notes →
↑ ↓ to navigate · Enter to open · Esc to close. Search stays in your browser.