jam-cloud/.planning/codebase/CONVENTIONS.md

5.7 KiB

Coding Conventions

Analysis Date: 2026-01-11

Naming Patterns

Files:

  • React components: JK{ComponentName}.js (JamKazam brand prefix)
  • Examples: JKDashboardMain.js, JKTimeAgo.js, JKSessionModal.js in jam-ui/src/components/
  • Non-JK components: PascalCase.js (e.g., Avatar.js, FalconCardHeader.js)
  • Test files: *.test.js (Jest unit tests), *.spec.ts (Playwright E2E), *.spec.rb (RSpec)

Functions:

  • camelCase for all functions: getPersonById(), getUserDetail(), createAffiliatePartner()
  • Examples in jam-ui/src/helpers/rest.js
  • Async functions: No special prefix (async/await pattern used)
  • Event handlers: handle{EventName} pattern (e.g., handleClick, handleSubmit)

Variables:

  • camelCase for variables: firstName, loadingExperiences, classNames
  • State variables: const [firstName, setFirstName] = useState('Anthony');
  • Constants: UPPERCASE convention not strictly enforced, but used for module-level constants

Types:

  • Interfaces/Types: PascalCase, no I prefix
  • React PropTypes: Imported and used for component prop validation
  • Example from jam-ui/src/components/common/Avatar.js: import PropTypes from 'prop-types';

Code Style

Formatting:

  • Prettier enforced via .prettierrc in jam-ui/
  • Single quotes: true (use 'string' not "string")
  • Print width: 120 characters
  • Indentation: 2 spaces (standard Prettier default)
  • Semicolons: Not explicitly configured, follows Prettier defaults

Linting:

  • ESLint with .eslintrc.json in jam-ui/
  • Extends: react-app, prettier, plugin:react/recommended
  • Plugins: prettier
  • Rule enforcement: prettier/prettier set to error
  • Exception: react/no-unescaped-entities disabled

Import Organization

Order:

  1. React/core libraries (e.g., react, react-dom)
  2. Third-party packages (e.g., prop-types, @fortawesome/react-fontawesome)
  3. Internal/relative imports (e.g., ../../helpers/utils)
  4. Styles (if applicable)

Example from jam-ui/src/components/common/Avatar.js:

import React from 'react';
import PropTypes from 'prop-types';
import { isIterableArray } from '../../helpers/utils';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';

Grouping:

  • Blank lines between import groups
  • Alphabetical within groups (not strictly enforced)

Path Aliases:

  • No custom path aliases configured
  • Relative imports used throughout (../../, ../)

Error Handling

Patterns:

  • Promise-based error handling with .catch() or try/catch for async/await
  • Rails backend: Exceptions bubble to api_controller.rb base class
  • Frontend: Errors caught in apiFetch() wrapper, returned as rejected promises
  • Background jobs: Resque retry logic for transient failures

Error Types:

  • API errors: Returned as JSON with status codes
  • Client errors: Logged to console (development), reported to Bugsnag (production)
  • Validation errors: Handled by ActiveRecord validations, returned in API responses

Logging

Framework:

  • Rails logger for backend (configured in web/config/environments/)
  • Console logging for frontend (console.log, console.error)
  • Bugsnag for production error tracking (API key in web/config/application.rb)

Patterns:

  • Log at controller/action boundaries in Rails
  • Minimal logging in frontend (removed in production builds)
  • InfluxDB for time-series metrics (configured but disabled for production)

Comments

When to Comment:

  • Explain "why" not "what": Complex business logic, non-obvious algorithms
  • TODO comments: Mark incomplete features or planned improvements
  • FIXME comments: Mark known issues requiring fixes
  • XXX comments: Mark questionable code requiring review

JSDoc/PropTypes:

  • PropTypes used for React component prop validation
  • JSDoc not extensively used, code is generally self-documenting
  • Test files have header comments describing purpose

TODO Comments:

  • Format: // TODO: description or # TODO: description
  • Examples: // TODO: Expose jamClient globally for debugging. This is temporarily added. Remove it later.
  • No username or issue tracking in TODO comments

Function Design

Size:

  • Keep functions under 100 lines where practical
  • Extract complex logic into helper functions
  • Example: Large helpers like MixerHelper.js (1,270 lines) contain multiple related functions

Parameters:

  • Destructure object parameters in function signature
  • Example: const Avatar = ({ size, rounded, src, name, emoji, className }) => { ... }
  • Options objects for 4+ parameters: function update(id, options) { ... }

Return Values:

  • Explicit return statements
  • Promise-based returns for async operations
  • Example: return new Promise((resolve, reject) => { ... })

Module Design

Exports:

  • Named exports preferred: export const functionName = () => { ... }
  • Default exports for React components (not universal)
  • Barrel exports via index.js files (not extensively used)

React Components:

  • Functional components with hooks (React 16.13.1+)
  • Arrow function syntax: const Component = (props) => { ... }
  • PropTypes at bottom of file
  • Example component structure:
    import React from 'react';
    import PropTypes from 'prop-types';
    
    const Avatar = ({ size, src, name }) => {
      return <div>...</div>;
    };
    
    Avatar.propTypes = {
      size: PropTypes.string,
      src: PropTypes.string,
      name: PropTypes.string
    };
    
    export default Avatar;
    

Ruby/Rails Patterns:

  • Class-based models inheriting from ActiveRecord::Base
  • Controller actions follow RESTful conventions
  • Snake_case for file names, method names, variables
  • CamelCase for class names

Convention analysis: 2026-01-11 Update when patterns change