or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

configuration.mdcore-rules.mdindex.mdjsx-rules.mdquality-rules.md
tile.json

quality-rules.mddocs/

Code Quality Rules

Rules for enforcing Qwik-specific code quality patterns and performance optimizations.

Capabilities

Prefer Classlist

Enforces using the classlist prop over importing a classnames helper.

/**
 * Enforces using classlist prop over classnames helper
 * The classlist prop accepts an object { [class: string]: boolean } like classnames
 */
preferClasslist: Rule;

Rule Configuration:

  • Type: suggestion rule
  • Category: Code Quality
  • Recommended: warn level
  • Strict: error level

Options Schema:

{
  type: 'object',
  properties: {
    classnames: {
      type: 'array',
      description: 'An array of names to treat as classnames functions',
      default: ['cn', 'clsx', 'classnames'],
      items: {
        type: 'string',
        minItems: 1,
        uniqueItems: true
      }
    }
  },
  additionalProperties: false
}

Usage Example:

// ❌ Invalid: using classnames helper
import classnames from 'classnames';

<div className={classnames({
  'active': isActive,
  'disabled': isDisabled
})} />

// ✅ Valid: using classlist prop
<div class={{
  'active': isActive,
  'disabled': isDisabled
}} />

Loader Location

Detects declaration location of loader$ functions to ensure proper placement.

/**
 * Detects declaration location of loader$ functions
 * Ensures loaders are declared in appropriate locations for proper SSR
 */
loaderLocation: Rule;

Rule Configuration:

  • Type: problem rule
  • Category: Code Quality
  • Recommended: warn level
  • Strict: error level

Options Schema:

{
  type: 'object',
  properties: {
    routesDir: {
      type: 'string',
      default: 'src/routes'
    }
  },
  additionalProperties: false
}

Usage Example:

// ❌ Invalid: loader in wrong location
export default component$(() => {
  const data = routeLoader$(() => { // Error: loader should be at module level
    return { message: 'Hello' };
  });
  
  return <div>{data.value.message}</div>;
});

// ✅ Valid: loader at module level
export const useData = routeLoader$(() => {
  return { message: 'Hello' };
});

export default component$(() => {
  const data = useData();
  return <div>{data.value.message}</div>;
});

No Use Visible Task

Detects useVisibleTask$() functions and suggests alternatives.

/**
 * Detects useVisibleTask$() functions
 * Suggests alternatives for better performance and SSR compatibility
 */
noUseVisibleTask: Rule;

Rule Configuration:

  • Type: suggestion rule
  • Category: Performance
  • Recommended: warn level
  • Strict: warn level

Usage Example:

// ⚠️ Discouraged: useVisibleTask for simple effects
export default component$(() => {
  useVisibleTask$(() => { // Warning: consider alternatives
    console.log('Component visible');
  });
  
  return <div>Content</div>;
});

// ✅ Better: use useTask$ for most cases
export default component$(() => {
  useTask$(() => {
    console.log('Component mounted');
  });
  
  return <div>Content</div>;
});

Code Quality Patterns

CSS Class Management

Classlist vs Classnames: The prefer-classlist rule encourages using Qwik's built-in classlist prop instead of external classnames libraries:

Benefits of classlist prop:

  • Native Qwik optimization
  • No additional bundle size
  • Better tree-shaking
  • Consistent with Qwik patterns

Pattern Comparison:

// External library approach (discouraged)
import cn from 'classnames';
<div className={cn('base', { active: isActive })} />

// Qwik native approach (preferred)
<div class={['base', { active: isActive }]} />
// or
<div class={{ base: true, active: isActive }} />

Loader Placement

Module-Level Declaration: Loaders should be declared at the module level for proper SSR and routing integration:

Why Module-Level:

  • Enables static analysis by Qwik's build system
  • Proper integration with routing and prefetching
  • Better performance through static optimization
  • Correct SSR timing and data availability

Pattern Examples:

// ❌ Component-level (runtime creation)
export default component$(() => {
  const loader = routeLoader$(() => getData()); // Problem: dynamic creation
  return <div>{loader.value}</div>;
});

// ✅ Module-level (static analysis)
export const usePageData = routeLoader$(() => getData());

export default component$(() => {
  const data = usePageData(); // Proper: static reference
  return <div>{data.value}</div>;
});

Visible Task Alternatives

Performance Considerations: useVisibleTask$ runs when a component becomes visible, but often other hooks are more appropriate:

Alternative Patterns:

// For initialization effects
useTask$(() => {
  // Runs on component mount (SSR + client)
});

// For resource loading
useResource$(async () => {
  // Lazy resource loading with proper SSR handling
});

// For browser-only effects
useVisibleTask$(({ track }) => {
  // Only when you specifically need visibility-based triggering
  track(() => someSignal.value);
  // Browser-only DOM manipulation
});

When to Use useVisibleTask$:

  • Intersection Observer patterns
  • Animation triggers on scroll
  • Lazy loading of non-critical resources
  • Browser-only DOM measurements

Rule Integration

Example System

Quality rules integrate with the plugin's documentation system:

// Example definitions for documentation
const preferClasslistExamples: QwikEslintExamples;
const loaderLocationExamples: QwikEslintExamples;

interface QwikEslintExamples {
  [scenario: string]: {
    good?: QwikEslintExample[];
    bad?: QwikEslintExample[];
  };
}

Configuration Integration

Rules work together to enforce consistent code quality:

// Recommended configuration balances performance and usability
{
  'qwik/prefer-classlist': 'warn',    // Suggest native patterns
  'qwik/loader-location': 'warn',     // Ensure proper placement
  'qwik/no-use-visible-task': 'warn', // Encourage alternatives
}

// Strict configuration enforces best practices
{
  'qwik/prefer-classlist': 'error',   // Require native patterns
  'qwik/loader-location': 'error',    // Enforce proper placement
  'qwik/no-use-visible-task': 'warn', // Still warn (sometimes needed)
}

Performance Impact

Bundle Size Optimization

Classlist Rule Benefits:

  • Eliminates classnames library dependency (~2-3KB)
  • Better tree-shaking with native Qwik patterns
  • Reduced runtime JavaScript execution

SSR Optimization

Loader Location Benefits:

  • Enables static analysis during build
  • Proper prefetching and data loading timing
  • Better integration with Qwik's SSR pipeline

Runtime Performance

Visible Task Alternatives:

  • useTask$ runs during SSR and hydration (better UX)
  • useResource$ provides better caching and loading states
  • useVisibleTask$ should be reserved for specific visibility-based needs

Types

// Quality rule definitions (standardized to TSESLint)
type Rule = TSESLint.RuleModule<any, any>;

// Classlist prop type
type ClassList = 
  | string 
  | string[] 
  | { [className: string]: boolean }
  | (string | { [className: string]: boolean })[];

// Loader types
type RouteLoader<T> = () => Promise<T>;
type LoaderSignal<T> = {
  readonly value: T;
};

// Task types
type TaskFn = (context: { track: <T>(signal: () => T) => T }) => void | Promise<void>;
type VisibleTaskFn = (context: { track: <T>(signal: () => T) => T }) => void | Promise<void>;

// Example system integration
interface QwikEslintExample {
  code: string;
  codeTitle?: string;
  codeHighlight?: string;
  description?: string;
}

interface QwikEslintExamples {
  [scenario: string]: {
    good?: QwikEslintExample[];
    bad?: QwikEslintExample[];
  };
}