BookNest exists twice, as Framework7's web app and this chapter's phone app, and both compute the same cart total from the same six books. A monorepo keeps both apps in one repository, with the shared logic in a package of its own. npm 2,036 workspaces suffice; Turborepo 226,392 (2.11.4) and Nx 180,159 (23.2.1) add cached, parallel tasks for many packages. A trial layout, with a Vite 25,978 page standing in for the Framework7 572,986 app:
booknest-mono/
package.json { "private": true, "workspaces": ["apps/*", "packages/*"] }
apps/mobile/ create-expo-app (SDK 57); depends on "@booknest/core": "*"
apps/web/ a Vite page; depends on "@booknest/core": "*"
packages/core/ "name": "@booknest/core", "main": "index.js"
index.js exports books (from booknest-data.json) and cartTotal(items)npm install at the root links each workspace into node_modules/@booknest/, so both apps import { books, cartTotal } from '@booknest/core'. Expo 6,418 's documentation suggests workspace:*, but npm 9.2.0 and 11.20.0 both stopped with EUNSUPPORTEDPROTOCOL: with npm, write *. Since SDK 52 Expo configures Metro for monorepos by itself:
npm ls @booknest/core
npm run build --workspace @booknest/web | grep "assets/"
cd apps/mobile && npx expo export --platform android 2>&1 | grep -E "Bundled|\.hbc"booknest-mono@ /home/dev/lane-ch3/booknest-mono ├── @booknest/core@1.0.0 -> ./packages/core ├─┬ @booknest/mobile@1.0.0 -> ./apps/mobile │ └── @booknest/core@1.0.0 deduped -> ./packages/core └─┬ @booknest/web@0.0.0 -> ./apps/web └── @booknest/core@1.0.0 deduped -> ./packages/core dist/assets/index-BtN4EBmb.js 2.15 kB │ gzip: 1.15 kB Android Bundled 4378ms apps/mobile/index.js (580 modules) _expo/static/js/android/index-2b9f300e33c565ef8cbd5b8a137d8755.hbc (1.4MB)
Metro watched the whole repository (note the apps/mobile/index.js path) and bundled the shared package with no metro.config.js. Keep one version of react and react-native in the repository, since two copies in one app fail at run time, and keep shared packages free of native modules, as plain JavaScript like these cart rules.