Skip to content

TimoBechtel/style

Repository files navigation

Style 🛼

Roll in style.

Highly opinionated configuration files for typescript projects.

Tip

Let your agent set this up for you:

Read https://raw.githubusercontent.com/TimoBechtel/style/main/skills/setup-style/SKILL.md and configure.

Usage

Make sure to first commit your code before running the following commands. This allows you to revert changes easily.

npm i -D @timobechtel/style typescript

Install gh-get to make it easier to download the template files:

gh extension install timobechtel/gh-get

Code formatter, replaces Prettier.

npm i -D oxfmt
gh get timobechtel/style templates/.oxfmtrc.json

Faster ESLint alternative. 5x faster in personal testing.

npm i -D oxlint

Core:

gh get timobechtel/style templates/.oxlintrc.jsonc

React:

gh get timobechtel/style templates/react/.oxlintrc.jsonc
Migrating to Oxlint? - `File '@timobechtel/style/tsconfig/core' not found.`

When migrating from ESLint to Oxlint, you might need to update the tsconfig.json file:

- "extends": ["@timobechtel/style/tsconfig/core"]
+ "extends": ["@timobechtel/style/tsconfig/core.json"]
- "extends": ["@timobechtel/style/tsconfig/react"]
+ "extends": ["@timobechtel/style/tsconfig/react.json"]

tsgolint requires a file extension to resolve the config file.

Typescript

Pre-configured tsconfig files.

Existing tsconfig

For existing projects or templates, I recomment leaving the config as-is and adding this preset to the extends array.

{
  "extends": ["@timobechtel/style/tsconfig/core.json"]
}

New tsconfig

gh get timobechtel/style templates/tsconfig.json

Or with React

gh get timobechtel/style templates/react/tsconfig.json
Or manually

Copy to tsconfig.json:

{
  "extends": "@timobechtel/style/tsconfig/react.json"
}

Expo

With expo make sure to add "moduleResolution": "bundler" to the compilerOptions, otherwise certain routing types might break.

Example

Copy to tsconfig.json:

{
  "extends": ["expo/tsconfig.base", "@timobechtel/style/tsconfig/core.json"],
  "compilerOptions": {
    "moduleResolution": "bundler", // <-- this is important
    "strict": true,
    "paths": {
      "@/*": ["./*"]
    }
  },
  "include": ["**/*.ts", "**/*.tsx", ".expo/types/**/*.ts", "expo-env.d.ts"]
}

Prettier

Prettier config will not be updated anymore. I recommend using Oxfmt instead. oxfmt has been configured to match prettier rules, however this might drift in future versions.

Setup prettier anyways
npm i -D prettier
gh get timobechtel/style templates/.prettierrc
Extend / customize config

Need to extend the config, e.g. adding plugins?

gh get timobechtel/style templates/.prettierrc.mjs

Create a .prettierrc.mjs file and import the config, like this:

import config from '@timobechtel/style/prettier/index.mjs';

/**
 * @type {import("prettier").Config}
 */
export default {
  ...config,
  // your config
};

Eslint

Eslint config will be removed in a future version. Use Oxlint instead. oxlint has been configured to match existing eslint rules, however this might drift in future versions.

Setup eslint anyways
npm i -D eslint
gh get timobechtel/style templates/eslint.config.js

Note: If your project is not ESM (no "type": "module" in package.json), rename the file to eslint.config.mjs.

Or manually

Copy the following to an eslint.config.js:

import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { defineConfig } from 'eslint/config';
import styleCore from '@timobechtel/style/eslint/core.js';
import { createTypeScriptImportResolver } from 'eslint-import-resolver-typescript';
import { createNodeResolver } from 'eslint-plugin-import-x';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

export default defineConfig([
  ...styleCore,
  {
    languageOptions: {
      parserOptions: {
        tsconfigRootDir: __dirname,
      },
    },
    settings: {
      'import-x/resolver-next': [
        createTypeScriptImportResolver({
          project: path.resolve(__dirname, 'tsconfig.json'),
        }),
        createNodeResolver(),
      ],
    },
  },
]);

React

gh get timobechtel/style templates/react/eslint.config.js
Or manually

Also spread styleReact from @timobechtel/style/eslint/react.js:

import styleCore from '@timobechtel/style/eslint/core.js';
import styleReact from '@timobechtel/style/eslint/react.js';
import { defineConfig } from 'eslint/config';

export default defineConfig([
  ...styleCore,
  ...styleReact,
  // ... your config
]);

Migration from v1.x

If you're upgrading from v1.x, you'll need to:

  1. Upgrade to ESLint v9+
  2. Replace .eslintrc.cjs with eslint.config.js
  3. Update imports to use .js extension (e.g., @timobechtel/style/eslint/core.js)
  4. Note: Import plugin rules now use import-x/ prefix instead of import/

VSCode

Note: You should disable source.organizeImports in your VSCode config, as this collides with the import-x/order rule.

Add the following to your VSCode config, e.g. .vscode/settings.json

{
  "editor.codeActionsOnSave": {
    // use eslint import-x/order instead
    "source.sortImports": "never"
  }
}

semantic-release

This repo also contains a semantic-release configuration.

npm i -D semantic-release @semantic-release/changelog @semantic-release/git
gh get timobechtel/style templates/.releaserc.json

Agent Skills

npx skills add timobechtel/style@setup-style

About

Highly opinionated config files (Prettier, ESLint, TSConfig)

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors