Skip to content

Format and Style Standards

VUP projects adopt unified code formatting and style standards to ensure team collaboration consistency and code quality. This guide details all formatting and code quality tools used in the project and their configurations.

Tool Overview

VUP projects use the following tools to ensure code quality and formatting consistency:

  • ESLint - Code quality checking and best practices
  • Prettier - Code formatting
  • TypeScript - Type checking and compilation
  • Tailwind CSS - Styling framework
  • PostCSS - CSS post-processor
  • VSCode - Editor configuration and plugins

ESLint Configuration

Basic Configuration

The project uses @antfu/eslint-config - a modern, opinionated ESLint configuration by Anthony Fu:

javascript
// eslint.config.js
import antfu from '@antfu/eslint-config';

export default antfu({
  typescript: true,
  vue: true,
  stylistic: false,
  rules: {
    'ts/no-empty-object-type': 'off',
    'ts/no-require-imports': 'off',
    'node/prefer-global/process': 'off',
    'no-console': 'off',
    'no-alert': 'off',
  },
  overrides: [
    {
      files: ['**/*.config.{js,ts}', '**/vite.config.*', '**/nuxt.config.*'],
      rules: {
        'no-undef': 'off',
      },
    },
    {
      files: ['**/*.d.ts'],
      rules: {
        'ts/no-explicit-any': 'off',
        'ts/ban-ts-comment': 'off',
      },
    },
  ],
  ignores: [
    '**/node_modules/**',
    '**/dist/**',
    '**/build/**',
    '**/.nuxt/**',
    '**/.output/**',
    '**/.nitro/**',
    '**/.vitepress/cache/**',
    '**/.wxt/**',
    '**/auto-imports.d.ts',
    '**/.wxt/types/**',
  ],
});

Key Features

@antfu/eslint-config provides:

  • TypeScript Support - Full TypeScript integration with strict rules
  • Vue 3 Support - Optimized for Vue 3 Composition API
  • Modern JavaScript - ES2022+ features and best practices
  • Auto-import Support - Works with unplugin-auto-import
  • Project-tuned Rules - Some strict rules are disabled to match template development style
  • Performance Optimized - Fast linting with minimal overhead

Prettier Configuration

Basic Configuration

javascript
// prettier.config.js
export default {
  plugins: ['prettier-plugin-tailwindcss'],
  semi: true,
  singleQuote: true,
  tabWidth: 2,
  trailingComma: 'es5',
  printWidth: 100,
  endOfLine: 'lf',
  bracketSameLine: false,
  overrides: [
    {
      files: '*.md',
      options: {
        printWidth: 80,
        proseWrap: 'always',
      },
    },
  ],
};

Configuration Explanation

  • semi: true - Use semicolons
  • plugins: ['prettier-plugin-tailwindcss'] - Sort Tailwind classes automatically
  • singleQuote: true - Use single quotes
  • tabWidth: 2 - Indentation width of 2 spaces
  • trailingComma: "es5" - Add trailing commas where valid in ES5
  • printWidth: 100 - Line width limit of 100 characters
  • endOfLine: "lf" - Use LF line endings
  • bracketSameLine: false - Place > of multi-line JSX elements on next line

Markdown Special Configuration

javascript
// Markdown file special handling
{
  files: '*.md',
  options: {
    printWidth: 80, // Line width limit of 80 characters
    proseWrap: 'always', // Always wrap
  },
}

TypeScript Configuration

Root Configuration

json
// tsconfig.json
{
  "extends": "@tsconfig/node22/tsconfig.json",
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "lib": ["ES2022", "DOM", "DOM.Iterable"],
    "strict": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "removeComments": false,
    "noImplicitAny": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "noUncheckedIndexedAccess": true,
    "exactOptionalPropertyTypes": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "baseUrl": "."
  },
  "exclude": [
    "node_modules",
    "dist",
    "build",
    "**/.nuxt/**",
    "**/.output/**",
    "**/.nitro/**",
    "**/.vitepress/cache/**",
    "**/.wxt/**"
  ]
}

Application Configuration

json
// apps/*/tsconfig.json
{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "outDir": "./.output",
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "@_shared/*": ["../../_shared/*"]
    }
  },
  "include": [
    "src/**/*",
    "src/**/*.vue",
    "src/*.vue",
    "./auto-imports.d.ts",
    "src/vue-shim.d.ts"
  ]
}

Tailwind CSS Integration

Tailwind v4 (PostCSS)

javascript
// postcss.config.js
export default {
  plugins: {
    '@tailwindcss/postcss': {},
  },
};

Global Style Entry

scss
// @_shared/assets/styles/tailwind.scss
@import 'tailwindcss';

PostCSS Configuration

javascript
// postcss.config.js
export default {
  plugins: {
    '@tailwindcss/postcss': {},
  },
};

Plugin Explanation

  • @tailwindcss/postcss - Tailwind v4 official PostCSS plugin

VSCode Configuration

Editor Settings

