Code Quality Review
Code Quality Review
Info
This document outlines the frontend coding standards for the eIsland project. All frontend code must comply with these rules โ no exceptions.
HTML Standards
Document Structure
All HTML documents must start with an HTML5 doctype declaration in lowercase, and include the required structural elements: <html>, <head>, and <body>.
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>Page Title</title>
</head>
<body>
</body>
</html>Language and Encoding
Specify the language attribute on the root HTML element and declare UTF-8 encoding explicitly.
<html lang="zh-CN">
<head>
<meta charset="utf-8">
</head>Formatting Rules
- Use 2 spaces for indentation
- All HTML tags use lowercase
- All attribute values must use double quotes
- Self-closing elements do not need a trailing slash in HTML5
Attribute Order
HTML attributes should follow this order:
classid,namedata-*src,for,type,href,valuetitle,altrole,aria-*tabindexstyle
Semantic HTML
- Ensure headings follow a logical hierarchy (
h1โh2โh3) without skipping levels - All
<img>tags must have analtattribute - Avoid inline event handlers โ use external JavaScript instead
- A page must have only one
<main>element
CSS Standards
Tailwind CSS
Class Order
Tailwind classes must follow a fixed order: layout โ box model โ typography โ visual effects.
<button class="flex items-center justify-center w-full p-4 font-bold text-white bg-blue-500 rounded-lg hover:bg-blue-600">
Click me
</button>Important
Prefer Tailwind shorthand forms when available (e.g., mx-4 instead of ml-4 mr-4).
Utility-First Principle
To enforce the utility-first approach, avoid adding custom semantic class names to components. All styles should be composed from atomic utility classes. If customization is truly needed, use @apply in CSS.
Arbitrary Values
For negative arbitrary values, the - sign must be placed outside the brackets.
<div class="-top-[-10px]">...</div>General CSS Rules
- Use 2 spaces for indentation
- All code uses lowercase (except strings)
- Use double quotes consistently
- One blank line between rule sets; no trailing whitespace
- Use kebab-case for class names, IDs, keyframes, and custom media queries
Selector Complexity Limits
| Rule | Limit |
|---|---|
| ID selectors | Forbidden |
| Class selectors per selector | Max 4 |
| Attribute selectors per selector | Max 2 |
| Combinators per selector | Max 4 |
| Universal selectors per selector | Max 1 |
| Type selectors per selector | Max 2 |
| Type selector prefixing a class/ID | Forbidden (e.g., div.my-class) |
Color Rules
- Prefer 3-digit hex shorthand
- Color values must be lowercase
- Color names are forbidden (use hex or HSL)
- Hue values use angle units (
deg)
.element {
color: #fff;
background-color: #f0c;
border-color: hsl(270deg 60% 70%);
}Numeric Rules
- Omit units for zero values (
padding: 0) - Omit leading zero for decimals below 1 (
opacity: .5) - No trailing zeros
Property Declaration Order
Properties should be declared in this order:
- Composition rules (
composes) all- Positioning (
position,top,z-index, etc.) - Display mode (
box-sizing,display) - Flexbox
- Grid
- Spacing (
gap) - Alignment (
align-*,justify-*) - Order
- Box model (
width,height,padding,margin,overflow) - Typography (
font-*,color,text-*) - Interaction (
cursor,pointer-events) - Background and border
- Mask
- SVG properties
- Transitions and animations
- Paged media
Caution
!important is strictly forbidden.
JavaScript / TypeScript Standards
Variables and Constants
- Prefer
constfor constants,letfor reassignable variables. Avoidvar. - Declare one variable per
constorletstatement - Variables must be defined before use
- Never delete variables
- Avoid initializing to
undefined
const name = 'Alice';
let age = 30;Data Types
- Use literals for primitive types
- Use
as constfor read-only constants when the type is explicit anytype is forbidden unless absolutely necessary- Forbidden wrappers:
Function,Object,String,Number,Boolean
const config = {
host: 'localhost',
port: 8080,
} as const;Objects
- Use object literals
{} - Use shorthand method syntax
- Use shorthand property syntax (placed at the beginning of the object)
- Only quote invalid identifiers (e.g.,
'data-test') - Use
Object.hasOwn()instead ofObject.prototype.hasOwnProperty - Prefer spread
...overObject.assign
Arrays
- Use array literals
[] - Use
Array.from()for array-like conversions - Callbacks must have a
returnstatement (unless implicit) - Avoid
for...inon arrays - Prefer higher-order functions (
map,filter,reduce) overforloops
Strings
- Use single quotes
''for strings - Prefer template literals for concatenation
- Avoid unnecessary escape characters
const message = `Hello, ${name}!`;Functions
- Use function declarations or expressions, not
new Function() - Do not declare functions inside non-function blocks (
if,while) - Set default values in parameters, not in the function body
- Parameters with defaults go at the end of the parameter list
- Prefer rest parameters
...overarguments - No space before parentheses in function calls
Arrow Functions
- Use for anonymous callbacks
- Omit braces and
returnfor single-expression bodies without side effects
const square = (x: number) => x * x;Classes and Interfaces
- Always use
classโ avoid directprototypemanipulation - Call
super()in non-empty constructors - One class per file
- Prefer
interfaceovertypefor object shapes; usetypefor unions and tuples
Modules
- Use ES6 modules (
import/export) exclusively - No file extensions in import paths
- Use
export defaultfor single-export modules - Imports at the top of the file, ordered: builtins โ external โ internal (absolute) โ parent relative โ sibling relative
Comparison and Equality
- Always use
===and!== - No explicit comparison of booleans to
true/false
const isAdult = age >= 18; // โ
const isAdult = age >= 18 ? true : false; // โNaming Conventions
| Element | Convention | Example |
|---|---|---|
| Variables, functions | camelCase | userName, getUser() |
| Classes, interfaces, types, enums | PascalCase | UserProfile, StatusEnum |
| Constants | UPPER_SNAKE_CASE | MAX_RETRY_COUNT |
| No leading/trailing underscores | โ | โ |
| File names | camelCase or kebab-case | userProfile.ts or user-profile.ts |
Promises and Async
- Prefer
async/await rejectreasons should beErrorobjects- Always include
.catch()ortry...catch - Avoid
return/throw/break/continueinfinallyblocks - Avoid unnecessary
await - Avoid
awaitin loops โ usePromise.allfor parallelism
async function fetchData() {
return fetch('/api/data'); // โ
Direct return
}Security
Caution
eval() and new Function() are strictly forbidden. javascript: URLs are forbidden. Never use innerHTML/outerHTML with unvalidated content.
React Standards
File Extensions and Component Definition
- React component files use
.tsxextension - Prefer function declarations for named components
- Anonymous components may use arrow functions
- Do not import
React(React 17+ JSX transform handles this)
JSX Rules
- JSX attributes use double quotes; JS/TS strings use single quotes
- Boolean
truevalues are omitted:<Checkbox checked /> - Self-closing tags have a space before the slash:
<MyComponent /> - Multi-line JSX must be wrapped in parentheses
- No spaces inside JSX curly braces:
name={userName}notname={ userName }
Props
- Destructure props in the function parameter
- Use default parameters for optional props
- Avoid props spreading โ pass each prop explicitly
- Never use array index as
keyโ use stable unique identifiers
items.map((item) => <ListItem key={item.id} item={item} />); // โ
items.map((item, index) => <ListItem key={index} item={item} />); // โHooks Rules
- Only call Hooks at the top level โ never in loops, conditions, or nested functions
- Only call Hooks in React functions โ components or custom Hooks
useEffect,useCallback,useMemomust include all external dependencies- Use symmetric naming:
[count, setCount]
React Compiler Compatibility
- Never mutate State during rendering โ update in event handlers only
- Treat Props and State as immutable โ use functional updates
setUser(currentUser => ({ ...currentUser, age: currentUser.age + 1 })); // โ
Performance
- Avoid creating new objects/arrays/functions in render โ define externally or memoize
- Never define nested components inside another component's render function
Accessibility
- All
<img>tags must havealt(empty string""for decorative images) <a>tags must have content and a validhref- Interactive non-button elements need
roleand keyboard handlers โ prefer<button>directly
Next.js Standards
Server vs. Client Components
- Default to Server Components โ add
'use client'only when hooks, browser APIs, or event listeners are needed - Client Components cannot be
asyncfunctions
'use client';
import { useState } from 'react';
export default function SubmitButton() {
const [loading, setLoading] = useState(false);
return (
<button onClick={() => setLoading(true)}>
{loading ? 'Loading...' : 'Submit'}
</button>
);
}Image Optimization
Important
Must use next/image โ HTML <img> tags are forbidden. LCP images require the priority attribute. Always specify width and height (or fill).
import Image from 'next/image';
<Image src={heroImage} alt="Hero Banner" priority width={1200} height={600} />Script Loading
- Must use
next/scriptโ synchronous<script>tags are forbidden - Inline scripts must have an
idattribute - Do not place
<Script>inside<head>or Metadata
Metadata and SEO
- Use the Metadata API (
metadataobject orgenerateMetadata) - Never use
<head>tags ornext/head
Fonts
- Must use
next/fontโ importing Google Fonts via<link>is forbidden
Navigation
- Internal links: Must use
<Link>โ<a>for internal pages is forbidden - External links: Use
<a>withrel="noopener noreferrer"whentarget="_blank" - Programmatic navigation: Use
useRouterfromnext/navigation(nevernext/router)
Forbidden Patterns Summary
| Pattern | Reason | Alternative |
|---|---|---|
var | Function scope, causes bugs | const / let |
any | Bypasses type checking | Explicit type or unknown |
== / != | Implicit coercion | === / !== |
eval() | XSS security risk | Redesign |
javascript: URL | Security risk | onClick or Link |
| Inline event handlers | Hard to maintain | External JS or event delegation |
HTML <img> | Performance | next/image |
Plain <script> | Blocks rendering | next/script |
<a> for internal navigation | Full page refresh | <Link> component |
CSS !important | Breaks specificity | Reorganize selectors |
Array index as key | List update bugs | Stable unique ID |
Props spreading ...props | Unmaintainable | Pass each prop explicitly |
innerHTML / outerHTML | XSS risk | Direct text rendering or sanitization |
Changelog
4f6b6-on

