Strongtie Design System
Getting StartedComponents

Search documentation

Search for a command to run or a page to navigate to.

Getting Started
  • Introduction
  • Setup Guide
  • Package Installation
  • Styles Only (CSS)
  • Code Quality Setup
  • Resources
Guides
  • Framework Recommendations
  • Design Standards
  • Design Standards Examples
AI-Assisted Development
  • AI Agent Guide
  • AI Agent Skills
  • AGENTS.md Template
Registry
  • Getting Started
  • Combobox
  • Datepicker
  • MultiSelect
  • Tab Nav
  • Tree
Foundations
  • States
  • Variables
Migrations
  • Migration Guide
  • CDN Migration Guide
  • Telerik Migration
Governance
  • Governance Model
  • Contribution Model
Components
  • Accordion
  • Alert
  • Alert Dialog
  • Avatar
  • Badge
  • Breadcrumb
  • Button
  • Button Group
  • Calendar
  • Card
  • Carousel
  • Chart
  • Checkbox
  • Collapsible
  • Combobox
  • Command
  • Context Menu
  • Date Picker
  • Dialog
  • Drawer
  • Dropdown Menu
  • Empty
  • Field
  • Form
  • Hover Card
  • Input
  • Input Group
  • Input Otp
  • Item
  • Kbd
  • Label
  • Menubar
  • Multi Select
  • Navigation Menu
  • Pagination
  • Popover
  • Progress
  • Radio Group
  • Resizable
  • Scroll Area
  • Select
  • Separator
  • Sheet
  • Sidebar
  • Skeleton
  • Slider
  • Sonner
  • Spinner
  • Switch
  • Tab Nav
  • Table
  • Tabs
  • Textarea
  • Toaster
  • Toggle
  • Toggle Group
  • Tooltip
  • Tree
2026 Simpson Strong-Tie
  1. Getting Started
  2. Code Quality Setup

Code Quality Setup

PreviousNext

ESLint, Prettier, and Stylelint configuration for Simpson Strong-Tie projects using Ultracite.

The @strongtie code quality packages provide pre-configured linting and formatting for Simpson Strong-Tie projects. They extend Ultracite with company-specific rule overrides.

ESLint 9 and 10 both supported. The @strongtie/eslint package declares a peer range of ^9.0.0 || ^10.0.0. ESLint 10 is now the recommended version — the earlier eslint-plugin-react incompatibility has been resolved.

What's Included

PackageDescription
@strongtie/eslintESLint rules for TypeScript, React, and accessibility
@strongtie/prettierPrettier config (re-exports Ultracite)
@strongtie/stylelintStylelint config with Tailwind CSS support

Prerequisites

  • Node.js >= 22.0.0
  • npm >= 10.0.0
  • TypeScript project with tsconfig.json

Installation

Configure Azure Artifacts

The packages are hosted on Azure Artifacts (Simpson feed). Create a .npmrc file in your project root:

.npmrc
@strongtie:registry=https://pkgs.dev.azure.com/StrongTie/_packaging/Simpson/npm/registry/
@strongtie:always-auth=true
registry=https://registry.npmjs.org/

Important: Use @strongtie:registry (scoped) to ensure only @strongtie/* packages use Azure Artifacts authentication.

Install Core Dependencies

First, install Ultracite, ESLint, Prettier, and Stylelint:

npm install -D ultracite@^7 eslint@^10 prettier@^3 stylelint@^17

ESLint 10 is recommended. ESLint 9 is also supported if you need it (eslint@^9) — the @strongtie/eslint peer range is ^9.0.0 || ^10.0.0.

Install @strongtie Packages

npm install -D @strongtie/eslint @strongtie/prettier @strongtie/stylelint

Install ESLint Peer Dependencies

npm install -D \
  @typescript-eslint/eslint-plugin@^8 \
  @typescript-eslint/parser@^8 \
  eslint-config-prettier@^10 \
  eslint-import-resolver-typescript@^4 \
  eslint-plugin-compat@^7 \
  eslint-plugin-cypress@^6 \
  eslint-plugin-github@^6 \
  eslint-plugin-html@^8 \
  eslint-plugin-import@^2 \
  eslint-plugin-jest@^29 \
  eslint-plugin-jsx-a11y@^6 \
  eslint-plugin-n@^18 \
  eslint-plugin-prettier@^5 \
  eslint-plugin-promise@^7 \
  eslint-plugin-react@^7 \
  eslint-plugin-react-hooks@^7 \
  eslint-plugin-sonarjs@^4 \
  eslint-plugin-storybook@^10 \
  eslint-plugin-unicorn@^70 \
  eslint-plugin-unused-imports@^4 \
  globals@^17

Install Stylelint Peer Dependencies

npm install -D \
  stylelint-config-standard@^37 \
  stylelint-config-idiomatic-order@^10 \
  stylelint-prettier@^5

Create Configuration Files

Create the following configuration files in your project root:

ESLint Configuration:

eslint.config.mjs
import base from "@strongtie/eslint/base"
import react from "@strongtie/eslint/react"
import { defineConfig } from "eslint/config"
 
export default defineConfig([
  // Global ignores
  {
    ignores: [
      "**/dist/",
      "**/build/",
      "**/.next/",
      "**/.turbo/",
      "**/node_modules/",
      "**/*.config.ts",
      "**/*.config.mjs",
      "**/*.d.ts",
      "**/*.json",
      "components/ui/**/*",
    ],
  },
 
  // Base TypeScript config (auto-detects ./tsconfig.json)
  ...base(),
 
  // React/JSX config
  ...react,
])

