Opinionated frontend development standards for modern React + TypeScript applications. Covers Suspense-first data fetching, lazy loading, feature-based architecture, MUI v7 styling, TanStack Router, performance optimization, and strict TypeScript practices.
67
67%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Passed
No known issues
Proper file and directory structure for maintainable, scalable frontend code in the the application.
Purpose: Domain-specific features with their own logic, API, and components
When to use:
Examples:
features/posts/ - Project catalog/post managementfeatures/blogs/ - Blog builder and renderingfeatures/auth/ - Authentication flowsStructure:
features/
my-feature/
api/
myFeatureApi.ts # API service layer
components/
MyFeatureMain.tsx # Main component
SubComponents/ # Related components
hooks/
useMyFeature.ts # Custom hooks
useSuspenseMyFeature.ts # Suspense hooks
helpers/
myFeatureHelpers.ts # Utility functions
types/
index.ts # TypeScript types
index.ts # Public exportsPurpose: Truly reusable components used across multiple features
When to use:
Examples:
components/SuspenseLoader/ - Loading wrappercomponents/CustomAppBar/ - Application headercomponents/ErrorBoundary/ - Error handlingcomponents/LoadingOverlay/ - Loading overlayStructure:
components/
SuspenseLoader/
SuspenseLoader.tsx
SuspenseLoader.test.tsx
CustomAppBar/
CustomAppBar.tsx
CustomAppBar.test.tsxBased on features/posts/ structure:
features/
posts/
api/
postApi.ts # API service layer (GET, POST, PUT, DELETE)
components/
PostTable.tsx # Main container component
grids/
PostDataGrid/
PostDataGrid.tsx
drawers/
ProjectPostDrawer/
ProjectPostDrawer.tsx
cells/
editors/
TextEditCell.tsx
renderers/
DateCell.tsx
toolbar/
CustomToolbar.tsx
hooks/
usePostQueries.ts # Regular queries
useSuspensePost.ts # Suspense queries
usePostMutations.ts # Mutations
useGridLayout.ts # Feature-specific hooks
helpers/
postHelpers.ts # Utility functions
validation.ts # Validation logic
types/
index.ts # TypeScript types/interfaces
queries/
postQueries.ts # Query key factories (optional)
context/
PostContext.tsx # React context (if needed)
index.ts # Public API exportsPurpose: Centralized API calls for the feature
Files:
{feature}Api.ts - Main API servicePattern:
// features/my-feature/api/myFeatureApi.ts
import apiClient from '@/lib/apiClient';
export const myFeatureApi = {
getItem: async (id: number) => {
const { data } = await apiClient.get(`/blog/items/${id}`);
return data;
},
createItem: async (payload) => {
const { data } = await apiClient.post('/blog/items', payload);
return data;
},
};Purpose: Feature-specific components
Organization:
Examples:
components/
MyFeatureMain.tsx # Main component
MyFeatureHeader.tsx # Supporting components
MyFeatureFooter.tsx
# OR with subdirectories:
containers/
MyFeatureContainer.tsx
presentational/
MyFeatureDisplay.tsx
blogs/
MyFeatureBlog.tsxPurpose: Custom hooks for the feature
Naming:
use prefix (camelCase)Examples:
hooks/
useMyFeature.ts # Main hook
useSuspenseMyFeature.ts # Suspense version
useMyFeatureMutations.ts # Mutations
useMyFeatureFilters.ts # Filters/searchPurpose: Utility functions specific to the feature
Examples:
helpers/
myFeatureHelpers.ts # General utilities
validation.ts # Validation logic
transblogers.ts # Data transblogations
constants.ts # ConstantsPurpose: TypeScript types and interfaces
Files:
types/
index.ts # Main types, exported
internal.ts # Internal types (not exported)From vite.config.ts lines 180-185:
| Alias | Resolves To | Use For |
|---|---|---|
@/ | src/ | Absolute imports from src root |
~types | src/types | Shared TypeScript types |
~components | src/components | Reusable components |
~features | src/features | Feature imports |
// ✅ PREFERRED - Use aliases for absolute imports
import { apiClient } from '@/lib/apiClient';
import { SuspenseLoader } from '~components/SuspenseLoader';
import { postApi } from '~features/posts/api/postApi';
import type { User } from '~types/user';
// ❌ AVOID - Relative paths from deep nesting
import { apiClient } from '../../../lib/apiClient';
import { SuspenseLoader } from '../../../components/SuspenseLoader';@/ (General):
@/lib/apiClient@/hooks/useAuth@/config/theme@/services/authService~types (Type Imports):
import type { Post } from '~types/post';
import type { User, UserRole } from '~types/user';~components (Reusable Components):
import { SuspenseLoader } from '~components/SuspenseLoader';
import { CustomAppBar } from '~components/CustomAppBar';
import { ErrorBoundary } from '~components/ErrorBoundary';~features (Feature Imports):
import { postApi } from '~features/posts/api/postApi';
import { useAuth } from '~features/auth/hooks/useAuth';Pattern: PascalCase with .tsx extension
MyComponent.tsx
PostDataGrid.tsx
CustomAppBar.tsxAvoid:
myComponent.tsx ❌my-component.tsx ❌MYCOMPONENT.tsx ❌Pattern: camelCase with use prefix, .ts extension
useMyFeature.ts
useSuspensePost.ts
useAuth.ts
useGridLayout.tsPattern: camelCase with Api suffix, .ts extension
myFeatureApi.ts
postApi.ts
userApi.tsPattern: camelCase with descriptive name, .ts extension
myFeatureHelpers.ts
validation.ts
transblogers.ts
constants.tsPattern: camelCase, index.ts or descriptive name
types/index.ts
types/post.ts
types/user.tsExample: features/posts/
Example: Adding export dialog to posts feature
Example: components/SuspenseLoader/
// 1. React and React-related
import React, { useState, useCallback, useMemo } from 'react';
import { lazy } from 'react';
// 2. Third-party libraries (alphabetical)
import { Box, Paper, Button, Grid } from '@mui/material';
import type { SxProps, Theme } from '@mui/material';
import { useSuspenseQuery, useQueryClient } from '@tanstack/react-query';
import { createFileRoute } from '@tanstack/react-router';
// 3. Alias imports (@ first, then ~)
import { apiClient } from '@/lib/apiClient';
import { useAuth } from '@/hooks/useAuth';
import { useMuiSnackbar } from '@/hooks/useMuiSnackbar';
import { SuspenseLoader } from '~components/SuspenseLoader';
import { postApi } from '~features/posts/api/postApi';
// 4. Type imports (grouped)
import type { Post } from '~types/post';
import type { User } from '~types/user';
// 5. Relative imports (same feature)
import { MySubComponent } from './MySubComponent';
import { useMyFeature } from '../hooks/useMyFeature';
import { myFeatureHelpers } from '../helpers/myFeatureHelpers';Use single quotes for all imports (project standard)
Export public API from feature for clean imports:
// features/my-feature/index.ts
// Export main components
export { MyFeatureMain } from './components/MyFeatureMain';
export { MyFeatureHeader } from './components/MyFeatureHeader';
// Export hooks
export { useMyFeature } from './hooks/useMyFeature';
export { useSuspenseMyFeature } from './hooks/useSuspenseMyFeature';
// Export API
export { myFeatureApi } from './api/myFeatureApi';
// Export types
export type { MyFeatureData, MyFeatureConfig } from './types';Usage:
// ✅ Clean import from feature index
import { MyFeatureMain, useMyFeature } from '~features/my-feature';
// ❌ Avoid deep imports (but OK if needed)
import { MyFeatureMain } from '~features/my-feature/components/MyFeatureMain';src/
├── features/ # Domain-specific features
│ ├── posts/
│ │ ├── api/
│ │ ├── components/
│ │ ├── hooks/
│ │ ├── helpers/
│ │ ├── types/
│ │ └── index.ts
│ ├── blogs/
│ └── auth/
│
├── components/ # Reusable components
│ ├── SuspenseLoader/
│ ├── CustomAppBar/
│ ├── ErrorBoundary/
│ └── LoadingOverlay/
│
├── routes/ # TanStack Router routes
│ ├── __root.tsx
│ ├── index.tsx
│ ├── project-catalog/
│ │ ├── index.tsx
│ │ └── create/
│ └── blogs/
│
├── hooks/ # Shared hooks
│ ├── useAuth.ts
│ ├── useMuiSnackbar.ts
│ └── useDebounce.ts
│
├── lib/ # Shared utilities
│ ├── apiClient.ts
│ └── utils.ts
│
├── types/ # Shared TypeScript types
│ ├── user.ts
│ ├── post.ts
│ └── common.ts
│
├── config/ # Configuration
│ └── theme.ts
│
└── App.tsx # Root componentKey Principles:
See Also: