| 1 | # Build for the platform |
| 2 | |
| 3 | Prefer fully native UI when practical. The gain is in everyday behaviour: |
| 4 | the app responds to the menus, keyboard, selection, accessibility and |
| 5 | navigation habits a person brings from the rest of their device. A familiar |
| 6 | appearance alone does not deliver that improvement. |
| 7 | |
| 8 | Use platform controls and conventions for navigation, menus, contextual |
| 9 | actions, links, windows, drag/drop, sharing and keyboard interaction. |
| 10 | Desktop right-click should expose the relevant context menu. Link actions |
| 11 | should support the platform's expectations for opening, copying and sharing |
| 12 | destinations; do not reduce every link to a JavaScript click handler. |
| 13 | Accessibility semantics and focus behaviour belong in the first implementation. |
| 14 | |
| 15 | ## When a hybrid app is appropriate |
| 16 | |
| 17 | A complex editor, feed or established interactive screen can justify reuse |
| 18 | through a webview. Keep the app shell and navigation native and choose |
| 19 | individual embedded surfaces deliberately. Give the embedded content a |
| 20 | narrow, typed bridge for app commands and navigation intents. The native |
| 21 | host resolves those intents to native screens, contextual actions and |
| 22 | system services. It should not need to inspect DOM text to discover meaning. |
| 23 | |
| 24 | Internal app destinations open through native navigation. External web |
| 25 | destinations follow the platform's browser conventions, including the |
| 26 | person's choice where applicable. Preserve useful editing, selection and |
| 27 | accessibility behaviour inside the web surface. Avoid replacing a capable |
| 28 | web editor merely to increase the percentage of native code. |
| 29 | |
| 30 | For encrypted content, bridge capabilities stay narrow. Pass only what the |
| 31 | embedded surface needs; a webview that displays one conversation need not |
| 32 | receive the account's private key or another conversation's keys. |
| 33 | |
| 34 | ## A shared app manifest |
| 35 | |
| 36 | When navigation and commands are repeated across clients, consider a |
| 37 | manifest of app meaning with separate web and native compilers/renderers. |
| 38 | It can describe stable destination IDs, route parameters, commands, |
| 39 | capabilities, labels/localisation keys and link intent. The app's server |
| 40 | still enforces permissions; hiding a command is not authorisation. |
| 41 | |
| 42 | For example, the common definition can say a document supports `open`, |
| 43 | `rename`, `share` and `delete`, and identify their handlers. The web renderer |
| 44 | can use routes, anchors, forms and a toolbar; the Mac renderer can use |
| 45 | windows, menu commands and right-click actions; the iPhone renderer can use |
| 46 | navigation stacks, toolbars and action menus. Destructive confirmation and |
| 47 | disabled/unavailable actions need explicit meaning in that contract. |
| 48 | |
| 49 | Keep DOM structure, coordinates and platform-specific navigation stacks out |
| 50 | of the common schema. Provide platform overrides for presentation and |
| 51 | capabilities rather than forcing the least capable shared layout everywhere. |
| 52 | Share business rules, API contracts and test vectors below the renderers. |
| 53 | |
| 54 | The first proof should be a real feature rendered for web and native, with |
| 55 | tests for destinations and action semantics plus platform UI tests. Extract |
| 56 | the manifest schema after that proof, rather than designing a universal |
| 57 | compiler before either client works. |
| 58 | |
| 59 | No such compiler ships in the initial kit. Rastrillo's existing resource |
| 60 | manifests generate server-rendered web CRUD; they are a separate mechanism. |
| 61 | |