Prettier Configuration:

prettier.config.mjs
export { default } from "@strongtie/prettier"

Stylelint Configuration:

stylelint.config.mjs
export { default } from "@strongtie/stylelint"

Create Ignore Files

Create .prettierignore in your project root:

.prettierignore
# Build outputs
dist/
build/
 
# Test coverage
coverage/
 
# Dependencies
node_modules/
.yalc/
 
# Config files
*.config.ts
*.config.mjs
*.config.js
 
# Type definitions
**/*.d.ts
 
# JSON files
**/*.json
 
# UI components (shadcn/ui)
components/ui/

Create .stylelintignore in your project root:

.stylelintignore
# Build outputs
dist/
build/
 
# Coverage
coverage/
 
# Dependencies
node_modules/
.yalc/
 
# Non-CSS files
**/*.ts
**/*.tsx
**/*.js
**/*.jsx
**/*.mjs
**/*.cjs
**/*.json
**/*.md
 
# Config files
*.config.*
 
# UI components (shadcn/ui)
components/ui/

Add Scripts to package.json

package.json
{
  "scripts": {
    "check": "ultracite check",
    "fix": "ultracite fix",
    "lint": "eslint .",
    "lint:fix": "eslint --fix .",
    "lint:css": "stylelint '**/*.css'",
    "lint:css:fix": "stylelint '**/*.css' --fix",
    "format": "prettier --check .",
    "format:fix": "prettier --write ."
  }
}

Verify Installation

# Check for issues without fixing
npm run check
 
# Auto-fix issues
npm run fix
 
# Run ESLint
npm run lint
 
# Run Stylelint
npm run lint:css
 
# Check formatting
npm run format

Configuration Options

Custom TypeScript Project Paths

For monorepos or custom tsconfig locations, pass the project option:

eslint.config.mjs
import base from "@strongtie/eslint/base"
import react from "@strongtie/eslint/react"
 
export default [
  { ignores: ["**/dist/", "**/node_modules/"] },
 
  // Monorepo with multiple tsconfig files
  ...base({
    project: ["./apps/*/tsconfig.json", "./packages/*/tsconfig.json"],
  }),
 
  ...react,
]

Node.js Scripts Config

For build scripts and tooling that run in Node.js:

eslint.config.mjs
import base from "@strongtie/eslint/base"
import react from "@strongtie/eslint/react"
import scripts from "@strongtie/eslint/scripts"
 
export default [
  { ignores: ["**/dist/"] },
  ...base(),
  ...react,
  ...scripts, // Relaxes rules for scripts/**/*.{js,mjs,ts}
]

Vite Projects (React Refresh)

For Vite projects, add the react-refresh plugin:

npm install -D eslint-plugin-react-refresh
eslint.config.mjs
import base from "@strongtie/eslint/base"
import react from "@strongtie/eslint/react"
import reactRefresh from "eslint-plugin-react-refresh"
import { defineConfig } from "eslint/config"
 
export default defineConfig([
  { ignores: ["**/dist/"] },
  ...base(),
  ...react,
  {
    plugins: {
      "react-refresh": reactRefresh,
    },
    rules: {
      "react-refresh/only-export-components": [
        "warn",
        { allowConstantExport: true },
      ],
    },
  },
])

Named Imports

You can also use named imports:

eslint.config.mjs
import { base, react, scripts } from "@strongtie/eslint"
 
export default [...base(), ...react, ...scripts]

What Rules Are Configured

