Amends 0295
(decision 2, the sections of
defineApp; decision 6, the closed set of code hatches; decision 12,
the AppShortcuts menu kind),
0281 (the MenuKind list
in its note) and
0307 (a
NativeWidget placement). It keeps 0058 (Electron is the desktop
implementation) and 0249 (one app, several
targets). Each amended page carries a note that says what changed and which of its decisions
stand.Context
An app’s name, identifiers and store text are written in several places: the name indefineApp, the bundle
identifier in the platform section, and the metadata of the web, desktop and store builds in their own files. The
desktop section of ADR 0295 is named electron, and the PWA options sit outside the one app definition. App
shortcuts would be written by hand in a menu file and kept in step by hand, and native home-screen widgets are not
covered by any ADR. The owner decided these points in the final structure review of 2026-10-24.
Decision
Identity.- One
identitysection.stackra.config.tsholds oneidentitysection with the app id in reverse-DNS form, the bundle identifier of each platform, the name, short name, description and copyright, the publisher and the support URL. - Text comes from the lang files. The name, short name, description and copyright are lang keys, so each
locale’s value comes from its catalogue in
assets/lang(ADR 0305, lang files). English and Arabic are set there, not in the config. - Gen feeds every target from identity. Gen feeds the web manifest, the Electron build, the Expo configuration,
the store listings and the HTML head from
identity. No other file repeats those values. - One app id. The app id is written once, in
identity. The desktop section takes no app id of its own.
desktopreplaceselectron. Theelectronsection ofdefineApp, in ADR 0295 decision 2, is renameddesktop. Electron stays the implementation (0058, 0249). This ADR changes the section’s name and not its role. The Electron code hatch of ADR 0295 decision 6,electron.extend.ts, is renameddesktop.extend.tswith it.
- PWA options are the
pwasection. The PWA options are thepwasection ofstackra.config.ts, a section that ADR 0295 decision 2 already lists. pwa.extend.tsis a hatch for caching only. The PWA runtime-caching hatch ispwa.extend.ts, which follows the<tool>.extend.tspattern of ADR 0295 decision 6. It holds runtime caching rules and nothing else. It joins that decision’s closed set and carries itsReason:header and manifest entry.
-
A route declares its shortcut. A route declares
appShortcut: { icon, labelKey }, as in this example: -
Gen emits every shortcut from the declarations. From the same declarations, gen emits:
- the PWA manifest
shortcuts; - the Electron jump list and dock menu;
- the mobile quick actions, shown on long-press through
expo-quick-actions.
- the PWA manifest
-
stackra.configonly orders and caps.stackra.config.tsorders the shortcuts and caps their number. It declares none. TheAppShortcutsmenu kind of ADR 0295 decision 12 is retired for this purpose. -
Keyboard shortcuts are a different thing. Keyboard shortcuts stay in
@stackra/shortcuts, with the app’sshortcuts/group of.shortcut.tsfiles. An app shortcut is never a keyboard shortcut. -
Icons.
icontakes a named icon, such asIcons.House, as ADR 0309 decides. How the icon constants are generated is the subject of 0322, not of this one.
- A
NativeWidgetplacement. iOS WidgetKit widgets and Android Glance widgets are aNativeWidgetplacement that reuses an existing Widget query (0307). The placement adds no query of its own. - An Expo config plugin writes the native code. An Expo config plugin generates the Swift and Kotlin pieces of the widget. Nobody writes them by hand.
- PWAs have no home-screen widgets. A PWA has no home-screen widgets on iOS or Android, so the web target generates none.
Consequences
- An app’s name, identifiers and store text have one home, and the store listing and the UI read the same keys.
- Derived shortcuts follow the routes: a route that is removed takes its shortcut with it.
- A config that still writes
electronis a breaking change for that member. Members convert in STA-344. - Native widgets need a native build. The Expo config plugin is the only generator of their Swift and Kotlin code.
- The desktop section keeps Electron’s name out of the config keys but not out of the implementation.
Enforcement
- planned — gen check: every
identitykey resolves in each locale that the app ships. No work item yet. - planned — STA-339, the bundle identifier check of ADR 0295 applies to the bundle identifiers in
identity. - planned — gen check: a route’s
appShortcuthas an icon and alabelKeythat resolves in each shipped locale. No work item yet. - planned — the
pwa.extend.tshatch check of ADR 0295 decision 6 (aReason:header and a manifest entry) applies to it, as STA-339 plans for every hatch. - planned — a test that the Expo config plugin’s Swift and Kotlin output compiles for iOS and Android. No work item yet.
Supersedes and sources
Supersedes: none. Amends: 0295 (decisions 2, 6 and 12), 0281 (theMenuKind
list) and 0307 (a NativeWidget
placement). Keeps 0058, 0249
and 0309. Sources: the owner’s decisions in
the final structure review of 2026-10-24 (STA-428).