Migrate or upgrade TypeScript tooling in the Phoenix monorepo. Use when upgrading TypeScript versions, switching tools (ESLint to oxlint, Prettier to oxfmt), upgrading bundlers (Vite, esbuild), or making major dependency upgrades. Triggers on requests to migrate, upgrade, or replace TypeScript/JavaScript tooling.
70
88%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
Guide for migrating or upgrading TypeScript tooling in the Phoenix monorepo. This skill covers upgrading core dependencies (TypeScript, React), switching tools (linters, formatters, bundlers), and managing breaking changes across js/app/ and js/ directories.
All TypeScript code lives in a single pnpm workspace rooted at js/:
| Directory | Purpose |
|---|---|
js/app/ | React/TypeScript frontend (main Phoenix UI, workspace package phoenix-ui) |
js/packages/* | Publishable TypeScript packages (phoenix-client, phoenix-evals, etc.) |
js/ | Workspace root: single pnpm-lock.yaml, pnpm-workspace.yaml, .pnpmfile.cjs |
Shared tooling versions are managed at the workspace root where possible:
| Tool | Config Location |
|---|---|
| pnpm | js/package.json → packageManager |
| TypeScript | package.json → devDependencies (keep js/app and js root aligned) |
| oxlint | package.json → devDependencies (keep js/app and js root aligned) |
| oxfmt | package.json → devDependencies (keep js/app and js root aligned) |
| Config | Location | Purpose |
|---|---|---|
.oxlintrc.json | Root + js/app/ + js/ | Linter config (nested inheritance) |
.oxfmtrc.jsonc | Root | Formatter config (shared) |
tsconfig.json | js/app/ and js/ packages | TypeScript config |
vite.config.ts | js/app/ | Build/dev server config |
relay.config.js | js/app/ | GraphQL/Relay config |
Complete replacement of one tool with another.
Workflow:
Upgrading a tool to a new major version with breaking changes.
Workflow:
Upgrading a core dependency that affects application code.
Workflow:
js/app/, js/, or both)git checkout -b chore/migrate-<tool>-to-<version>
# or
git checkout -b chore/upgrade-<tool>-<version># For js/app/ (the app workspace package)
cd js/app && pnpm add -D <package>@<version>
# For js/ (workspace root)
cd js && pnpm add -D -w <package>@<version>
# For upgrading existing dependencies
cd js/app && pnpm update <package>@<version>Tip: Keep old tool installed until migration is verified for tool replacements.
Phoenix uses nested configs with inheritance where possible:
phoenix/
├── .<tool>rc.json # Shared base config
├── js/app/
│ └── .<tool>rc.json # Extends base, adds React-specific options
└── js/
└── .<tool>rc.json # Extends base, adds Node-specific optionsConfig inheritance pattern:
{
"$schema": "./node_modules/<tool>/configuration_schema.json",
"extends": ["../.<tool>rc.json"]
}Tip: Use the tool's own CLI to identify issues:
pnpm run typecheck # TypeScript errors
pnpm run lint # Linter errors
pnpm run build # Build errorsUpdate both js/app/package.json and js/package.json if script invocations changed:
{
"scripts": {
"lint": "<new-command>",
"typecheck": "<new-command>"
}
}Edit .pre-commit-config.yaml if the tool is used in pre-commit:
- id: <tool>-app
name: <tool> (app)
entry: pnpm --dir js/app run <script>
language: system
files: ^js/app/.*\.[jt]sx?$
pass_filenames: false
- id: <tool>-js
name: <tool> (js)
entry: pnpm --dir js run <script>
language: system
files: ^js/.*\.[jt]sx?$
pass_filenames: false.vscode/extensions.json if extensions changedDEVELOPMENT.md:{
"<extension>.path.<binary>": "js/app/node_modules/<package>/bin/<binary>"
}Note: .vscode/settings.json is gitignored - document settings in DEVELOPMENT.md.
# Remove old dependencies
cd js/app && pnpm remove <old-tool> <old-plugins>
cd js && pnpm remove -w <old-tool> <old-plugins>
# Delete old config files
rm js/app/<old-config> js/<old-config># Type checking
cd js/app && pnpm run typecheck
cd js && pnpm run typecheck
# Linting
cd js/app && pnpm run lint
cd js && pnpm run lint
# Formatting
cd js/app && pnpm run fmt:check
cd js && pnpm run fmt:check
# Unit tests
cd js/app && pnpm test
cd js && pnpm run -r test
# Build
cd js/app && pnpm run build
cd js && pnpm run -r build
# E2E tests (for significant changes)
cd js/app && pnpm run test:e2e
# Pre-commit hooks
pre-commit run --all-filesFiles to check and update:
| File | What to update |
|---|---|
AGENTS.md | Tool versions, commands, style conventions |
DEVELOPMENT.md | Setup instructions, VS Code settings |
js/app/README.md | Tool references, test commands |
.cursor/rules/typescript-packages/RULE.md | Commands, workflow instructions |
.claude/settings.json | PostToolUse hooks |
CHANGELOG.md | Note significant tooling changes |
The app (js/app/package.json) and the workspace root (js/package.json) both
declare shared tooling (typescript, oxlint, oxfmt). Keep those versions aligned
when upgrading — the single lockfile makes drift visible in review.
When upgrading shared tooling, upgrade js/app/ and the js/ workspace root together. Version drift causes subtle bugs and CI failures.
eslint-disable comments)| Scenario | Approach |
|---|---|
| Identical config for both dirs | Single root config |
| Shared base + dir-specific overrides | Root config + nested configs with extends |
| Completely different configs per dir | Separate configs (no inheritance) |
These directories have their own tooling and should NOT be included in migrations:
scripts/docker/devops/oidc-server/ - Separate OIDC test serverscripts/mock-llm-server/ - Separate mock serverinternal_docs/ - Internal documentation utilitiesStricter type checking: New TypeScript versions often add stricter checks. Fix errors by:
tsconfig.json to temporarily relax checks if neededDependency type mismatches: Ensure @types/* packages are compatible with the new TS version.
rm -rf node_modules/.cache js/app/dist js/**/distpnpm installpnpm run build$schema path is relative to the config file locationextends path (e.g., "../.toolrc.json")Cmd+Shift+P → "Reload Window")pnpm install in both directoriespackage.json matches hook entrypnpm --dir js/app run <script>.nvmrc)pnpm-lock.yaml)--frozen-lockfile locally to match CI behaviorRelevant CI files for TypeScript tooling:
| Workflow | Purpose |
|---|---|
.github/workflows/typescript-CI.yml | Whole js/ workspace (app + packages): build, typecheck, fmt, lint, codegen drift, test |
.github/workflows/playwright.yaml | E2E tests |
Arize-ai/phoenix
8ac3caf
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.