Skip to content

Getting Started

Welcome to jmlweb-tooling! This guide will help you get started with our shared configuration packages for modern JavaScript and TypeScript projects.

jmlweb-tooling is a collection of shared configuration packages that provide consistent, opinionated settings for popular development tools:

  • Oxfmt - Fast code formatting with import sorting (recommended)
  • Oxlint - Fast linting for JavaScript, TypeScript, React and Node.js, with type-aware rules (recommended)
  • Prettier and ESLint - The previous formatter and linter configurations, in maintenance mode
  • TypeScript - Strict TypeScript configurations for various project types
  • Testing - Pre-configured Vitest and Jest setups
  • Build Tools - Ready-to-use tsdown and Vite configurations
  • Commit Linting - Conventional Commits enforcement
  • Consistency - Same code style across all your projects
  • Zero Configuration - Works out of the box with sensible defaults
  • Best Practices - Based on industry standards and modern conventions
  • Easy Updates - Update one package to get improvements across all projects
  • Monorepo Friendly - Designed to work seamlessly in monorepo setups

Browse all available packages in the sidebar navigation or explore specific categories below.

Before getting started, ensure you have:

  • Node.js >= 22.12.0 (Download)
  • A package manager: pnpm (recommended), npm, or yarn

Check your Node.js version:

Terminal window
node --version

If you don’t have pnpm installed:

Terminal window
npm install -g pnpm

Let’s set up a new TypeScript project with Oxfmt, Oxlint and TypeScript configurations.

Install the Oxfmt configuration and Oxfmt:

Terminal window
pnpm add -D @jmlweb/oxfmt-config-base oxfmt

Create an oxfmt.config.ts file:

import baseConfig from '@jmlweb/oxfmt-config-base';
import { defineConfig } from 'oxfmt';
export default defineConfig({
...baseConfig,
});

Format your code:

Terminal window
pnpm exec oxfmt

Install the Oxlint configuration, Oxlint and its type-aware engine:

Terminal window
pnpm add -D @jmlweb/oxlint-config-base oxlint oxlint-tsgolint

Create an oxlint.config.ts file:

import baseConfig from '@jmlweb/oxlint-config-base';
import { defineConfig } from 'oxlint';
export default defineConfig({
extends: [baseConfig],
options: {
typeAware: true,
},
});

Run Oxlint:

Terminal window
pnpm exec oxlint

Install the TypeScript configuration:

Terminal window
pnpm add -D @jmlweb/tsconfig-base typescript

Create a tsconfig.json file:

