diff --git a/.browserslistrc b/.browserslistrc
deleted file mode 100644
index cb0f4177d..000000000
--- a/.browserslistrc
+++ /dev/null
@@ -1 +0,0 @@
-Electron 9.4.4
diff --git a/.editorconfig b/.editorconfig
deleted file mode 100644
index a7092c29d..000000000
--- a/.editorconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-root = true
-
-[*]
-indent_style = space
-indent_size = 2
-end_of_line = lf
-charset = utf-8
-trim_trailing_whitespace = true
-insert_final_newline = true
-
-[package.json]
-# Match Cordova edit behavior
-insert_final_newline = false
diff --git a/.env b/.env
deleted file mode 100644
index 8255993a6..000000000
--- a/.env
+++ /dev/null
@@ -1,3 +0,0 @@
-REACT_APP_SCRIPT_SRC_CSP=''
-REACT_APP_CONNECT_SRC_CSP=''
-NODE_ENV='development'
diff --git a/.eslintignore b/.eslintignore
index ea488711f..551293df2 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1,3 +1,2 @@
src/ui
-src/protocol-validation
network-canvas
diff --git a/.eslintrc.json b/.eslintrc.json
deleted file mode 100644
index 338d8dd26..000000000
--- a/.eslintrc.json
+++ /dev/null
@@ -1,50 +0,0 @@
-{
- "root": true,
- "extends": "airbnb",
- "env": {
- "browser": true,
- "commonjs": true,
- "es2020": true,
- "node": true
- },
- "parser": "@babel/eslint-parser",
- "parserOptions": {
- "ecmaVersion": 2018,
- "ecmaFeatures": {
- "jsx": true,
- "spread": true,
- "experimentalObjectRestSpread": true,
- "object-shorthand": ["error", "always"]
- },
- "sourceType": "module"
- },
- "plugins": ["react"],
- "rules": {
- "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
- "no-console": "error",
- "import/no-extraneous-dependencies": ["error", {"optionalDependencies": false, "peerDependencies": false}],
- "jsx-a11y/no-static-element-interactions": "off",
- "jsx-a11y/click-events-have-key-events": "off",
- "jsx-a11y/anchor-is-valid": "off"
- },
- "settings": {
- "import/resolver": {
- "alias": [
- ["@app", "./src"],
- ["@components", "./src/components"],
- ["@modules", "./src/ducks/modules"],
- ["@selectors", "./src/selectors"],
- ["@hooks", "./src/hooks"],
- ["@utils", "./src/utils"]
- ]
- }
- },
- "overrides": [
- {
- "files": "*.test.js",
- "rules": {
- "react/jsx-props-no-spreading": "off"
- }
- }
- ]
-}
diff --git a/.github/workflows/dist.yml b/.github/workflows/dist.yml
deleted file mode 100644
index 40915198b..000000000
--- a/.github/workflows/dist.yml
+++ /dev/null
@@ -1,46 +0,0 @@
-name: Dist
-on:
- push:
- branches:
- - "release/**"
-
- # Allows you to run this workflow manually from the Actions tab
- workflow_dispatch:
-
-jobs:
- dist:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- with:
- submodules: recursive
- - uses: actions/setup-python@v4
- with:
- python-version: "3.10.12"
- # update apt cache
- - name: Update apt cache
- run: sudo apt-get update -y
- # Set node version
- - uses: actions/setup-node@v4
- with:
- node-version: "14.21.3"
- - name: Set NPM 7
- run: npm install -g npm@8.19.4
- # Cache node_modules
- - uses: actions/cache@v4
- env:
- cache-name: cache-node-modules
- with:
- path: "**/node_modules"
- key: ${{ runner.os }}-modules-${{ hashFiles('**/package-lock.json') }}
-
- - name: Install MDNS build dependencies
- run: sudo apt-get install libavahi-compat-libdnssd-dev
-
- - name: Install node modules
- run: npm install
-
- - name: Linux build
- run: npm run dist:linux -- --publish always
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
deleted file mode 100644
index 3322c7c59..000000000
--- a/.github/workflows/main.yml
+++ /dev/null
@@ -1,83 +0,0 @@
-name: CI
-on:
- push:
- branches: [master]
- pull_request:
-
- # Allows you to run this workflow manually from the Actions tab
- workflow_dispatch:
-
-jobs:
- test:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- with:
- submodules: recursive
- - uses: actions/setup-python@v4
- with:
- python-version: "3.10.12"
- # update apt cache
- - name: Update apt cache
- run: sudo apt-get update -y
- # Set node version
- - uses: actions/setup-node@v4
- with:
- node-version: "14.21.3"
- - name: Set NPM 7
- run: npm install -g npm@8.19.4
- # Cache node_modules
- - uses: actions/cache@v4
- env:
- cache-name: cache-node-modules
- with:
- path: "**/node_modules"
- key: ${{ runner.os }}-modules-${{ hashFiles('**/package-lock.json') }}
-
- - name: Install MDNS build dependencies
- run: sudo apt-get install libavahi-compat-libdnssd-dev
-
- - name: Install node modules
- run: npm install
-
- - name: Lint
- run: npm run lint -- --max-warnings 0 && npm run sass-lint -- --max-warnings 0
-
- - name: Run tests
- run: npm run test
-
- build:
- needs: test
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- with:
- submodules: recursive
- - uses: actions/setup-python@v4
- with:
- python-version: "3.10.12"
- # update apt cache
- - name: Update apt cache
- run: sudo apt-get update -y
- # Set node version
- - uses: actions/setup-node@v4
- with:
- node-version: "14.21.3"
- - name: Set NPM 7
- run: npm install -g npm@8.19.4
- # Cache node_modules
- - uses: actions/cache@v4
- env:
- cache-name: cache-node-modules
- with:
- path: "**/node_modules"
- key: ${{ runner.os }}-modules-${{ hashFiles('**/package-lock.json') }}
-
- - name: Install MDNS build dependencies
- run: sudo apt-get install libavahi-compat-libdnssd-dev
-
- - name: Install node modules
- run: npm install
-
- - name: Build
- run: npm run build
diff --git a/.gitignore b/.gitignore
index f45501a7f..e1f46b234 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,24 +1,8 @@
+node_modules/
+dist/
+out/
+release-builds/
+.turbo/
+coverage/
+*.log
.DS_Store
-/node_modules
-/bower_components
-/platforms
-/coverage
-/release-builds
-/www
-/app
-/.idea
-/docs-build
-/plugins
-
-# local dev build output
-electron-dev/
-
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-yarn.lock
-
-*.zip
-*.pbxproj
-.vscode
-Icon^M^M
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index 0d91b8345..000000000
--- a/.gitmodules
+++ /dev/null
@@ -1,9 +0,0 @@
-[submodule "network-canvas"]
- path = network-canvas
- url = https://github.com/complexdatacollective/network-canvas.git
-[submodule "src/protocol-validation"]
- path = src/protocol-validation
- url = https://github.com/complexdatacollective/protocol-validation.git
-[submodule "development-protocol"]
- path = development-protocol
- url = https://github.com/complexdatacollective/development-protocol.git
diff --git a/.npmrc b/.npmrc
deleted file mode 100644
index 5a89ce15d..000000000
--- a/.npmrc
+++ /dev/null
@@ -1,2 +0,0 @@
-save-prefix=~
-arch=x64
\ No newline at end of file
diff --git a/.oxlintrc.json b/.oxlintrc.json
new file mode 100644
index 000000000..fde2f3e11
--- /dev/null
+++ b/.oxlintrc.json
@@ -0,0 +1,17 @@
+{
+ "extends": ["../../.oxlintrc.json", "../../tooling/oxlint/react.json"],
+ "rules": {
+ "react/exhaustive-deps": "warn",
+ "no-process-env": "off"
+ },
+ "overrides": [
+ {
+ "files": ["development-protocol/**"],
+ "rules": { "no-unused-vars": "off" }
+ },
+ {
+ "files": ["src/utils/webShims/**"],
+ "rules": { "no-unused-expressions": "off" }
+ }
+ ]
+}
diff --git a/.stylelintrc.json b/.stylelintrc.json
deleted file mode 100644
index d75964a3f..000000000
--- a/.stylelintrc.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "extends": "stylelint-config-standard-scss",
- "rules": {
- "selector-class-pattern": null,
- "custom-property-pattern": null,
- "scss/at-extend-no-missing-placeholder": null
- }
-}
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 000000000..899befc19
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,12 @@
+# network-canvas-architect
+
+## 6.6.0
+
+- **Updated core dependencies.** The technology the app is built on has been brought up to
+ date, which improves stability and performance and lays the groundwork for future
+ improvements.
+- **Compatibility with upcoming macOS versions.** This release ensures the app continues to
+ run smoothly on the latest and upcoming versions of macOS.
+- **Improved security.** We've adopted current security best practices for building and
+ distributing the app — including properly signed and notarized macOS builds — so you can be
+ confident the software you download is genuine and safe to run.
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 000000000..b20f0f6a9
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,140 @@
+# CLAUDE.md
+
+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
+
+## Project Overview
+
+Network Canvas Architect is an Electron + React application for designing Network Canvas interview protocols. It includes a `network-canvas/` directory containing built interviewer assets for interview preview functionality.
+
+## Development Commands
+
+```bash
+# Install dependencies
+pnpm install
+
+# Development
+pnpm run dev # Start electron-vite dev server with HMR
+
+# Build
+pnpm run build # Build production bundle
+pnpm run preview # Preview production build
+
+# Testing (Vitest)
+pnpm test # Run tests once
+pnpm test:watch # Watch mode
+pnpm test:coverage # Run with coverage
+pnpm test:update-snapshots # Update snapshots
+
+# Linting
+pnpm run lint # Run Biome linting
+pnpm run lint:fix # Auto-fix linting and formatting issues
+
+# Distribution
+pnpm run dist:mac # macOS build (x64 + arm64)
+pnpm run dist:linux # Linux build
+pnpm run dist:win # Windows build
+```
+
+## Architecture
+
+### Build System
+
+electron-vite with custom configuration:
+
+- **electron.vite.config.js** - Main, preload, and renderer configuration
+- Main process files are copied (not bundled) due to CommonJS usage
+- Renderer uses Vite with React plugin
+
+### State Management
+
+Redux with ducks pattern (`src/ducks/`):
+
+- **store.js** - Redux store with redux-persist, thunk middleware
+- **modules/root.js** - Root reducer combining all slices
+- **modules/protocol/** - Protocol state (stages, codebook, assets) with timeline middleware for undo/redo
+- **modules/session.js** - Current editing session state
+- **modules/ui/** - UI state (screens, dialogs)
+
+Protocol actions are prefixed with `PROTOCOL/` and tracked by the timeline middleware for undo/redo support.
+
+### Selectors
+
+Reselect-based selectors in `src/selectors/`:
+
+- **protocol.js** - Current protocol data
+- **codebook/** - Node/edge types, variables
+- **indexes.js** - Derived indexes for fast lookups
+- **usage.js** - Track where variables/types are used
+
+### Import Aliases
+
+Configured in `electron.vite.config.js` and `vitest.config.js`:
+
+- `@app` → `src/`
+- `@components` → `src/components/`
+- `@modules` → `src/ducks/modules/`
+- `@selectors` → `src/selectors/`
+- `@hooks` → `src/hooks/`
+- `@utils` → `src/utils/`
+
+### Key Directories
+
+- **src/components/sections/** - Stage editor section components (prompts, forms, panels per interview stage type)
+- **src/components/StageEditor/** - Stage editing UI
+- **src/components/Form/** - Redux-form field components
+- **src/components/Codebook/** - Codebook (types/variables) management UI
+- **src/utils/netcanvasFile/** - `.netcanvas` file format handling (read/write protocols)
+- **src/utils/electronBridge.js** - Secure IPC bridge abstraction for renderer process
+- **src/behaviours/** - Higher-order components for zoom, validation, windowing
+
+### Protocol Structure
+
+A protocol contains:
+
+- `stages[]` - Interview stages configuration
+- `codebook` - Node types, edge types, ego, and their variables
+- `assetManifest` - Media assets (images, audio, video, external data)
+
+### Electron Integration
+
+Security hardened with context isolation:
+
+- **public/electron-starter.js** - Electron main process entry
+- **public/preload/appPreload.js** - Secure IPC bridge (contextBridge)
+- **public/components/ipcHandlers.js** - Main process IPC handlers
+- **src/utils/electronBridge.js** - Renderer-side abstraction for IPC
+
+All Node.js operations happen in the main process via IPC. The renderer has no direct Node.js access.
+
+## Testing
+
+Vitest with Enzyme. Test files use `.test.js` suffix and are co-located with source files in `__tests__/` directories.
+
+Test setup: `config/vitest/setup.js`
+Mock files: `src/__mocks__/`
+
+Snapshot testing is used for component rendering. Update snapshots with:
+
+```bash
+pnpm test:update-snapshots
+```
+
+## Code Style
+
+- Biome for linting and formatting (tabs, double quotes, 120 char width)
+- React 16 with class components and hooks
+- Redux-form for form state
+
+## Prerequisites
+
+- Node.js 22.x (LTS)
+- pnpm 9.x
+
+## Security
+
+This application uses Electron's recommended security model:
+
+- `nodeIntegration: false`
+- `contextIsolation: true`
+- Preload scripts with contextBridge for IPC
+- All file system operations via main process
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index 2e6425172..4d61908df 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -8,19 +8,19 @@ In the interest of fostering an open and welcoming environment, we as contributo
Examples of behavior that contributes to creating a positive environment include:
-* Using welcoming and inclusive language
-* Being respectful of differing viewpoints and experiences
-* Gracefully accepting constructive criticism
-* Focusing on what is best for the community
-* Showing empathy towards other community members
+- Using welcoming and inclusive language
+- Being respectful of differing viewpoints and experiences
+- Gracefully accepting constructive criticism
+- Focusing on what is best for the community
+- Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
-* The use of sexualized language or imagery and unwelcome sexual attention or advances
-* Trolling, insulting/derogatory comments, and personal or political attacks
-* Public or private harassment
-* Publishing others' private information, such as a physical or electronic address, without explicit permission
-* Other conduct which could reasonably be considered inappropriate in a professional setting
+- The use of sexualized language or imagery and unwelcome sexual attention or advances
+- Trolling, insulting/derogatory comments, and personal or political attacks
+- Public or private harassment
+- Publishing others' private information, such as a physical or electronic address, without explicit permission
+- Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
diff --git a/README.md b/README.md
index 40066966a..556748da8 100644
--- a/README.md
+++ b/README.md
@@ -12,10 +12,10 @@ For questions and support, please visit the [Network Canvas User Community](http
### Prerequisites
-- [Node.js](https://nodejs.org/en/) (v14.21.3)
-- [npm](https://www.npmjs.com/) (v8.19.4)
+- [Node.js](https://nodejs.org/en/) (v22.x LTS) - Use [fnm](https://github.com/Schniz/fnm) or [nvm](https://github.com/nvm-sh/nvm) for version management
+- [pnpm](https://pnpm.io/) (v9.x) - Install via `corepack enable` or `npm install -g pnpm`
- [Git](https://git-scm.com/)
-- [Python](https://www.python.org/) (v3.10.12)
+- [Python](https://www.python.org/) (v3.10+) - For native module compilation
### Installation
@@ -31,35 +31,32 @@ git clone https://github.com/complexdatacollective/Architect.git
git submodule update --init --recursive -f
```
-3. Install NPM packages
+3. Install packages with pnpm
```sh
-npm install
+pnpm install
```
-Note: for Apple Silicon users, you need to install the `electron` package manually:
-
-```sh
- npm install electron --arch=x86
-```
+Note: The `.npmrc` file configures x64 architecture for Electron (required until Electron upgrade is complete).
# Operation
-| `npm run
+
+