The reserved punktfunk://browse/<host-ref> route now routes on the Apple client, and two new front doors emit it — both round-tripping through the one URL router, so there is no second code path.
What's new
Shortcuts / Siri / Spotlight — a new Open Game Library intent beside Connect / Wake / End Stream. Host-parameterized like the others (HostEntity picker), foregrounds the app and lands in that host's library with nothing streaming yet. Phrases: "Open ⟨host⟩ library in Punktfunk" / "Show ⟨host⟩ games in Punktfunk".
A configurable library widget (kind PunktfunkLibrary; small + both Lock-Screen families) — long-press → Edit Widget picks a saved host (the AppIntentConfiguration the HostEntity doc comment always anticipated); a tap opens that host's library. Unconfigured it follows the most recent host. A configured host that was later removed shows the empty state rather than silently following a different host — a widget that says "Studio" must never open someone else's library. Same .never timeline + push-reload design as the hosts widget; HostStore now reloads both kinds.
The route
ContentView.openLibrary(from:) drives the same libraryTarget every internal surface writes, so a link lands in whichever presentation the current mode owns: the gamepad console's in-place library screen, the touch cover, the macOS sheet, or tvOS's cover.
Connect's posture minus the connect itself:
pin conflict (fp= vs. the stored identity) → hard refusal with a notice
a live session is never preempted
an unsaved host → notice (the library fetch rides the paired mTLS identity, so there is nothing to show before the host is saved — unlike connect, there's no confirmation-sheet path to offer)
launch= / profile= on a browse are ignored, not refused — nothing streams until a title is picked, and that connect resolves its own profile
wake stays reserved (Shortcuts users have the Wake Host intent, which never round-trips through a URL). Other clients keep answering browse with a notice; the parse side was already in the shared grammar and the vector file, so nothing moves cross-language.
DeepLink.browse(host:) is the shared emitter, covered by a round-trip test beside connect's — the same backward-compatibility stakes: a Home-Screen widget keeps sending yesterday's URL.
xcodebuild of PunktfunkWidgetsExtension for the iOS Simulator — green
Not yet on-glass: the widget config picker and the Siri phrases are device-verifiable only
The reserved `punktfunk://browse/<host-ref>` route now routes on the Apple client, and two new front doors emit it — both round-tripping through the one URL router, so there is no second code path.
## What's new
**Shortcuts / Siri / Spotlight** — a new **Open Game Library** intent beside Connect / Wake / End Stream. Host-parameterized like the others (`HostEntity` picker), foregrounds the app and lands in that host's library with nothing streaming yet. Phrases: "Open ⟨host⟩ library in Punktfunk" / "Show ⟨host⟩ games in Punktfunk".
**A configurable library widget** (kind `PunktfunkLibrary`; small + both Lock-Screen families) — long-press → Edit Widget picks a saved host (the `AppIntentConfiguration` the `HostEntity` doc comment always anticipated); a tap opens that host's library. Unconfigured it follows the most recent host. A configured host that was later removed shows the empty state rather than silently following a different host — a widget that says "Studio" must never open someone else's library. Same `.never` timeline + push-reload design as the hosts widget; `HostStore` now reloads both kinds.
## The route
`ContentView.openLibrary(from:)` drives the same `libraryTarget` every internal surface writes, so a link lands in whichever presentation the current mode owns: the gamepad console's in-place library screen, the touch cover, the macOS sheet, or tvOS's cover.
Connect's posture minus the connect itself:
- pin conflict (`fp=` vs. the stored identity) → hard refusal with a notice
- a live session is never preempted
- an unsaved host → notice (the library fetch rides the paired mTLS identity, so there is nothing to show before the host is saved — unlike connect, there's no confirmation-sheet path to offer)
- `launch=` / `profile=` on a browse are ignored, not refused — nothing streams until a title is picked, and that connect resolves its own profile
`wake` stays reserved (Shortcuts users have the Wake Host intent, which never round-trips through a URL). Other clients keep answering `browse` with a notice; the parse side was already in the shared grammar and the vector file, so nothing moves cross-language.
`DeepLink.browse(host:)` is the shared emitter, covered by a round-trip test beside connect's — the same backward-compatibility stakes: a Home-Screen widget keeps sending yesterday's URL.
Docs updated: clients, game-library, profiles-and-links.
## Verified
- macOS `swift build` + full `swift test` (CI parity) — green, including the new round-trip test
- iOS + tvOS triple typechecks (`swift build --triple arm64-apple-{ios,tvos}17.0`) — green
- `xcodebuild` of `PunktfunkWidgetsExtension` for the iOS Simulator — green
- Not yet on-glass: the widget config picker and the Siri phrases are device-verifiable only
The reserved punktfunk://browse/<host-ref> route now routes on Apple: it
drives the same libraryTarget every internal surface writes, so the link
lands in whichever presentation the current mode owns — the gamepad
console's in-place library screen, the touch cover, the macOS sheet, or
tvOS's cover. Connect's posture minus the connect: a pin conflict
refuses, a live session is never preempted, an unsaved host gets a
notice (the library rides the paired mTLS identity, so there is nothing
to browse before the host is saved). browse ignores launch=/profile= —
nothing streams until a title is picked, and that connect resolves its
own profile.
On top of the route, the two new front doors:
- OpenLibraryIntent ("Open Game Library") beside Connect/Wake/End in
Shortcuts/Siri/Spotlight, host-parameterized like the others and
round-tripping through the URL — one router, no second path.
- A configurable library widget (kind "PunktfunkLibrary",
AppIntentConfiguration over HostEntity — the configuration the
HostEntity doc comment anticipated): pick a host, tap into its
library. Unconfigured it follows the most recent host; a configured
host that was removed shows the empty state rather than silently
following a different host. Same .never timeline + HostStore push as
the hosts widget, now reloading both kinds.
DeepLink.browse(host:) is the one emitter both doors share, covered by
a round-trip test beside connect's; the parse side was already in the
grammar and the vector file. Docs updated (clients, game-library,
profiles-and-links).
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
The reserved
punktfunk://browse/<host-ref>route now routes on the Apple client, and two new front doors emit it — both round-tripping through the one URL router, so there is no second code path.What's new
Shortcuts / Siri / Spotlight — a new Open Game Library intent beside Connect / Wake / End Stream. Host-parameterized like the others (
HostEntitypicker), foregrounds the app and lands in that host's library with nothing streaming yet. Phrases: "Open ⟨host⟩ library in Punktfunk" / "Show ⟨host⟩ games in Punktfunk".A configurable library widget (kind
PunktfunkLibrary; small + both Lock-Screen families) — long-press → Edit Widget picks a saved host (theAppIntentConfigurationtheHostEntitydoc comment always anticipated); a tap opens that host's library. Unconfigured it follows the most recent host. A configured host that was later removed shows the empty state rather than silently following a different host — a widget that says "Studio" must never open someone else's library. Same.nevertimeline + push-reload design as the hosts widget;HostStorenow reloads both kinds.The route
ContentView.openLibrary(from:)drives the samelibraryTargetevery internal surface writes, so a link lands in whichever presentation the current mode owns: the gamepad console's in-place library screen, the touch cover, the macOS sheet, or tvOS's cover.Connect's posture minus the connect itself:
fp=vs. the stored identity) → hard refusal with a noticelaunch=/profile=on a browse are ignored, not refused — nothing streams until a title is picked, and that connect resolves its own profilewakestays reserved (Shortcuts users have the Wake Host intent, which never round-trips through a URL). Other clients keep answeringbrowsewith a notice; the parse side was already in the shared grammar and the vector file, so nothing moves cross-language.DeepLink.browse(host:)is the shared emitter, covered by a round-trip test beside connect's — the same backward-compatibility stakes: a Home-Screen widget keeps sending yesterday's URL.Docs updated: clients, game-library, profiles-and-links.
Verified
swift build+ fullswift test(CI parity) — green, including the new round-trip testswift build --triple arm64-apple-{ios,tvos}17.0) — greenxcodebuildofPunktfunkWidgetsExtensionfor the iOS Simulator — greenThe reserved punktfunk://browse/<host-ref> route now routes on Apple: it drives the same libraryTarget every internal surface writes, so the link lands in whichever presentation the current mode owns — the gamepad console's in-place library screen, the touch cover, the macOS sheet, or tvOS's cover. Connect's posture minus the connect: a pin conflict refuses, a live session is never preempted, an unsaved host gets a notice (the library rides the paired mTLS identity, so there is nothing to browse before the host is saved). browse ignores launch=/profile= — nothing streams until a title is picked, and that connect resolves its own profile. On top of the route, the two new front doors: - OpenLibraryIntent ("Open Game Library") beside Connect/Wake/End in Shortcuts/Siri/Spotlight, host-parameterized like the others and round-tripping through the URL — one router, no second path. - A configurable library widget (kind "PunktfunkLibrary", AppIntentConfiguration over HostEntity — the configuration the HostEntity doc comment anticipated): pick a host, tap into its library. Unconfigured it follows the most recent host; a configured host that was removed shows the empty state rather than silently following a different host. Same .never timeline + HostStore push as the hosts widget, now reloading both kinds. DeepLink.browse(host:) is the one emitter both doors share, covered by a round-trip test beside connect's; the parse side was already in the grammar and the vector file. Docs updated (clients, game-library, profiles-and-links).