Raypx

Tooling

Biome linter, Lefthook git hooks, and Turborepo build system.

Raypx uses a modern toolchain: Biome for linting and formatting, Lefthook for git hooks, and Turborepo for monorepo build orchestration. This page covers each tool and how to customize it.

Biome

Biome replaces ESLint, Prettier, and some import-sorting tools with a single fast binary. Configuration lives in biome.json.

Formatter

{
  "formatter": {
    "enabled": true,
    "indentStyle": "space",
    "indentWidth": 2,
    "lineWidth": 100,
    "lineEnding": "lf"
  }
}
  • Indent: 2 spaces.
  • Line width: 100 characters.
  • Line ending: LF (Unix-style).

JavaScript files use semicolons in "asNeeded" mode and multiline attribute positioning:

{
  "javascript": {
    "formatter": {
      "enabled": true,
      "attributePosition": "multiline",
      "semicolons": "asNeeded"
    }
  }
}

Linter Rules

The linter enables the recommended ruleset plus custom overrides:

{
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true,
      "style": {
        "useImportType": "error",
        "useSelfClosingElements": "error",
        "noUselessElse": "error"
      },
      "suspicious": {
        "noExplicitAny": "warn",
        "noConsole": {
          "level": "warn",
          "options": {
            "allow": ["warn", "error", "debug"]
          }
        }
      },
      "security": {
        "noDangerouslySetInnerHtml": "warn"
      }
    }
  }
}

Notable rules:

RuleLevelDescription
useImportTypeerrorEnforces import type for type-only imports.
useSelfClosingElementserrorRequires <br /> instead of <br>.
noExplicitAnywarnWarns on explicit any usage.
noConsolewarnWarns on console.log, but allows console.warn and console.error.
noDangerouslySetInnerHtmlwarnWarns on dangerouslySetInnerHTML usage.
useSortedClasseswarnAuto-sorts Tailwind utility classes in cn(), clsx(), and cva() calls.

File Includes

{
  "files": {
    "includes": [
      "**/*.{tsx,ts,js,jsx,json,jsonc,css,mdx}",
      "!**/dist",
      "!**/node_modules",
      "!**/.output",
      "!**/routeTree.gen.ts"
    ]
  }
}

Overrides

Specific file patterns have custom rules:

PatternOverride
**/routeTree.gen.tsAll checks disabled (auto-generated).
**/*.cssLinter disabled.
**/*.mdxLinter and assist disabled; formatter enabled.
packages/ui/src/components/**/*.tsxa11y rules disabled (components are primitives).
packages/**/src/logger-browser.tsnoConsole disabled (logging library).

Running Biome

# Check and auto-fix all files
pnpm check

# Format only
pnpm format

Tailwind CSS Support

Biome is configured to parse Tailwind directives in CSS files:

{
  "css": {
    "parser": {
      "tailwindDirectives": true
    }
  }
}

Lefthook

Lefthook manages git hooks. Configuration is in lefthook.yml.

Pre-Commit

Runs in parallel on every commit:

pre-commit:
  parallel: true
  jobs:
    - name: biome
      glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}"
      run: pnpm biome check --write --no-errors-on-unmatched --files-ignore-unknown=true {staged_files}
      stage_fixed: true
    - name: typecheck
      run: pnpm typecheck
  • biome: Runs Biome on staged files only. Auto-fixes issues and re-stages the fixed files.
  • typecheck: Runs tsc --noEmit to catch type errors.

Both jobs run in parallel to minimize wait time.

Pre-Push

pre-push:
  jobs:
    - name: test
      run: pnpm test

Runs the full Vitest suite before pushing to a remote. If any test fails, the push is blocked.

Turborepo

Turborepo orchestrates builds across the monorepo. Configuration is in turbo.json.

Task Pipeline

{
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "inputs": ["$TURBO_DEFAULT$", ".env*"],
      "outputs": ["dist/**"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    },
    "db:push": { "cache": false },
    "db:generate": { "cache": false },
    "db:migrate": { "cache": false, "persistent": true },
    "db:studio": { "cache": false, "persistent": true }
  }
}

Key behaviors:

  • build: Depends on ^build (builds dependencies first). Caches based on source files and .env* files. Outputs dist/**.
  • dev: Never cached, runs persistently (long-running process).
  • Database tasks: Never cached because they modify external state. db:migrate and db:studio are persistent.

Running Tasks

# Build all packages
pnpm build

# Build a specific package
turbo -F @raypx/database build

# Run a database command
pnpm db:push
pnpm db:studio

TypeScript

The TypeScript configuration extends a shared base from @raypx/tsconfig:

{
  "extends": "@raypx/tsconfig/tsconfig.base.json",
  "compilerOptions": {
    "target": "ES2022",
    "jsx": "react-jsx",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "verbatimModuleSyntax": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "paths": {
      "@/*": ["./src/*"],
      "@raypx/ui/*": ["./packages/ui/src/*"],
      "collections/*": [".source/*"]
    }
  }
}

Path Aliases

AliasResolves ToUsage
@/*./src/*Application source files.
@raypx/ui/*./packages/ui/src/*UI package source.
collections/*./.source/*Fumadocs content collections.

Path aliases are resolved by Vite via resolve.tsconfigPaths: true in vite.config.ts. This means import { foo } from "@/lib/foo" works in both the Vite build and TypeScript without any additional configuration.

On this page