diff --git a/docs/community/contribute/first-time.md b/docs/community/contribute/first-time.md
index 3913edb..9cde414 100644
--- a/docs/community/contribute/first-time.md
+++ b/docs/community/contribute/first-time.md
@@ -29,27 +29,38 @@ git remote add upstream https://github.com/OpenDataEnsemble/OpenDataEnsemble.git
### 2. Set Up Your Development Environment
-Depending on which component you want to contribute to:
+Depending on which component you want to contribute to.
+
+ODE JavaScript packages use **pnpm** (not npm). Enable the pinned version once per machine:
+
+```bash
+corepack enable
+corepack prepare pnpm@10.33.2 --activate
+```
+
+Build `@ode/tokens` before Formulus or Formplayer. See [Development Setup](/docs/development/setup#package-manager-pnpm).
**For mobile app (Formulus):**
```bash
+cd packages/tokens && pnpm install && pnpm run build && cd ../..
cd formulus
-npm install
-npm run start
+pnpm install
+pnpm start
```
**For web app (Formplayer):**
```bash
-cd formplayer
-npm install
-npm run start
+cd packages/tokens && pnpm install && pnpm run build && cd ../..
+cd formulus-formplayer
+pnpm install
+pnpm start
```
**For backend server (Synkronus):**
```bash
cd synkronus
go mod download
-go run ./cmd/server
+go run ./cmd/synkronus
```
For detailed setup instructions, see the relevant component's development guide:
@@ -109,8 +120,9 @@ Use conventional commit format:
If your change affects functionality, write tests:
```bash
-# Run tests for your component
-cd formulus && npm test
+# Run tests for your component (from repo root)
+cd formulus && pnpm run test --ci --coverage --watchAll=false
+cd formulus-formplayer && pnpm run test run
cd synkronus && go test ./...
```
@@ -210,9 +222,9 @@ Once your PR is approved and merged, you're officially a contributor! Your code
- [Mobile Development](/docs/development/formulus-development)
**Contributing to Documentation:**
-- Documentation uses Markdown and Docusaurus
-- Edit files in `/docs` folder
-- Run `npm run start` to preview changes
+- Documentation lives in the separate [docs](https://github.com/OpenDataEnsemble/docs) repository (Markdown + Docusaurus)
+- That site still uses **npm** for its own tooling (`npm install`, `npm start` in the docs repo)
+- ODE application code in this monorepo uses **pnpm** (see above)
- Follow the same PR process for doc changes
### Common Tasks for First-Time Contributors
diff --git a/docs/developer/developer-getting-started.md b/docs/developer/developer-getting-started.md
index 310c243..ee00b64 100644
--- a/docs/developer/developer-getting-started.md
+++ b/docs/developer/developer-getting-started.md
@@ -97,6 +97,8 @@ brew install node go postgresql git
```bash
sudo apt-get update
sudo apt-get install nodejs npm golang postgresql git
+# Enable pnpm for the ODE monorepo (pinned in package.json files):
+# corepack enable && corepack prepare pnpm@10.33.2 --activate
```
**Windows:**
@@ -288,13 +290,13 @@ ODE maintains high standards:
### JavaScript/TypeScript
```bash
# Run linter
-npm run lint
+pnpm run lint
# Auto-fix issues
-npm run lint:fix
+pnpm run lint:fix
# Format code
-npm run format
+pnpm run format
```
### Go
diff --git a/docs/development/building-testing.md b/docs/development/building-testing.md
index fb56592..f1cf732 100644
--- a/docs/development/building-testing.md
+++ b/docs/development/building-testing.md
@@ -17,9 +17,10 @@ Build the React Native mobile application:
```bash
cd formulus
-npm install
-npm run android # For Android
-npm run ios # For iOS (macOS only)
+cd ../packages/tokens && pnpm install && pnpm run build && cd ../formulus
+pnpm install
+pnpm run android # For Android
+pnpm run ios # For iOS (macOS only)
```
@@ -54,18 +55,18 @@ Or build from Xcode:
Build the React web form renderer:
```bash
-cd formulus-formplayer
-npm install
-npm run build
+cd ../packages/tokens && pnpm install && pnpm run build && cd ../formulus-formplayer
+pnpm install
+pnpm run build
```
-**Build for React Native:**
+**Build and copy into Formulus (and Desktop):**
```bash
-npm run build:rn
+pnpm run build:copy
```
-This builds and copies the output to the Formulus app.
+This builds and copies the output to the Formulus app (and ODE Desktop when using the full pipeline).
### Synkronus
@@ -125,7 +126,7 @@ go build -o bin/synk ./cmd/synkronus
```bash
cd formulus
-npm test
+pnpm run test --ci --coverage --watchAll=false
```
Runs Jest tests with React Native Testing Library.
@@ -134,10 +135,10 @@ Runs Jest tests with React Native Testing Library.
```bash
cd formulus-formplayer
-npm test
+pnpm run test run
```
-Runs Jest tests for React components.
+Runs Vitest for React components.
### Backend Testing
@@ -187,13 +188,13 @@ E2E testing will be added as the testing infrastructure evolves.
```bash
# Formulus
cd formulus
-npm run lint
-npm run lint:fix
+pnpm run lint
+pnpm run lint:fix
# Formplayer
cd formulus-formplayer
-npm run lint
-npm run lint:fix
+pnpm run lint
+pnpm run lint:fix
```
**Backend:**
@@ -210,10 +211,10 @@ golangci-lint run # If configured
```bash
# Format code
-npm run format
+pnpm run format
# Check formatting
-npm run format:check
+pnpm run format:check
```
**Backend:**
@@ -250,8 +251,8 @@ Run CI checks locally:
```bash
# Frontend
-cd formulus && npm run lint && npm run format:check && npm test
-cd formulus-formplayer && npm run lint && npm run format:check && npm test
+cd formulus && pnpm run lint && pnpm run format:check && pnpm run test --ci --coverage --watchAll=false
+cd formulus-formplayer && pnpm run lint && pnpm run format:check && pnpm run test run
# Backend
cd synkronus && go test ./... && go fmt ./...
@@ -318,8 +319,8 @@ git push origin v1.0.0
```bash
# Clear and reinstall
-rm -rf node_modules package-lock.json
-npm install
+rm -rf node_modules
+pnpm install
```
### Go Module Issues
@@ -338,7 +339,7 @@ go mod tidy
cd android
./gradlew clean
cd ..
-npm run android
+pnpm run android
```
### iOS Build Issues
@@ -349,7 +350,7 @@ cd ios
rm -rf Pods Podfile.lock
bundle exec pod install
cd ..
-npm run ios
+pnpm run ios
```
## Related Documentation
diff --git a/docs/development/contributing.md b/docs/development/contributing.md
index a8582ca..aab09c5 100644
--- a/docs/development/contributing.md
+++ b/docs/development/contributing.md
@@ -58,13 +58,12 @@ Use descriptive branch names:
### 5. Test Your Changes
```bash
-# Frontend projects
-npm test
-npm run lint
-npm run format:check
+# Frontend projects (from each package directory; see Development Setup for pnpm)
+cd formulus && pnpm run lint && pnpm run format:check && pnpm run test --ci --coverage --watchAll=false
+cd formulus-formplayer && pnpm run lint && pnpm run format:check && pnpm run test run
# Go projects
-go test ./...
+cd synkronus && go test ./...
go fmt ./...
```
@@ -171,10 +170,10 @@ func (s *Service) GetUser(username string) (*User, error) {
Ensure your code passes all quality checks:
```bash
-# Frontend
-npm run lint
-npm run format:check
-npm test
+# Frontend (pnpm, per package directory)
+pnpm run lint
+pnpm run format:check
+pnpm run test
# Backend
go test ./...
diff --git a/docs/development/formplayer-development.md b/docs/development/formplayer-development.md
index e5f106e..341cd7f 100644
--- a/docs/development/formplayer-development.md
+++ b/docs/development/formplayer-development.md
@@ -12,25 +12,27 @@ Formplayer is a React web application that renders JSON Forms. It runs within We
## Prerequisites
-- **Node.js** 18+ and npm
+- **Node.js** 20+ and **pnpm** 10.33.2
- **React** development experience
+- **`@ode/tokens` built** — from `packages/tokens`: `pnpm install && pnpm run build` (see [Development Setup](/docs/development/setup#package-manager-pnpm))
## Local Development
### Setup
```bash
+cd packages/tokens && pnpm install && pnpm run build && cd ../..
cd formulus-formplayer
-npm install
+pnpm install
```
### Development Server
```bash
-npm start
+pnpm start
```
-Opens at http://localhost:3000
+Opens at http://localhost:3000 (or the port Vite prints).
### Development Features
@@ -40,25 +42,30 @@ Opens at http://localhost:3000
## Building
-### Build for React Native
-
-Build and copy to Formulus app:
+### Build and copy to Formulus (and ODE Desktop)
```bash
-npm run build:rn
+pnpm run build:copy
```
This:
-1. Builds the React app
-2. Copies build to Formulus app directory
-3. Updates WebView assets
-### Build for Web
+1. Syncs the Formulus interface definition
+2. Builds the React app (`build/`)
+3. Copies assets into Formulus Android/iOS formplayer directories
+4. Copies assets into `desktop/public/formplayer_dist/` when building the full pipeline
-Standard web build:
+From **ODE Desktop** only (requires an existing `formulus-formplayer/build/`):
```bash
-npm run build
+cd desktop
+pnpm copy:formplayer
+```
+
+### Build for Web only
+
+```bash
+pnpm run build
```
Output in `build/` directory.
@@ -82,14 +89,15 @@ Output in `build/` directory.
2. **Register in Formplayer:**
Add to Formplayer configuration when initialized by Formulus.
+When you change `formulus/src/webview/FormulusInterfaceDefinition.ts`, run `pnpm run sync-interface` (or `pnpm run build`) in formulus-formplayer.
+
## Testing
```bash
-npm test
+pnpm run test run
```
## Related Documentation
- [Formplayer Reference](/reference/formplayer) - Component reference
- [Form Design Guide](/guides/form-design) - Creating forms
-
diff --git a/docs/development/formulus-development.md b/docs/development/formulus-development.md
index b859545..49ba525 100644
--- a/docs/development/formulus-development.md
+++ b/docs/development/formulus-development.md
@@ -14,7 +14,7 @@ This guide covers local development and production building for the Formulus Rea
### Required Tools
-- **Node.js** 18+ and npm
+- **Node.js** 20+ and **pnpm** 10.33.2 (see [Development Setup](/docs/development/setup#package-manager-pnpm))
- **React Native CLI** or Expo CLI
- **Java Development Kit (JDK)** 11 or higher
- **Android Studio** (for Android development)
@@ -48,7 +48,8 @@ cd ode/formulus
### Step 2: Install Dependencies
```bash
-npm install
+cd ../packages/tokens && pnpm install && pnpm run build && cd ../formulus
+pnpm install
```
### Step 3: Install iOS Dependencies
@@ -76,7 +77,7 @@ iOS development is only available on macOS. Skip this step if you're developing
Generate the Synkronus API client from OpenAPI spec:
```bash
-npm run generate:api
+pnpm run generate:api
```
### Step 5: Generate WebView Injection Script
@@ -84,13 +85,13 @@ npm run generate:api
Generate the JavaScript injection script:
```bash
-npm run generate
+pnpm run generate
```
### Step 6: Start Metro Bundler
```bash
-npm start
+pnpm start
```
Keep this terminal open. Metro is the JavaScript bundler.
@@ -101,7 +102,7 @@ Keep this terminal open. Metro is the JavaScript bundler.
```bash
-npm run android
+pnpm run android
```
This will:
@@ -114,7 +115,7 @@ This will:
```bash
-npm run ios
+pnpm run ios
```
This will:
@@ -201,11 +202,11 @@ For iOS development, Windows is not supported. Use macOS with Xcode.
### Testing
```bash
-# Run tests
-npm test
+# Run tests (do not use `pnpm test -- --watch`; use pnpm run test)
+pnpm run test
-# Run tests in watch mode
-npm test -- --watch
+# CI-style run
+pnpm run test --ci --coverage --watchAll=false
```
## Building for Production
@@ -291,7 +292,7 @@ AAB location: `android/app/build/outputs/bundle/release/app-release.aab`
### Adding Dependencies
```bash
-npm install package-name
+pnpm add package-name
```
For native dependencies, may need to:
@@ -309,7 +310,7 @@ cd ios && pod install && cd ..
When Synkronus API changes:
```bash
-npm run generate:api
+pnpm run generate:api
```
### Updating WebView Interface
@@ -317,7 +318,7 @@ npm run generate:api
When Formulus interface changes:
```bash
-npm run generate
+pnpm run generate
```
### Cleaning Build
@@ -331,7 +332,7 @@ cd ios && xcodebuild clean && cd ..
# Remove node_modules
rm -rf node_modules
-npm install
+pnpm install
```
## Troubleshooting
@@ -339,7 +340,8 @@ npm install
### Common Issues
**Metro Bundler Won't Start:**
-- Clear Metro cache: `npm start -- --reset-cache`
+- Clear Metro cache: `pnpm start -- --reset-cache`
+- Android: if Gradle reports missing `:notifee_core`, run `pnpm run vendor:notifee` (or use `pnpm run android`, which runs it via `preandroid`)
- Delete `node_modules` and reinstall
**Build Fails:**
diff --git a/docs/development/installation.md b/docs/development/installation.md
index 0851037..fffd9c2 100644
--- a/docs/development/installation.md
+++ b/docs/development/installation.md
@@ -18,7 +18,7 @@ Before installing ODE components, ensure your system meets the following require
|-------------|---------|-------------|
| **Operating System** | macOS 10.15, Windows 10, or Linux | Latest stable version |
| **Node.js** | 20.0 or higher | Latest stable |
-| **npm** | 10.0 or higher | Latest stable |
+| **pnpm** | 10.33.2 (via Corepack or global install) | Match `packageManager` in ODE `package.json` files |
| **Android Studio** | Latest stable | Latest stable |
| **Xcode** | 14.0 or higher (macOS only) | Latest stable |
| **Java Development Kit** | JDK 17 | JDK 17 or higher |
@@ -57,8 +57,8 @@ Verify your installation by running:
# Check Node.js version
node --version
-# Check npm version
-npm --version
+# Check pnpm version
+pnpm --version
# Check Go version
go version
@@ -79,8 +79,8 @@ Using PowerShell:
# Check Node.js version
node --version
-# Check npm version
-npm --version
+# Check pnpm version
+pnpm --version
# Check Go version
go version
@@ -96,7 +96,7 @@ Or using Git Bash/WSL (same commands as Linux/macOS):
```bash
node --version
-npm --version
+pnpm --version
go version
psql --version
docker --version
@@ -156,7 +156,9 @@ git clone https://github.com/OpenDataEnsemble/ode.git
cd ode
# Build the Synkronus portal first
-cd synkronus-portal && npm ci && npm run build && cd ..
+cd packages/tokens && pnpm install --frozen-lockfile && pnpm run build && cd ../..
+cd packages/components && pnpm install --frozen-lockfile && cd ..
+cd synkronus-portal && pnpm install --frozen-lockfile && pnpm run build && cd ..
# Build and run Synkronus
cd synkronus
@@ -175,7 +177,9 @@ git clone https://github.com/OpenDataEnsemble/ode.git
cd ode
# Build the Synkronus portal first
-cd synkronus-portal && npm ci && npm run build && cd ..
+cd packages/tokens && pnpm install --frozen-lockfile && pnpm run build && cd ../..
+cd packages/components && pnpm install --frozen-lockfile && cd ..
+cd synkronus-portal && pnpm install --frozen-lockfile && pnpm run build && cd ..
# Build and run Synkronus
cd synkronus
@@ -190,7 +194,9 @@ git clone https://github.com/OpenDataEnsemble/ode.git
cd ode
# Build the Synkronus portal first
-cd synkronus-portal && npm ci && npm run build && cd ..
+cd packages/tokens && pnpm install --frozen-lockfile && pnpm run build && cd ../..
+cd packages/components && pnpm install --frozen-lockfile && cd ..
+cd synkronus-portal && pnpm install --frozen-lockfile && pnpm run build && cd ..
# Build and run Synkronus
cd synkronus
diff --git a/docs/development/installing-formulus-dev.md b/docs/development/installing-formulus-dev.md
index 2314ee6..3865d53 100644
--- a/docs/development/installing-formulus-dev.md
+++ b/docs/development/installing-formulus-dev.md
@@ -264,7 +264,7 @@ adb devices
```bash
# Build APK first (if not already built)
cd formulus
-npm run android
+pnpm run android
# Install on emulator
adb -s emulator-5554 install android/app/build/outputs/apk/debug/app-debug.apk
@@ -276,7 +276,7 @@ adb -s emulator-5554 install android/app/build/outputs/apk/debug/app-debug.apk
```powershell
# Build APK first
cd formulus
-npm run android
+pnpm run android
# Install on emulator
adb -s emulator-5554 install android\app\build\outputs\apk\debug\app-debug.apk
@@ -297,7 +297,7 @@ When configuring Formulus on an emulator to connect to a local server:
### Prerequisites
-- **Node.js** 18+ and npm
+- **Node.js** 20+ and **pnpm** 10.33.2
- **React Native CLI** or **Expo CLI**
- **Java Development Kit (JDK)** 11 or higher
- **Android Studio** with Android SDK
@@ -308,8 +308,9 @@ When configuring Formulus on an emulator to connect to a local server:
```bash
+cd packages/tokens && pnpm install && pnpm run build && cd ../..
cd formulus
-npm install
+pnpm install
```
@@ -322,7 +323,7 @@ npm install
```bash
# In formulus directory
-npm start
+pnpm start
```
Keep this terminal open. Metro is the JavaScript bundler for React Native.
@@ -337,10 +338,10 @@ Keep this terminal open. Metro is the JavaScript bundler for React Native.
```bash
# For Android device (connected via USB)
-npm run android
+pnpm run android
# For Android emulator (must be running)
-npm run android
+pnpm run android
```
diff --git a/docs/development/quick-start.md b/docs/development/quick-start.md
index 4cd160a..4d6d5a6 100644
--- a/docs/development/quick-start.md
+++ b/docs/development/quick-start.md
@@ -33,9 +33,10 @@ The server will be available at `http://localhost:8080`.
Download and install the APK from the [releases page](https://github.com/OpenDataEnsemble/ode/releases), or build from source:
```bash
+cd ode/packages/tokens && pnpm install && pnpm run build && cd ../..
cd ode/formulus
-npm install
-npm run android
+pnpm install
+pnpm run android
```
@@ -44,10 +45,11 @@ npm run android
Build from source (requires macOS and Xcode):
```bash
+cd ode/packages/tokens && pnpm install && pnpm run build && cd ../..
cd ode/formulus
-npm install
+pnpm install
cd ios && bundle install && bundle exec pod install && cd ..
-npm run ios
+pnpm run ios
```
diff --git a/docs/development/setup.md b/docs/development/setup.md
index 2f61cc5..c5c769c 100644
--- a/docs/development/setup.md
+++ b/docs/development/setup.md
@@ -11,7 +11,7 @@ Complete guide to setting up a development environment for ODE.
Before setting up the development environment, ensure you have:
- **Node.js** 20.0 or higher
-- **npm** 10.0 or higher
+- **pnpm** 10.33.2 (ODE pins this via `packageManager` in each package; enable with [Corepack](https://nodejs.org/api/corepack.html): `corepack enable && corepack prepare pnpm@10.33.2 --activate`)
- **Go** 1.24 or higher (for server and CLI development)
- **PostgreSQL** 13.0 or higher (for server development)
- **Git** for version control
@@ -29,9 +29,21 @@ ode/
├── synkronus-cli/ # Go command-line utility
├── synkronus-portal/ # React web portal
└── packages/
- └── tokens/ # Design tokens package
+ ├── tokens/ # Design tokens package
+ └── components/ # Shared UI components
```
+## Package manager (pnpm)
+
+ODE JavaScript/TypeScript packages use **pnpm** (`pnpm@10.33.2` via Corepack) with a **per-package** `pnpm-lock.yaml` (there is no root workspace install). Run `pnpm install` inside each component directory you work on.
+
+**Recommended install order** when setting up several components:
+
+1. `packages/tokens` — `pnpm install` then `pnpm run build`
+2. Consumers — `pnpm install` in `formulus-formplayer`, `formulus`, `packages/components`, `synkronus-portal`, or `desktop` as needed
+
+CI and Docker use `pnpm install --frozen-lockfile` for reproducible installs.
+
## Clone the Repository
```bash
@@ -44,21 +56,24 @@ cd ode
### Setup
```bash
+cd packages/tokens && pnpm install && pnpm run build && cd ../..
cd formulus
-npm install
+pnpm install
```
+Android builds require the Notifee native core (gitignored). `pnpm run android` runs `preandroid` to vendor it automatically; or run `pnpm run vendor:notifee` before `./gradlew` directly.
+
### Running
```bash
# Start Metro bundler
-npm start
+pnpm start
# Run on Android
-npm run android
+pnpm run android
# Run on iOS (macOS only)
-npm run ios
+pnpm run ios
```
### Code Quality
@@ -67,26 +82,26 @@ ODE enforces consistent formatting and linting:
```bash
# Run linting
-npm run lint
+pnpm run lint
# Run linting with auto-fix
-npm run lint:fix
+pnpm run lint:fix
# Format code
-npm run format
+pnpm run format
# Check formatting (no writes)
-npm run format:check
+pnpm run format:check
```
### Generating Files
```bash
# Generate WebView injection script
-npm run generate
+pnpm run generate
# Generate API client from OpenAPI spec
-npm run generate:api
+pnpm run generate:api
```
## Formplayer Development
@@ -94,36 +109,56 @@ npm run generate:api
### Setup
```bash
+cd packages/tokens && pnpm install && pnpm run build && cd ../..
cd formulus-formplayer
-npm install
+pnpm install
```
### Running
```bash
# Development server
-npm start
+pnpm start
-# Build for React Native
-npm run build:rn
+# Build and copy assets into Formulus (and ODE Desktop)
+pnpm run build:copy
```
### Code Quality
```bash
# Run linting
-npm run lint
+pnpm run lint
# Run linting with auto-fix
-npm run lint:fix
+pnpm run lint:fix
# Format code
-npm run format
+pnpm run format
# Check formatting (no writes)
-npm run format:check
+pnpm run format:check
```
+## ODE Desktop Development
+
+### Setup
+
+```bash
+cd packages/tokens && pnpm install && pnpm run build && cd ../..
+cd desktop
+pnpm install
+```
+
+### Running
+
+```bash
+pnpm run dev # Vite dev server
+pnpm run build:tauri # Build formplayer assets + desktop + Tauri app
+```
+
+See [ODE Desktop developer mode](/docs/guides/ode-desktop-developer-mode) for local custom app iteration.
+
## Synkronus Development
### Setup
@@ -202,13 +237,14 @@ Make your code changes following the coding standards.
### 3. Test Locally
```bash
-# Run tests
-npm test # For frontend projects
-go test ./... # For Go projects
+# Run tests (from each package directory)
+cd formulus && pnpm run test --ci --coverage --watchAll=false
+cd formulus-formplayer && pnpm run test run
+go test ./... # For Go projects (from synkronus/, etc.)
# Check code quality
-npm run lint
-npm run format:check
+pnpm run lint
+pnpm run format:check
```
### 4. Commit Changes
@@ -264,13 +300,13 @@ The CI pipeline automatically:
```bash
# Check all components
-cd formulus && npm run lint && cd ..
-cd formulus-formplayer && npm run lint && cd ..
+cd formulus && pnpm run lint && cd ..
+cd formulus-formplayer && pnpm run lint && cd ..
cd synkronus && go test ./... && cd ..
# Format all code
-cd formulus && npm run format && cd ..
-cd formulus-formplayer && npm run format && cd ..
+cd formulus && pnpm run format && cd ..
+cd formulus-formplayer && pnpm run format && cd ..
cd synkronus && go fmt ./... && cd ..
```
@@ -279,11 +315,13 @@ cd synkronus && go fmt ./... && cd ..
### Node Modules Issues
```bash
-# Clear and reinstall
-rm -rf node_modules package-lock.json
-npm install
+# Clear and reinstall (run inside the package directory, e.g. formulus/)
+rm -rf node_modules
+pnpm install
```
+If dependencies are missing after clone, ensure you ran `pnpm install` in that package directory (and built `packages/tokens` first when using `@ode/tokens` or `@ode/components`).
+
### Go Module Issues
```bash
diff --git a/docs/development/synkronus-portal-development.md b/docs/development/synkronus-portal-development.md
index fbfe969..d063088 100644
--- a/docs/development/synkronus-portal-development.md
+++ b/docs/development/synkronus-portal-development.md
@@ -8,10 +8,17 @@ Complete guide for developing the Synkronus Portal web interface.
## Prerequisites
-- **Node.js** 20+ and npm
+- **Node.js** 20+ and **pnpm** 10.33.2
- **Go** 1.22+ (for backend)
- **PostgreSQL** 17+ (for backend)
+Install shared packages before the portal:
+
+```bash
+cd packages/tokens && pnpm install && pnpm run build && cd ../..
+cd packages/components && pnpm install && cd ../..
+```
+
## Local Development Setup
@@ -25,13 +32,13 @@ See [Synkronus Development](/development/synkronus-development) for backend setu
```bash
cd synkronus-portal
-npm install
+pnpm install
```
#### Step 3: Start Development Server
```bash
-npm run dev
+pnpm run dev
```
Portal available at http://localhost:5174
@@ -49,8 +56,8 @@ docker compose up -d postgres synkronus
```bash
cd synkronus-portal
-npm install
-npm run dev
+pnpm install
+pnpm run dev
```
Portal available at http://localhost:5174
@@ -70,10 +77,10 @@ Portal available at http://localhost:5174
### Build
```bash
-npm run build
+pnpm run build
```
-Output in `dist/` directory.
+`prebuild` runs OpenAPI client generation from `../synkronus/openapi/synkronus.yaml`. Output is in `dist/`.
### Docker Production Build
@@ -97,4 +104,3 @@ See [Synkronus Portal Reference](/reference/synkronus-portal) for detailed patte
- [Synkronus Portal Reference](/reference/synkronus-portal) - Component reference
- [Deployment Guide](/guides/deployment) - Production deployment
-
diff --git a/docs/getting-started/architecture-overview.md b/docs/getting-started/architecture-overview.md
index dc90cf8..df9bd75 100644
--- a/docs/getting-started/architecture-overview.md
+++ b/docs/getting-started/architecture-overview.md
@@ -53,7 +53,7 @@ The Synkronus Portal is a React application that gets **embedded directly into t
```
**Build Process:**
-1. Portal built with `npm run build`
+1. Portal built with `pnpm run build` (in `synkronus-portal/`)
2. Build output copied to `synkronus/portal/dist/`
3. Go binary embeds portal using `//go:embed`
4. Portal served at `/portal` route
@@ -129,7 +129,7 @@ Development -> Build -> ZIP Upload -> Server Storage -> Mobile Download
- **Build Tools**: Vite for web apps
### Development Tools
-- **Package Manager**: npm
+- **Package Manager**: pnpm (per-package lockfiles in the ODE monorepo)
- **Code Quality**: ESLint, Prettier, TypeScript
- **Testing**: Jest for unit tests
- **Containerization**: Docker with multi-stage builds
diff --git a/docs/guides/component-library.md b/docs/guides/component-library.md
index b2be504..588abf3 100644
--- a/docs/guides/component-library.md
+++ b/docs/guides/component-library.md
@@ -153,20 +153,22 @@ const Button = ({ variant, size, ...props }) => {
1. **Install dependencies**:
```bash
-cd packages/tokens && npm install
-cd ../components && npm install
+cd packages/tokens && pnpm install
+cd ../components && pnpm install
```
2. **Build tokens**:
```bash
-cd packages/tokens && npm run build
+cd packages/tokens && pnpm run build
```
-3. **Link packages locally**:
+3. **Use packages in an ODE app** (Formulus, formplayer, portal use `file:` dependencies in `package.json`):
```bash
-# In your app directory
-npm link ../packages/tokens
-npm link ../packages/components
+# Example in package.json:
+# "@ode/tokens": "file:../packages/tokens"
+# "@ode/components": "file:../packages/components"
+# Then from that app directory:
+pnpm install
```
### Adding New Tokens
@@ -188,7 +190,7 @@ npm link ../packages/components
2. **Build tokens**:
```bash
-npm run build
+pnpm run build
```
3. **Use in components**:
@@ -371,7 +373,7 @@ export const MyButton = ({ children, onPress }) => (
- Check that packages are installed and linked correctly
**Tokens not working:**
-- Verify tokens are built: `npm run build` in tokens package
+- Verify tokens are built: `pnpm run build` in tokens package
- Check import path: `@ode/tokens`
**Theme not applying:**
diff --git a/docs/guides/custom-applications.md b/docs/guides/custom-applications.md
index f831bba..1b48fa2 100644
--- a/docs/guides/custom-applications.md
+++ b/docs/guides/custom-applications.md
@@ -10,7 +10,11 @@ Complete guide to building and deploying custom applications that integrate with
## Overview
-Custom applications are **web applications** (HTML, CSS, and JavaScript) that run inside the Formulus mobile app’s WebView. You may author them with **any** stack—plain static files, **Vite**, **React**, **Vue**, **Svelte**, or another bundler—**as long as the build output** can be packaged as described in the [app bundle format](/docs/reference/app-bundle-format) (entry HTML, assets, and `forms/` layout). They provide specialized workflows, custom navigation, integration with the ODE form system, and interfaces tailored to your use case.
+Custom applications are **web applications** (HTML, CSS, and JavaScript) that run inside the Formulus mobile app’s WebView.
+
+:::note ODE monorepo vs your custom app
+The **ODE repository** (Formulus, Formplayer, Synkronus Portal, design packages) uses **pnpm** — see [Development Setup](/docs/development/setup#package-manager-pnpm). **Your** custom app project can use **npm**, **pnpm**, or **yarn**; the examples below use common **npm** script names from the [custom_app](https://github.com/OpenDataEnsemble/custom_app) template.
+::: You may author them with **any** stack—plain static files, **Vite**, **React**, **Vue**, **Svelte**, or another bundler—**as long as the build output** can be packaged as described in the [app bundle format](/docs/reference/app-bundle-format) (entry HTML, assets, and `forms/` layout). They provide specialized workflows, custom navigation, integration with the ODE form system, and interfaces tailored to your use case.
## Scaffolding
diff --git a/docs/guides/ode-desktop-developer-mode.md b/docs/guides/ode-desktop-developer-mode.md
index 3729146..f90202e 100644
--- a/docs/guides/ode-desktop-developer-mode.md
+++ b/docs/guides/ode-desktop-developer-mode.md
@@ -1,6 +1,6 @@
# ODE Desktop developer mode
-**Developer mode** in ODE Desktop lets you iterate on a **local custom app build** (for example `dist/` after `npm run build`) against a profile’s real observations and workspace, without replacing the bundle you downloaded from Synkronus.
+**Developer mode** in ODE Desktop lets you iterate on a **local custom app build** (for example `dist/` after your app’s build command, such as `npm run build` or `pnpm run build`) against a profile’s real observations and workspace, without replacing the bundle you downloaded from Synkronus. Building **ODE Desktop** itself uses **pnpm** — see [Development Setup](/docs/development/setup#package-manager-pnpm).
## What it is
diff --git a/docs/guides/quick-start-custom-app.md b/docs/guides/quick-start-custom-app.md
index cfe5a3b..b867f84 100644
--- a/docs/guides/quick-start-custom-app.md
+++ b/docs/guides/quick-start-custom-app.md
@@ -10,7 +10,7 @@ Create and deploy a custom ODE application in 30 minutes using this step-by-step
**Prerequisites:**
- ODE server running (see [Installation Guide](/docs/getting-started/installation))
-- Node.js 20+ and npm 10+
+- Node.js 20+ and npm 10+ (for **your custom app** project; the ODE monorepo uses **pnpm** — see [Development Setup](/docs/development/setup#package-manager-pnpm))
- Basic knowledge of React/JavaScript
- Text editor (VS Code recommended)
@@ -541,14 +541,14 @@ synk app-bundle upload app-bundles/bundle-v1.0.0.zip --activate
### 12.1 Install Formulus App
-**Android:**
+**Android (build Formulus from the ODE repo):**
```bash
-# Install APK via ADB
-npm run android
-
-# Or install from Google Play Store (search "Formulus")
+cd ode/packages/tokens && pnpm install && pnpm run build && cd ../..
+cd ode/formulus && pnpm install && pnpm run android
```
+Or install a release APK / from an app store when available.
+
### 12.2 Configure App
1. Open Formulus app
diff --git a/docs/reference/formplayer.md b/docs/reference/formplayer.md
index 3d40272..3655753 100644
--- a/docs/reference/formplayer.md
+++ b/docs/reference/formplayer.md
@@ -371,23 +371,24 @@ Themes can be customized:
### Development Build
```bash
-# Install dependencies
-npm install
+# Install dependencies (build @ode/tokens first)
+cd ../packages/tokens && pnpm install && pnpm run build && cd ../formulus-formplayer
+pnpm install
# Start development server
-npm start
+pnpm start
-# Opens at http://localhost:3000
+# Opens at http://localhost:3000 (or Vite's printed port)
```
### Production Build
```bash
-# Build for React Native (Formulus)
-npm run build:rn
+# Build and copy into Formulus (and ODE Desktop)
+pnpm run build:copy
-# Build for web
-npm run build
+# Build for web only
+pnpm run build
```
### Build Output
@@ -488,7 +489,7 @@ Error handling for:
### Local Development
-1. **Start Dev Server**: `npm start`
+1. **Start Dev Server**: `pnpm start`
2. **Open Browser**: Navigate to `http://localhost:3000`
3. **Hot Reload**: Changes reflect automatically
diff --git a/docs/reference/formulus.md b/docs/reference/formulus.md
index 6aac942..30cc057 100644
--- a/docs/reference/formulus.md
+++ b/docs/reference/formulus.md
@@ -269,23 +269,24 @@ See [Formulus Development Guide](/development/formulus-development) for complete
### Key Development Commands
```bash
-# Install dependencies
-npm install
+# Install dependencies (build @ode/tokens first; see Development Setup)
+cd ../packages/tokens && pnpm install && pnpm run build && cd ../formulus
+pnpm install
# Start Metro bundler
-npm start
+pnpm start
-# Run on Android
-npm run android
+# Run on Android (vendors Notifee via preandroid)
+pnpm run android
# Run on iOS
-npm run ios
+pnpm run ios
# Generate API client from OpenAPI spec
-npm run generate:api
+pnpm run generate:api
# Generate WebView injection script
-npm run generate
+pnpm run generate
```
### Project Structure
diff --git a/docs/reference/synkronus-portal.md b/docs/reference/synkronus-portal.md
index 05823f6..257748d 100644
--- a/docs/reference/synkronus-portal.md
+++ b/docs/reference/synkronus-portal.md
@@ -147,7 +147,7 @@ The API service handles errors:
**Start Development:**
```bash
-npm run dev
+pnpm run dev
```
### Production Mode
@@ -159,7 +159,7 @@ npm run dev
**Build for Production:**
```bash
-npm run build
+pnpm run build
```
### Environment Variables
@@ -187,7 +187,7 @@ docker compose up -d
Build and serve with any static file server:
```bash
-npm run build
+pnpm run build
# Serve dist/ directory
```
@@ -197,7 +197,7 @@ npm run build
1. **Install Dependencies:**
```bash
- npm install
+ pnpm install
```
2. **Start Backend:**
@@ -208,7 +208,7 @@ npm run build
3. **Start Portal:**
```bash
- npm run dev
+ pnpm run dev
```
4. **Access Portal:**