This project serves as a guide on how I set up every new project, following best practices to ensure code quality and maintainability.
-
Enforcing Code Standards. Here I specified how to setup Husky to automatically run Prettier & ESLint before every commit. With this we guarantee the quality of our code.
-
Project Architecture. Here I talk about different folder strucuters and which one could fit better the project needs.
This convention breaks component names into three meaningful parts:
-
BASE
: The core entity or subject the component relates to (e.g.,User
,Product
,Dashboard
). -
COMPOSITE
: Additional information describing the componentโs role or relation (e.g.,Profile
,Header
,Messages
). -
SUFFIX
: The type of UI element or its role in the system (e.g.,Card
,List
,Form
).
- Components
- Use kebab-case for files:
exercise-card.tsx
- Use PascalCase for component names:
ExerciseCard
- Utilities and Hooks
- Use kebab-case for files:
use-exercise.ts
- Prefix hooks with
use
:useExercise
- Types
- Use kebab-case for files:
exercise-types.ts
- Use PascalCase for type names:
Exercise
Error Handling: Use precise status codes and detailed messages, while ensuring no sensitive information is exposed.
- โ ErrorMessage: Something went wrong
- โ ErrorMessage: User not found. ID does not exist.
Consistent naming: Choose a convention and stick with it. Follow RESTful conventions.
- โ /create_user, /getUserDetail
- โ POST /users, GET /users/:id
Controlled Fetching: Enable data filtering through query parameters. Excessive or insufficient data can degrade performance.
- โ Over-fetching / Under-fetching: /users/{id}
- โ Use query parameters: GET /users/{id}?fields=name,email.
- IS for simple states:
- โ active
- โ isActive
- HAS for ownership:
- โ subsciption
- โ hasSubscription
- SHOULD for expected behavior:
- โ retry
- โ shouldRetry
- CAN for capabilities:
- โ edit
- โ canEdit
eventTypes.ts
type FormEvent = React.FormEvent<HTMLFormElement>;
type MouseEvent = React.MouseEvent<HTMLButtonElement>;
type ChangeEvent = React.ChangeEvent<HTMLInputElement>;
export { FormEvent, MouseEvent, ChangeEvent };
โ Avoid deeply nested validations that are hard to read.
โ Instead use invariants.
function invariant(condition: any, message?: string) {
if (condition) {
return;
}
throw new Error(message);
}
async function authenticateUser(credentials: {
username: string;
password: string;
}) {
const { username, password } = credentials;
invariant(
username && username.length >= 3,
"Username must be at least 3 characters long"
);
}
import { FixedSizeList as List } from 'react-window';
const list = [...]; // 10k items here
const Row = ({index, style}) => (
<div>
<User user={list[index]} />
</div>
);
const ExpensiveList = () => (
<List height={150} itemCount={10000} itemSize={35} width={300}>
{Row}
</List>
);