TypeScript Rules (Relaxed)

The package relaxes several strict TypeScript rules for practical development:

RuleSettingReason
@typescript-eslint/no-unsafe-*offToo strict for real-world code
@typescript-eslint/no-floating-promisesoffCommon in React Query callbacks
@typescript-eslint/no-non-null-assertionwarnCan cause runtime errors
@typescript-eslint/no-shadowwarnVariable shadowing causes confusion
@typescript-eslint/prefer-nullish-coalescingoff|| is often intentional for falsy coalescing
@typescript-eslint/use-unknown-in-catch-callback-variableoffToo strict for practical catch handling

React Rules

RuleSettingReason
react/jsx-indent*offHandled by Prettier/Biome
react/jsx-no-constructed-context-valuesoffReact 19 Compiler handles memoization
react/function-component-definitionoffNext.js uses export default function
react-hooks/purityoffToo strict for practical use
react-hooks/todooffReact Compiler not yet adopted
react-hooks/immutabilityoffReact Compiler not yet adopted

Accessibility Rules

RuleSettingReason
jsx-a11y/prefer-tag-over-rolewarnEncourages semantic HTML over ARIA

Code Style

RuleSettingReason
no-consolewarnAllowed in development
no-nested-ternaryoffSometimes clearer than if/else
unicorn/filename-caseoffExisting codebase conventions
unicorn/number-literal-caseoffConflicts with Prettier
unicorn/no-await-expression-memberoff(await foo).bar is valid
sonarjs/cognitive-complexityoffHandled elsewhere
sonarjs/different-types-comparisonoffSSR check pattern is valid
logical-assignment-operatorsoffStylistic preference
no-await-in-loopoffSometimes necessary

Custom Rules

The @strongtie/eslint package includes custom ESLint rules:

RuleSettingReason
@strongtie/no-static-inline-styleerrorUse Tailwind or CSS modules instead of inline styles
// ❌ Bad - static inline styles
<div style={{ color: "red" }} />
<div style={{ margin: 0, padding: 10 }} />
 
// ✅ OK - dynamic content (allowed)
<div style={{ color: dynamicColor }} />
<div style={{ width: `${size}px` }} />
<div style={styleObject} />

Stylelint Rules

RuleSettingReason
at-rule-no-unknownAllows TailwindSupports @tailwind, @apply, @layer, etc.

Monorepo Setup

For monorepos using Turbo:

turbo.json
{
  "tasks": {
    "lint": {
      "dependsOn": ["^lint"],
      "outputs": []
    },
    "check": {
      "outputs": []
    },
    "fix": {
      "outputs": []
    }
  }
}

Each workspace package should have its own config files or inherit from the root.

Troubleshooting

Plugin Compatibility Errors

If you see an error like this (older versions of eslint-plugin-react on ESLint 10):

TypeError: Error while loading rule 'react/boolean-prop-naming': contextOrFilename.getFilename is not a function

Update your ESLint plugins to their latest major versions — this incompatibility is fixed in current releases:

npm install -D eslint@^10 eslint-plugin-react@^7 eslint-plugin-react-hooks@^7

Missing Peer Dependencies

If you see Cannot find package 'eslint-plugin-*' errors, install the missing peer dependencies from Step 4 above.

TypeScript Parser Errors

Ensure your tsconfig.json includes all files being linted:

tsconfig.json
{
  "include": ["src/**/*", "**/*.ts", "**/*.tsx"]
}

ESLint Binary Not Found

If npm run lint fails with "command not found":

npm install -D eslint@^10

Stylelint CSS Parsing Errors

If Stylelint reports errors on non-CSS files, ensure your .stylelintignore excludes them (see Step 7 above).

Next Steps

Design Standards

Learn the design patterns and best practices for React applications.

AGENTS.md Template

Get the AGENTS.md template for AI-assisted development.

Getting StartedInstalling the @strongtie/design-system Package

On This Page

What's IncludedPrerequisitesInstallationConfiguration OptionsCustom TypeScript Project PathsNode.js Scripts ConfigVite Projects (React Refresh)Named ImportsWhat Rules Are ConfiguredTypeScript Rules (Relaxed)React RulesAccessibility RulesCode StyleCustom RulesStylelint RulesMonorepo SetupTroubleshootingPlugin Compatibility ErrorsMissing Peer DependenciesTypeScript Parser ErrorsESLint Binary Not FoundStylelint CSS Parsing ErrorsNext Steps

Contribute

  • Report an issue
  • Request a feature
  • Edit this page