{
"extends": "@jmlweb/tsconfig-base",
"compilerOptions": {
"outDir": "dist"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}

Your project is now configured with Oxfmt, Oxlint and TypeScript!

Already using the Prettier and ESLint packages? See Migrate to Oxc.

jmlweb-tooling packages follow a base → variant pattern, allowing you to start with sensible defaults and extend for specific use cases.

@jmlweb/oxfmt-config-base (formatting, import sorting, optional Tailwind CSS class sorting)

The Prettier configurations are maintained for existing projects:

@jmlweb/prettier-config-base (base formatting rules)
└── @jmlweb/prettier-config-tailwind (adds Tailwind CSS class sorting)
@jmlweb/oxlint-config-base (JavaScript and TypeScript linting)
├── @jmlweb/oxlint-config-react (adds React, hooks and JSX rules)
└── @jmlweb/oxlint-config-node (adds Node.js rules)

The ESLint configurations are maintained for existing projects, and eslint-config-astro remains the way to lint .astro files:

@jmlweb/eslint-config-base-js (JavaScript linting)
└── @jmlweb/eslint-config-base (adds TypeScript support)
├── @jmlweb/eslint-config-react (adds React and JSX rules)
├── @jmlweb/eslint-config-node (adds Node.js specific rules)
└── @jmlweb/eslint-config-astro (adds Astro framework rules)
@jmlweb/tsconfig-base (strict base configuration)
├── @jmlweb/tsconfig-node (Node.js projects)
├── @jmlweb/tsconfig-react (React libraries)
├── @jmlweb/tsconfig-nextjs (Next.js applications)
└── @jmlweb/tsconfig-astro (Astro projects)

Example: Extend tsconfig-node for backend services, tsconfig-nextjs for Next.js apps.

@jmlweb/vitest-config (Vitest with TypeScript and coverage)
@jmlweb/jest-config (Jest with TypeScript support)
@jmlweb/tsdown-config-base (tsdown for building TypeScript packages)
@jmlweb/vite-config (Vite for frontend projects)
@jmlweb/tsup-config-base (deprecated, use tsdown-config-base)

Setting up a basic TypeScript project from scratch:

Terminal window
# Initialize project
mkdir my-project && cd my-project
pnpm init
# Install configurations
pnpm add -D @jmlweb/oxfmt-config-base oxfmt
pnpm add -D @jmlweb/oxlint-config-base oxlint oxlint-tsgolint
pnpm add -D @jmlweb/tsconfig-node typescript
# Create source directory
mkdir src

package.json:

{
"name": "my-project",
"type": "module",
"scripts": {
"build": "tsc",
"lint": "oxlint",
"format": "oxfmt"
}
}

tsconfig.json:

{
"extends": "@jmlweb/tsconfig-node",
"compilerOptions": {
"outDir": "dist"
},
"include": ["src/**/*"]
}

Add the oxfmt.config.ts and oxlint.config.ts files from the Quick Start.

For a React application with TypeScript:

Terminal window
# Install dependencies
pnpm add -D @jmlweb/oxfmt-config-base oxfmt
pnpm add -D @jmlweb/oxlint-config-react oxlint oxlint-tsgolint @eslint-react/eslint-plugin eslint-plugin-perfectionist
pnpm add -D @jmlweb/tsconfig-react typescript
# For Vite-based projects
pnpm add -D @jmlweb/vite-config vite

oxlint.config.ts:

import reactConfig from '@jmlweb/oxlint-config-react';
import { defineConfig } from 'oxlint';
export default defineConfig({
extends: [reactConfig],
options: {
typeAware: true,
},
});

tsconfig.json:

{
"extends": "@jmlweb/tsconfig-react",
"compilerOptions": {
"outDir": "dist"
},
"include": ["src"]
}

vite.config.ts (if using Vite):

import { createReactViteConfig } from '@jmlweb/vite-config';
export default createReactViteConfig();

For Tailwind CSS, enable class sorting in oxfmt.config.ts with sortTailwindcss: { stylesheet: './src/index.css' }.

For a Next.js application:

Terminal window
# Install configurations
pnpm add -D @jmlweb/oxfmt-config-base oxfmt
pnpm add -D @jmlweb/oxlint-config-react oxlint oxlint-tsgolint @eslint-react/eslint-plugin eslint-plugin-perfectionist
pnpm add -D @jmlweb/tsconfig-nextjs typescript

tsconfig.json:

{
"extends": "@jmlweb/tsconfig-nextjs",
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}

For a Node.js backend service:

Terminal window
# Install configurations
pnpm add -D @jmlweb/oxfmt-config-base oxfmt
pnpm add -D @jmlweb/oxlint-config-node oxlint oxlint-tsgolint eslint-plugin-n
pnpm add -D @jmlweb/tsconfig-node typescript
pnpm add -D @jmlweb/vitest-config vitest

oxlint.config.ts:

import nodeConfig from '@jmlweb/oxlint-config-node';
import { defineConfig } from 'oxlint';
export default defineConfig({
extends: [nodeConfig],
options: {
typeAware: true,
},
});

vitest.config.ts:

import baseConfig from '@jmlweb/vitest-config';
import { defineConfig } from 'vitest/config';
export default defineConfig({
...baseConfig,
test: {
...baseConfig.test,
},
});

For workspace/monorepo dependencies, use the workspace:* protocol:

Root package.json:

{
"devDependencies": {
"@jmlweb/oxfmt-config-base": "workspace:*",
"@jmlweb/oxlint-config-base": "workspace:*",
"@jmlweb/tsconfig-base": "workspace:*"
}
}

This allows all packages in the monorepo to share the same configuration versions. See Monorepos for how Oxlint resolves configs and type-aware rules across packages.

All configurations can be extended to customize for your specific needs:

oxfmt.config.ts
import baseConfig from '@jmlweb/oxfmt-config-base';
import { defineConfig } from 'oxfmt';
export default defineConfig({
...baseConfig,
// Override specific options
printWidth: 100,
semi: false,
});
oxlint.config.ts
import baseConfig from '@jmlweb/oxlint-config-base';
import { defineConfig } from 'oxlint';
export default defineConfig({
extends: [baseConfig],
options: {
typeAware: true,
},
rules: {
// Override or add specific rules
'eslint/no-unused-vars': 'warn',
},
});
{
"extends": "@jmlweb/tsconfig-base",
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2022"],
"outDir": "dist",
"rootDir": "src"
}
}

Add these common scripts to your package.json:

{
"scripts": {
"build": "tsc",
"lint": "oxlint",
"lint:fix": "oxlint --fix",
"format": "oxfmt",
"format:check": "oxfmt --check",
"test": "vitest",
"type-check": "tsc --noEmit"
}
}

Run them with:

Terminal window
pnpm lint # Check for linting errors
pnpm lint:fix # Fix auto-fixable errors
pnpm format # Format all files
pnpm test # Run tests

options.typeAware must be set in your own oxlint.config.ts, and oxlint-tsgolint must be installed. Oxlint ignores options in configs loaded through extends.

For VS Code, install the Oxc extension, which runs both Oxfmt and Oxlint.

Add to .vscode/settings.json:

{
"editor.defaultFormatter": "oxc.oxc-vscode",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.oxc": "always"
}
}

If you see Cannot find package '@jmlweb/...':

  1. Ensure you’ve installed the package: pnpm add -D @jmlweb/package-name
  2. Check the package name is correct (all lowercase, with hyphens)
  3. Run pnpm install to ensure dependencies are installed

Now that you’re set up, explore the documentation for specific packages:

  • Oxfmt - Formatting options and import sorting
  • Oxlint - Linting rules and configuration
  • Migrate to Oxc - Move an existing project from Prettier and ESLint
  • TypeScript - Type checking and compiler options
  • Testing - Test configuration and coverage
  • Build Tools - Building and bundling your code

Found an issue or have a suggestion? Contributions are welcome!

Follow semantic versioning for updates:

  • Patch (1.0.x) - Bug fixes, safe to update
  • Minor (1.x.0) - New features, backward compatible
  • Major (x.0.0) - Breaking changes, read migration guides

Check changelogs in each package’s documentation for version history.