@iviva/uxp-lint
v0.0.8
Published
Linting and validation tool for iviva v5 UXP apps
Readme
uxp-lint
Code quality and linting for iviva v5 UXP React apps. Enforces the patterns established across the System, Location, and User reference apps.
What it checks
| Group | What's validated |
|---|---|
| Configuration.yml | pageId format, nav group structure, duplicate links, otherRoutes redirects |
| bundle.json | label/component key consistency, registerUI/bundle.json ID sync, localization order |
| Bulk Imports | name attribute on root XML element |
| Folder Structure | one .tsx per views/ subfolder, forms in forms/, services.ts present |
| Code Quality (ESLint) | TypeScript + React recommended rules + 9 custom UXP rules |
| Formatting (Prettier) | All .ts/.tsx/.scss files match project Prettier config |
| SCSS Rules | App-prefix class naming, no top-level .uxp-* overrides |
| Bundle Size | dist/main.js under configured limit (default 1 MB) |
| Duplicate Code | Code clones ≥ 10 lines |
Run uxp-lint rules to see all rules with severity.
Run uxp-lint rules <rule-id> for full documentation on any rule.
Installation
CLI
Install as a dev dependency in the app you want to lint:
npm install -D @iviva/uxp-lintAdd scripts to the app's package.json:
"scripts": {
"lint": "uxp-lint",
"fix": "uxp-lint fix",
"lint:ci": "uxp-lint --ci"
}VSCode Extension
The extension shows squiggly lines and Problems panel entries as you code, and provides Quick Fix actions for common issues — no need to run the CLI manually.
Download and install:
# Download the latest .vsix from the internal distribution
curl -L https://uxp.iviva.com/tools/uxp-lint/latest/uxp-lint-vscode.vsix \
-o /tmp/uxp-lint-vscode.vsix
# Install into VSCode
code --install-extension /tmp/uxp-lint-vscode.vsixOr from within VSCode: Extensions panel → ⋯ → Install from VSIX…
If you have @iviva/uxp-lint installed globally or as a dev dependency, you can also run:
uxp-lint install-vscodePoint the extension at your local build (if @iviva/uxp-lint is not in PATH):
Open VSCode settings and set:
"uxp-lint.binaryPath": "/path/to/your/app/node_modules/.bin/uxp-lint"The extension auto-detects the binary in this order:
uxp-lint.binaryPathsetting- Local
node_modules/.bin/uxp-lintin the workspace - Global
uxp-linton PATH - Falls back to
npx @iviva/uxp-lint
Setup
On first run, if no config is found, an interactive wizard creates .uxplint/config.json:
uxp-lint
# or explicitly:
uxp-lint setupThe wizard asks for your app's source path, bundle path, and rule preferences. The generated config is added to .gitignore automatically.
Manual config — create .uxplint/config.json at the app root:
{
"v5": true,
"viewsSrc": "./Resources/views/src",
"configYml": "./Configuration.yml",
"bundleJson": "./Resources/views/bundle.json",
"bulkImportsDir": "./BulkImports",
"appPrefix": "isystemapp_",
"rules": {},
"bundleSize": { "maxKb": 1024, "severity": "warn" },
"duplication": { "minLines": 10, "severity": "warn" },
"ai": { "enabled": false, "model": "claude-sonnet-4-6" }
}Override rule severity:
{
"rules": {
"no-hardcoded-jsx-text": "error",
"no-native-html-interactive": "off"
}
}The SCSS validator auto-detects the app prefix from global.scss. Set appPrefix explicitly if auto-detection doesn't pick it up.
Usage
Analyse
uxp-lint # analyse and show all issues
uxp-lint --ci # CI mode — exits 1 on any error, no prompts
uxp-lint --report # also write full report to .uxplint/report.txt
uxp-lint --report out.txt # write report to a specific file
uxp-lint --ai # include AI-powered code review (needs ANTHROPIC_API_KEY)Fix
uxp-lint fix # apply all quick fixes (deterministic, no AI needed)
uxp-lint fix --dry-run # preview what would change without writing files
uxp-lint fix --rule uxp/no-fa-prefix # fix one rule only
uxp-lint fix --file src/views/MyView.tsx # fix one file only
uxp-lint fix --ai # AI-powered fixes (requires Claude / ANTHROPIC_API_KEY)
uxp-lint fix --ai --dry-run
uxp-lint fix --ai --warnings # include warnings (default: errors only)
uxp-lint fix --ai --report .uxplint/report.txt # reuse existing reportRules
uxp-lint rules # list all rules with severity
uxp-lint rules uxp/no-fa-prefix # full docs: description, rationale, fix
uxp-lint rules @typescript-eslint/no-explicit-anyCI pipeline
# GitHub Actions example
- name: Lint
run: npx @iviva/uxp-lint --ciExit code is 0 for pass, 1 for any errors.
Quick fixes (VSCode + CLI)
The following rules have automatic quick fixes, available as VSCode code actions and via uxp-lint fix:
| Rule | Fix |
|---|---|
| uxp/require-memo | Wrap component with memo(), extract base component if needed |
| uxp/no-fa-prefix | Remove fa- from icon strings |
| uxp/no-inline-styles | Extract inline style to .scss file using app prefix |
| uxp/no-hardcoded-jsx-text | Add key to localization.json and replace with $L('key') |
| uxp/no-bad-hook-deps | Remove stable ref from useCallback/useMemo deps array |
| uxp/no-native-html-interactive | Insert TODO comment with UXP component suggestion |
| @typescript-eslint/no-explicit-any | Replace with unknown or typed placeholder |
Rules reference
| Severity | Rule | Category |
|---|---|---|
| warn | uxp/require-memo | React |
| error | uxp/no-inline-styles | React |
| error | uxp/url-params-form-state | React |
| warn | uxp/no-bad-hook-deps | React |
| warn | uxp/no-hardcoded-jsx-text | Patterns |
| warn | uxp/no-native-html-interactive | Patterns |
| error | uxp/service-config-shape | Standards |
| error | uxp/no-fa-prefix | Standards |
| warn | uxp/event-name-format | Standards |
| error | @typescript-eslint/no-explicit-any | Standards |
| warn | bundle-size | Configuration |
| warn | duplication | Configuration |
| warn | folder-structure | Configuration |
| warn | scss-app-prefix | SCSS |
| error | no-direct-uxp-override | SCSS |
Run uxp-lint rules <id> for the rationale and fix guidance for any rule.
Terminal output
Messages are grouped by file within each check group:
── Code Quality (ESLint)
src/views/ConfigurationsView.tsx 2 errors 1 warning
src/views/ConfigurationsView.tsx:14:3 error Component "ConfigurationsView" is not wrapped with memo() [uxp/require-memo]
src/views/ConfigurationsView.tsx:28:12 error Avoid inline styles. Move styles to SCSS and use className. [uxp/no-inline-styles]
src/views/ConfigurationsView.tsx:61:5 warn Hardcoded text "Save Changes" [uxp/no-hardcoded-jsx-text]A summary table is always printed at the end:
┌──────────────────────────────────┬────────┬──────────┬────────────┐
│ Group │ Status │ Errors │ Warnings │
├──────────────────────────────────┼────────┼──────────┼────────────┤
│ Configuration.yml │ ✔ │ – │ – │
│ Code Quality (ESLint) │ ✗ │ 2 │ 1 │
│ SCSS Rules │ ✔ │ – │ – │
├──────────────────────────────────┼────────┼──────────┼────────────┤
│ Total │ │ 2 │ 1 │
└──────────────────────────────────┴────────┴──────────┴────────────┘Each message line includes a file:line:col link — Ctrl+click in any terminal to jump directly to the issue.
