Coding Guidelines - AvengerDisassemble/KU-connect GitHub Wiki

Backend (NodeJS)

File Structure

/project-root
│
├── /src                       # Application source code
│   ├── /config                # Configuration files (e.g., DB, environment)
│   ├── /controllers           # Controllers to handle API requests & responses
│   ├── /routes                # Route definitions and endpoint organization
│   ├── /models                # Database models / schemas
│   ├── /services              # Business logic and service layer
│   ├── /middlewares           # Express middlewares (auth, validation, error handling)
│   ├── /utils                 # Utility functions and helpers
│   ├── /validators            # Input validation schemas
│   └── app.js                 # App initialization (Express app setup)
│
├── /tests                     # Automated tests (unit, integration)
├── .env                       # Environment variables
├── server.js                  # Server startup and HTTP server (entry point)
├── package.json
└── README.md

Naming convention

  1. Use camelCase for variables and functions (getUserData).
  2. Use PascalCase for classes and constructors (UserModel)
  3. Use UPPERCASE for constants (API_URL).
  4. Use kebab-case for file and folder names (user-controler.js).

Coding Style

The coding style shall follow the JavaScript Standard Style.

Documenting

The documenting standard will follow the JSDoc Standard.

Function

/**
 * Represents a book.
 * @param {string} title - The title of the book.
 * @param {string} author - The author of the book.
 */
function Book(title, author) {
}

Note: There is a "@constructor" included in the example. However, since we are writing a simple class, it won't be necessary.

Class

/** Class representing a point. */
class Point {
    /**
     * Create a point.
     * @param {number} x - The x value.
     * @param {number} y - The y value.
     */
    constructor(x, y) {
        // ...
    }

    /**
     * Get the x value.
     * @return {number} The x value.
     */
    getX() {
        // ...
    }

    /**
     * Get the y value.
     * @return {number} The y value.
     */
    getY() {
        // ...
    }

    /**
     * Convert a string containing two comma-separated numbers into a point.
     * @param {string} str - The string containing two comma-separated numbers.
     * @return {Point} A Point object.
     */
    static fromString(str) {
        // ...
    }
}

Module

/** @module color/mixer */

/** The name of the module. */
export const name = 'mixer';

/** The most recent blended color. */
export var lastColor = null;

/**
 * Blend two colors together.
 * @param {string} color1 - The first color, in hexadecimal format.
 * @param {string} color2 - The second color, in hexadecimal format.
 * @return {string} The blended color.
 */
export function blend(color1, color2) {}

// convert color to array of RGB values (0-255)
function rgbify(color) {}

export {
    /**
     * Get the red, green, and blue values of a color.
     * @function
     * @param {string} color - A color, in hexadecimal format.
     * @returns {Array.<number>} An array of the red, green, and blue values,
     * each ranging from 0 to 255.
     */
    rgbify as toRgb
}

Test

(Not yet finalized)

Frontend (React)

1. File Structure

src/
 ├─ assets/        # Static assets (e.g., logos, SVGs)
 ├─ components/    # Reusable UI components
 │   ├─ ui/        # Footer, Header, Guard, etc.
 │   └─ hooks/     # Custom hooks (e.g., useAuth)
 ├─ lib/           # Helper functions (e.g., utils.ts)
 ├─ pages/         # Page components, grouped by role
 │   ├─ admin/     # Admin dashboard
 │   ├─ employer/  # Employer dashboard
 │   ├─ professor/ # Professor dashboard
 │   ├─ student/   # Student dashboard
 │   └─ public/    # Landing, Login, NotFound
 ├─ services/      # API client logic (e.g., api.ts)
 ├─ styles/        # Global styles (CSS, Tailwind)
 ├─ utils/         # Shared utilities
 ├─ App.tsx        # Root component with router
 └─ main.tsx       # Entry point

2. Naming Conventions

  • Components: Use PascalCase and the .tsx file extension (e.g., Header.tsx, NoteCard.tsx).
  • Files & Helpers: Use camelCase for all other files (e.g., formatDate.ts, api.ts).
  • Types/Interfaces: Use PascalCase (e.g., User, ApiResponse).
  • Constants: Use UPPER_CASE with underscores (e.g., API_BASE_URL).
  • Variables, Functions: Use descriptive camelCase (e.g., userName, formatDate).
  • Booleans: Prefix with is, has, or can (e.g., isUserLoggedIn).

3. Component Structure

  • Use functional components (not class).
  • Keep components small and focused.
  • Order: imports → hooks/state → handlers → JSX return.
  • Use TypeScript interfaces/types for props.
  • Mark optional props with ? and set default values using default parameters.
import React from "react";

interface NoteCardProps {
  title: string;
  content: string;
  onDelete: () => void;
  age?: number; // optional
}

const NoteCard: React.FC<NoteCardProps> = ({ title, content, onDelete, age = 18 }) => {
  const handleClick = () => onDelete();

  return (
    <div className="note">
      <h1>{title}</h1>
      <p>{content} - {age}</p>
      <button onClick={handleClick}>Delete</button>
    </div>
  );
};

export default NoteCard;

4. Styling

  • Use Tailwind CSS.
  • Class names should be readable and grouped logically.
  • Use conditional classes with template strings.
<button className={isActive ? "bg-blue-500" : "bg-gray-300"}>
  Click
</button>

5. State & Hooks

  • Use React hooks such as useState, useEffect, and others.
  • Always define types explicitly when they cannot be inferred.
  • Use union types or generic parameters for complex states.
  • Extract repeated logic into custom hooks with proper typing.
const [count, setCount] = useState<number>(0);
const [user, setUser] = useState<User | null>(null);

useEffect(() => {
  console.log("User changed:", user);
}, [user]);

// Example of a custom hook
function useToggle(initialValue: boolean = false): [boolean, () => void] {
  const [value, setValue] = useState<boolean>(initialValue);
  const toggle = () => setValue((prev) => !prev);
  return [value, toggle];
}

6. Imports

  • Group imports in the following order:
    1. React.
    2. External libraries.
    3. Local Files: Components, hooks, or utils from within the project.
  • Use absolute imports (configured in tsconfig.json) instead of long relative paths.
  • Avoid unused imports; enforce cleanup with ESLint.

7. Event Handlers

  • Naming: Use descriptive names prefixed with a verb (e.g., handleClick, handleSubmit).
  • Placement: Define handler functions above the return statement.
  • Typing: Always specify event types for clarity and safety.
// Input change event
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
  setValue(e.target.value);
};

// Form submit event
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
  e.preventDefault();
  // submit logic
};

// Button click event
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
  console.log("Button clicked");
};
⚠️ **GitHub.com Fallback** ⚠️