Prefer native platform behaviour in companion apps
Shared logic should not flatten the menus, links, contextual actions and navigation people expect. Explain a native-first approach, selective hybrid surfaces and shared app semantics without implying that a dual-target compiler already exists.
3 files changed,
+95
−2
README.md+6 −2SKILL.md+29 −0docs/app-architecture.md+60 −0
CI passed — run details
Intent
diff --git a/README.md b/README.md| index 4bdebe9..7eaf6e6 100644 |
| --- a/README.md |
| +++ b/README.md |
| @@ -44,8 +44,12 @@ bundle identifiers, and add your app's screens. Run `xcodegen generate` in |
| the copied directory and open `Companion.xcodeproj`. Sign with your own team |
| for physical devices or distribution. |
| -Use native platform views for navigation and controls. A webview can reuse |
| -an existing web screen where that suits the app. Bind shared Go logic only |
| +Prefer fully native UI so navigation, menus, contextual actions, links and |
| +accessibility meet the platform's expectations. For a complex app, keep a |
| +native shell around selected webview screens. A shared app manifest can |
| +describe destinations and commands for separate web and native renderers; |
| +that is a possible architecture, not a compiler supplied by this kit. See |
| +[docs/app-architecture.md](docs/app-architecture.md). Bind shared Go logic only |
| when it removes duplication: see [docs/go-mobile.md](docs/go-mobile.md). |
| ## Validate |
diff --git a/SKILL.md b/SKILL.md| index c5c145e..e0855ce 100644 |
| --- a/SKILL.md |
| +++ b/SKILL.md |
| @@ -17,6 +17,35 @@ and revision, set app-owned bundle IDs, run `xcodegen generate`. The example |
| checks `/api/version` only; it supplies no authenticated session. The app |
| owns linking, navigation, storage, signing and release policy. |
| +## Prefer native UI |
| + |
| +Aim for a fully native interface wherever practical. Meeting the platform's |
| +expectations can substantially improve daily use: navigation, selection, |
| +menus, context menus/right-click, keyboard shortcuts, accessibility, links, |
| +windows and system sharing should behave as people already expect. Treat |
| +those behaviours as part of the feature, not final polish. Share logic and |
| +contracts freely; let each platform own how the feature is presented. |
| + |
| +For a complex app, a native navigation layer around selected webview screens |
| +can avoid duplicating a large working surface. Use that as a deliberate |
| +boundary: keep app navigation, menus, contextual actions and link routing |
| +native, and expose typed actions from the embedded screen. Route internal |
| +links to native destinations and ordinary external links through the |
| +platform's normal browser behaviour. Do not intercept text editing or |
| +replace useful web behaviour with a less capable native imitation. |
| + |
| +If both clients would otherwise duplicate navigation and action definitions, |
| +consider a shared app manifest compiled into separate web and native |
| +presentations. Share destination IDs, available commands, capabilities and |
| +link intent; each renderer chooses platform-appropriate controls. A command |
| +may appear in a web toolbar, a Mac menu/context menu, or an iPhone action |
| +menu. Avoid encoding DOM trees, pixel layout or one platform's navigation |
| +model as the common schema. See [docs/app-architecture.md](docs/app-architecture.md). |
| +This is architectural guidance, not an existing dual-target generator; |
| +Rastrillo's current resource manifests generate web CRUD only. |
| + |
| +## Shared components |
| + |
| `@MainActor CoalescedRunner.run` serializes one refresh operation. A burst |
| during a pass queues one trailing pass; callers await its completion. |
| Trailing passes reuse the first caller's closure. Keep one runner per |
diff --git a/docs/app-architecture.md b/docs/app-architecture.md| new file mode 100644 |
| index 0000000..58b5f52 |
| --- /dev/null |
| +++ b/docs/app-architecture.md |
| @@ -0,0 +1,60 @@ |
| +# Build for the platform |
| + |
| +Prefer fully native UI when practical. The gain is in everyday behaviour: |
| +the app responds to the menus, keyboard, selection, accessibility and |
| +navigation habits a person brings from the rest of their device. A familiar |
| +appearance alone does not deliver that improvement. |
| + |
| +Use platform controls and conventions for navigation, menus, contextual |
| +actions, links, windows, drag/drop, sharing and keyboard interaction. |
| +Desktop right-click should expose the relevant context menu. Link actions |
| +should support the platform's expectations for opening, copying and sharing |
| +destinations; do not reduce every link to a JavaScript click handler. |
| +Accessibility semantics and focus behaviour belong in the first implementation. |
| + |
| +## When a hybrid app is appropriate |
| + |
| +A complex editor, feed or established interactive screen can justify reuse |
| +through a webview. Keep the app shell and navigation native and choose |
| +individual embedded surfaces deliberately. Give the embedded content a |
| +narrow, typed bridge for app commands and navigation intents. The native |
| +host resolves those intents to native screens, contextual actions and |
| +system services. It should not need to inspect DOM text to discover meaning. |
| + |
| +Internal app destinations open through native navigation. External web |
| +destinations follow the platform's browser conventions, including the |
| +person's choice where applicable. Preserve useful editing, selection and |
| +accessibility behaviour inside the web surface. Avoid replacing a capable |
| +web editor merely to increase the percentage of native code. |
| + |
| +For encrypted content, bridge capabilities stay narrow. Pass only what the |
| +embedded surface needs; a webview that displays one conversation need not |
| +receive the account's private key or another conversation's keys. |
| + |
| +## A shared app manifest |
| + |
| +When navigation and commands are repeated across clients, consider a |
| +manifest of app meaning with separate web and native compilers/renderers. |
| +It can describe stable destination IDs, route parameters, commands, |
| +capabilities, labels/localisation keys and link intent. The app's server |
| +still enforces permissions; hiding a command is not authorisation. |
| + |
| +For example, the common definition can say a document supports `open`, |
| +`rename`, `share` and `delete`, and identify their handlers. The web renderer |
| +can use routes, anchors, forms and a toolbar; the Mac renderer can use |
| +windows, menu commands and right-click actions; the iPhone renderer can use |
| +navigation stacks, toolbars and action menus. Destructive confirmation and |
| +disabled/unavailable actions need explicit meaning in that contract. |
| + |
| +Keep DOM structure, coordinates and platform-specific navigation stacks out |
| +of the common schema. Provide platform overrides for presentation and |
| +capabilities rather than forcing the least capable shared layout everywhere. |
| +Share business rules, API contracts and test vectors below the renderers. |
| + |
| +The first proof should be a real feature rendered for web and native, with |
| +tests for destinations and action semantics plus platform UI tests. Extract |
| +the manifest schema after that proof, rather than designing a universal |
| +compiler before either client works. |
| + |
| +No such compiler ships in the initial kit. Rastrillo's existing resource |
| +manifests generate server-rendered web CRUD; they are a separate mechanism. |