json
// .vscode/settings.json
{
  "editor.codeActionsOnSave": {
    "source.organizeImports": "never",
    "source.removeUnusedImports": "never",
    "source.fixAll.eslint": "never"
  },
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSaveMode": "file",
  "editor.tabSize": 2,
  "files.eol": "\n",
  "typescript.preferences.importModuleSpecifier": "relative",
  "scss.lint.unknownAtRules": "ignore",
  "eslint.enable": true,
  "eslint.validate": ["javascript", "typescript", "vue"],
  "eslint.workingDirectories": [".", "apps/*"],
  "typescript.preferences.includePackageJsonAutoImports": "auto",
  "typescript.suggest.autoImports": true,
  "typescript.updateImportsOnFileMove.enabled": "always",
  "typescript.preferences.organizeImports": {
    "enabled": false
  }
}
json
// .vscode/extensions.json
{
  "recommendations": [
    "esbenp.prettier-vscode",
    "dbaeumer.vscode-eslint",
    "ms-vscode.vscode-typescript-next",
    "ms-vscode.vscode-json",
    "bradlc.vscode-tailwindcss",
    "vue.volar",
    "pflannery.vscode-versionlens"
  ]
}

Plugin Explanation

  • esbenp.prettier-vscode - Prettier formatting plugin
  • dbaeumer.vscode-eslint - ESLint code checking plugin
  • ms-vscode.vscode-typescript-next - TypeScript support
  • ms-vscode.vscode-json - JSON file support
  • bradlc.vscode-tailwindcss - Tailwind CSS IntelliSense
  • vue.volar - Vue 3 language service
  • pflannery.vscode-versionlens - Version number display

Script Commands

Root Directory Scripts

json
// package.json
{
  "scripts": {
    "dev:all": "pnpm --filter '*' dev",
    "build:all": "pnpm --filter '*' build",
    "lint:all": "pnpm --filter '*' lint",
    "lint:fix:all": "pnpm --filter '*' lint:fix",
    "format:all": "pnpm --filter '*' format",
    "format:check:all": "pnpm --filter '*' format:check",
    "type-check:all": "pnpm --filter '*' type-check",
    "prepare": "husky",
    "release": "release-it",
    "deploy:prod": "vercel --prod",
    "deploy:preview": "vercel"
  }
}

Application Scripts

json
// apps/*/package.json
{
  "scripts": {
    "dev": "vite",
    "build": "tsc --noEmit && vite build",
    "lint": "eslint src/ --ext .vue,.ts,.js",
    "lint:fix": "eslint src/ --ext .vue,.ts,.js --fix",
    "format": "prettier --write \"src/**/*.{js,ts,vue,json,css,scss}\"",
    "format:check": "prettier --check \"src/**/*.{js,ts,vue,json,css,scss}\""
  }
}

Usage Guide

Development Formatting

bash
# Format all files
pnpm format:all

# Check if formatting is correct
pnpm format:check:all

# Fix ESLint issues
pnpm lint:fix:all

Pre-commit Checks

The project is configured with Husky Git hooks that automatically run before commits:

bash
# pre-commit hook runs automatically
git add .
git commit -m "feat: add new feature"
# Automatically executes: pnpm lint-staged

Type Checking

bash
# Check TypeScript types
pnpm type-check:all

# Type checking also runs during build
pnpm build:all

Best Practices

1. Code Style

  • Use single quotes instead of double quotes
  • Use 2 spaces for indentation
  • Line width limit of 100 characters
  • Use trailing commas
  • Use semicolons

2. Import Order

javascript
// Correct import order
import { ref, computed } from 'vue'; // 1. Built-in modules
import { defineStore } from 'pinia'; // 2. External dependencies
import { useRouter } from 'vue-router'; // 3. External dependencies

import { api } from '@/utils/api'; // 4. Internal modules
import { formatDate } from '@/utils/date'; // 5. Internal modules

import type { User } from '@/types/user'; // 6. Type imports

3. Vue Components

vue
<template>
  <div class="container">
    <h1>{{ title }}</h1>
    <p>{{ description }}</p>
  </div>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue';

interface Props {
  title: string;
  description?: string;
}

const props = withDefaults(defineProps<Props>(), {
  description: '',
});

const isVisible = ref(true);
const displayTitle = computed(() => props.title.toUpperCase());
</script>

<style scoped>
.container {
  @apply p-4 bg-white rounded-lg shadow-md;
}
</style>

4. TypeScript Types

typescript
// Use explicit type definitions
interface User {
  id: number;
  name: string;
  email: string;
  createdAt: Date;
}

// Use type imports
import type { User } from '@/types/user';

// Use generics
function createApi<T>(url: string): Promise<T> {
  return fetch(url).then((res) => res.json());
}

Dependencies

ESLint Dependencies

json
{
  "devDependencies": {
    "@antfu/eslint-config": "^5.4.1",
    "eslint": "^9.34.0"
  }
}

Key Dependencies

  • @antfu/eslint-config - Modern, opinionated ESLint configuration
  • eslint - JavaScript/TypeScript linter
  • prettier - Code formatter
  • typescript - TypeScript compiler
  • vue-tsc - Vue TypeScript checker