Skip to main content

@ttoss/config

@ttoss/config is an opinionated configuration library for monorepo and packages. It contains a set of default configurations that you can use on your projects.

Install​

pnpm add -Dw @ttoss/config

Monorepo​

Use the configs of this section on the root of your monorepo.

The easiest way to set up all monorepo configurations at once is using the @ttoss/monorepo command:

pnpm add -Dw @ttoss/monorepo
npx @ttoss/monorepo setup-monorepo

This command will automatically create all configuration files and install all necessary dependencies for ESLint, Prettier, Husky, commitlint, lint-staged, Lerna, Syncpack, and pnpm workspace.

For more details, see @ttoss/monorepo documentation.

Manual Setup​

Alternatively, you can set up each tool manually:

ESLint and Prettier​

Install the following packages:

pnpm add -Dw eslint prettier @ttoss/eslint-config @ttoss/config

Create the .prettierrc.js file and add the following configuration:

.prettierrc.js
const { prettierConfig } = require('@ttoss/config');

module.exports = prettierConfig();

Create the eslint.config.mjs file and add the following configuration:

eslint.config.mjs
import ttossEslintConfig from '@ttoss/eslint-config';

export default [...ttossEslintConfig];

Husky, commitlint, and lint-staged​

This group of packages will only work if you have already installed ESLint and Prettier because lint-staged will run the eslint --fix command.

Install the following packages on the root of your monorepo:

pnpm add -Dw husky @commitlint/cli lint-staged

Create the .commitlintrc.js file and add the following configuration:

.commitlintrc.js
const { commitlintConfig } = require('@ttoss/config');

module.exports = commitlintConfig();

Create the .lintstagedrc.js file and add the following configuration:

.lintstagedrc.js
const { lintstagedConfig } = require('@ttoss/config');

module.exports = lintstagedConfig();

The default config runs ESLint on JS/TS files, Prettier on Markdown/JSON/YAML, and automatically sorts package.json keys using sort-package-json. No additional packages needed.

Finally, configure Husky:

npm set-script prepare "husky install"
pnpm run prepare
pnpm husky add .husky/commit-msg "pnpm commitlint --edit"
pnpm husky add .husky/pre-commit "pnpm lint-staged && pnpm syncpack:list"

Lerna (optional)​

Lerna helps manage versioning and publishing of packages in a monorepo.

Install lerna-lite packages:

pnpm add -Dw @lerna-lite/cli @lerna-lite/version @lerna-lite/changed @lerna-lite/list

Create the lerna.json file and configure it according to your monorepo structure:

lerna.json
{
"$schema": "node_modules/@lerna-lite/cli/schemas/lerna-schema.json",
"version": "independent",
"npmClient": "pnpm",
"stream": true,
"command": {
"publish": {
"allowBranch": "main",
"noPrivate": true
},
"version": {
"conventionalCommits": true,
"createRelease": "github",
"message": "chore(release): publish packages",
"syncWorkspaceLock": true,
"allowPeerDependenciesUpdate": true
}
},
"ignoreChanges": ["**/__fixtures__/**", "**/tests/**"],
"packages": ["packages/*"]
}

Syncpack (optional)​

Syncpack ensures consistent versions of dependencies across all packages in your monorepo.

Install syncpack:

pnpm add -Dw syncpack

Create the .syncpackrc.js file:

.syncpackrc.js
const { syncpackConfig } = require('@ttoss/config');

module.exports = syncpackConfig();

Add syncpack scripts to your root package.json:

package.json
{
"scripts": {
"syncpack:fix": "syncpack fix-mismatches",
"syncpack:list": "syncpack list-mismatches"
}
}

pnpm workspace (required for pnpm monorepos)​

Create a pnpm-workspace.yaml file to define which directories contain packages:

pnpm-workspace.yaml
packages:
- 'packages/*'

Adjust the packages array to match your monorepo structure. For example:

pnpm-workspace.yaml
packages:
- 'packages/*'
- 'examples/*'
- 'apps/*'

Create a .gitignore file in the monorepo root to exclude common build artifacts and dependencies:

.gitignore
node_modules/
dist/
build/
.build/
coverage/
*.log
.env
.env.test
.cache/
.turbo
**/i18n/compiled/
**/i18n/missing/
**/i18n/unused/
tsup.config.bundled*.mjs
package-lock.json
yarn.lock

Create an .npmrc file to configure pnpm behavior:

.npmrc
enable-pre-post-scripts=true
engine-strict=true
public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=*prettier*
public-hoist-pattern[]=@types*

Packages​

You can use configs below to your packages folders.

Jest​

Follow our tests guidelines to configure and run your tests.

Tsup​

Use tsup to bundle your TypeScript packages.

Install tsup on your package.

pnpm add -D tsup

Create the tsup.config.ts file on the package folder:

tsup.config.ts
import { tsupConfig } from '@ttoss/config';

export const tsup = tsupConfig();

Configure the build script on package.json:

package.json
"scripts": {
"build": "tsup",
}

i18n message ids​

ttoss-i18n extracts messages with one id pattern, and a catalog only applies when the bundler injects ids with the same one — a mismatch fails silently, every message falling back to its defaultMessage. Import the pattern instead of retyping it:

import {
formatjsBabelPlugin, // ['formatjs', { idInterpolationPattern, ast: true }]
formatjsSwcPlugin, // ['@swc/plugin-formatjs', { idInterpolationPattern, ast: true }]
I18N_ID_INTERPOLATION_PATTERN,
} from '@ttoss/config';

// vite.config.ts with @vitejs/plugin-react-swc
react({ plugins: [formatjsSwcPlugin()] });

// vite.config.ts with @vitejs/plugin-react
react({ babel: { plugins: [formatjsBabelPlugin()] } });

The Jest (babelConfig) and build (tsdownConfig, tsupConfig) presets already use it.

TypeScript​

Install TypeScript on your package:

pnpm add -D typescript

Extend default configuration for each tsconfig.json (touch tsconfig.json) on the package folder:

tsconfig.json
{
"extends": "@ttoss/config/tsconfig.json"
}

For tests, you can extend the default test configuration tsconfig.test.json on the package tests folder:

tests/tsconfig.json
{
"extends": "@ttoss/config/tsconfig.test.json",
"include": ["**/*.test.ts", "**/*.test.tsx"]
}

Extending configurations​

Each configuration is customizable and you can extend them with your own. For example, you can use the default .prettierrc.js file in your monorepo:

.prettierrc.js
const { prettierConfig } = require('@ttoss/config');

module.exports = prettierConfig();

But, if you want to change the printWidth option, you can do so:

.prettierrc.js
const { prettierConfig } = require('@ttoss/config');

module.exports = prettierConfig({
printWidth: 120,
});

You can also pass a second argument to every configuration to control array merge behavior (append or overwrite).

babel.config.js
const { babelConfig } = require('@ttoss/config');

// Overwrite plugins (default)
const overwriteConfig = babelConfig(
{
plugins: ['@babel/plugin-proposal-class-properties'],
},
{
arrayMerge: 'overwrite',
}
);

const appendConfig = babelConfig(
{
plugins: ['@babel/plugin-proposal-class-properties'],
},
{
arrayMerge: 'append',
}
);