Skip to main content

Coding Standards

This guide covers the coding standards and conventions used across the LAMISPlus 3.0 frontend codebase.

TypeScript

We use strict mode. Type everything properly.

// Good
const handleSubmit = (e: React.FormEvent<HTMLFormElement>): void => {
e.preventDefault();
};

// Bad - don't use any
const handleSubmit = (e: any) => {
e.preventDefault();
};

Use unknown instead of any when you don't know the type:

const handleError = (error: unknown): void => {
if (error instanceof Error) {
console.error(error.message);
}
};

Path Aliases

Always use path aliases instead of relative imports:

// Good
import { Button } from '@/components/Button';

// Bad
import { Button } from '../../../components/Button';

Available aliases:

  • @/* - ./src/*
  • @/components/* - ./src/components/*
  • @/features/* - ./src/features/*
  • @/hooks/* - ./src/hooks/*
  • @/config/* - ./src/config/*
  • @/utils/* - ./src/utils/*
  • @/types/* - ./src/types/*

Import Order

// 1. External dependencies
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';

// 2. Core imports (remote apps only)
import { useAppDispatch } from 'core/hooks';

// 3. Local imports
import { Button } from '@/components/common/Button';
import type { User } from '@/types/common';

// 4. Styles
import './styles.css';

File Naming

TypeConventionExample
ComponentsPascalCaseDataTable.tsx
HookscamelCase + use prefixuseAuth.ts
UtilscamelCaseerrorHandler.ts
ServicescamelCase + ServiceauthService.ts
TypesPascalCaseUser.ts
ConstantsUPPER_SNAKE_CASEAPI_ENDPOINTS

Component Structure

import React, { useState, useEffect } from 'react';

interface Props {
title: string;
onAction: () => void;
}

const MyComponent: React.FC<Props> = ({ title, onAction }) => {
const [state, setState] = useState('');

useEffect(() => {
// ...
}, []);

const handleClick = () => {
onAction();
};

return (
<div>
<h1>{title}</h1>
<button onClick={handleClick}>Action</button>
</div>
);
};

export default MyComponent;

Barrel Exports

Create an index.ts in each feature folder:

// features/auth/index.ts
export { default as Login } from './pages/Login';
export { default as Register } from './pages/Register';
export * from './types';
export { authService } from './services/authService';

Then import cleanly:

import { Login, authService } from '@/features/auth';

Git Commit Convention

We use Conventional Commits:

<type>(<scope>): <subject>

Types:

  • feat - New feature
  • fix - Bug fix
  • docs - Documentation
  • refactor - Refactoring
  • test - Tests
  • chore - Maintenance

Examples:

feat(auth): add password reset
fix(ehr): resolve patient search bug
docs: update setup instructions

Rules:

  • Keep subject under 100 characters
  • Use lowercase for type
  • No period at end of subject

Branch Naming

  • feature/description
  • fix/description
  • refactor/description
  • chore/description

Before You Commit

pnpm lint:fix
pnpm format
pnpm typecheck
pnpm test

All checks must pass before committing.

Best Practices

  • Keep remote apps focused on one domain
  • Reuse Core components when possible
  • Write tests for new features
  • Keep commits small and focused
  • Always use path aliases
  • No any types
  • Lazy load heavy components
  • Never commit .env files or credentials
  • Validate user input