# Coding Conventions **Analysis Date:** 2026-02-15 ## Naming Patterns **Files:** - Frontend pages: PascalCase with `.jsx` extension (e.g., `Dashboard.jsx`, `LoginPage.jsx`, `WorkoutPage.jsx`) - Frontend components: PascalCase with `.jsx` extension (e.g., `Icons.jsx`) - Backend routes: `index.js` for main server file - CSS files: kebab-case or match component name (e.g., `index.css`, `App.css`) - Context files: Named with `Context` suffix (e.g., `AuthContext.jsx`) **Functions:** - Async functions: verb + noun pattern (e.g., `fetchProgram`, `fetchLogs`, `handleSubmit`) - Event handlers: `handle` prefix (e.g., `handleSubmit`, `handleSave`, `handleChange`) - Helper/utility functions: descriptive names without prefixes (e.g., `getCoachGreeting`, `getMuscleGroups`, `getWeekStart`) - Hook usage: Standard React hooks (e.g., `useState`, `useEffect`, `useContext`) - Middleware functions: descriptive names (e.g., `authMiddleware`) **Variables:** - State variables: camelCase (e.g., `user`, `loading`, `program`, `selectedDay`) - Constants (config): UPPER_SNAKE_CASE or camelCase (e.g., `API_URL`, `JWT_SECRET`, `PORT`) - Local variables: camelCase (e.g., `dayOfWeek`, `todayWorkout`, `lastWeight`) - Boolean variables: descriptive (e.g., `loading`, `editing`, `warmupDone`, `completedWarmups`) - IDs: numeric or snake_case from database (e.g., `user_id`, `program_exercise_id`, `program_day_id`) **Types:** - Objects/interfaces: use descriptive structure without explicit types (e.g., `{ id, email, onboarding_complete }`) - Database records: snake_case field names from schema (e.g., `password_hash`, `body_fat_pct`, `measured_at`) ## Code Style **Formatting:** - No explicit linter/formatter detected in config - Indentation: 2 spaces (observed in code) - Line length: typically under 100 characters - Quotes: single quotes in most files, double quotes in some (inconsistent but not enforced) - Semicolons: inconsistently used (some files omit, some include) **Linting:** - No ESLint, Prettier, or Biome config files detected - No type checking (no TypeScript or JSDoc type annotations) **Spacing:** - Components separated by blank lines - Function logic blocks separated by comments - Import statements grouped: React/library imports first, then local imports ## Import Organization **Order:** 1. React and core library imports (e.g., `import React from 'react'`) 2. External libraries (e.g., `react-router-dom`, Express packages) 3. Local imports (context, pages, components) 4. CSS/asset imports (e.g., `import './index.css'`) **Path Aliases:** - No path aliases configured (`@/` style paths not used) - Relative imports used throughout (e.g., `'./context/AuthContext'`, `'../components/Icons'`) - Relative paths: `../` for parent directory navigation in page imports **Examples:** ```javascript // Frontend (AuthContext.jsx) import { createContext, useContext, useState, useEffect } from 'react'; import { useAuth } from '../context/AuthContext'; import { Icon } from '../components/Icons'; import './App.css'; // Backend (index.js) const express = require('express'); const { Pool } = require('pg'); const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken'); ``` ## Error Handling **Patterns:** - **Frontend (React):** Try-catch blocks in async functions, error state managed with `useState` ```javascript try { const res = await fetch(`${API_URL}/auth/login`, { ... }); const data = await res.json(); if (!res.ok) throw new Error(data.error); // Handle success } catch (err) { setError(err.message); } ``` - **Backend (Express):** Try-catch blocks in route handlers with status code responses ```javascript try { // Database query or logic res.json(result); } catch (err) { if (err.code === '23505') return res.status(400).json({ error: 'Email already exists' }); console.error('Operation error:', err); res.status(500).json({ error: 'Server error' }); } ``` - **Error Response Format:** JSON with `error` key: `{ error: 'Human-readable message' }` - **Status Codes:** 400 (validation/conflict), 401 (auth), 404 (not found), 500 (server error) - **Empty error catches:** Some empty catch blocks without logging (e.g., `catch { logout(); }` in AuthContext) ## Logging **Framework:** Native `console.error()` only **Patterns:** - Error logging: `console.error('Context + error:', err)` - Backend operations logged: `console.error('Register error:', err)`, `console.error('Profile error:', err)` - Frontend operations: minimal logging (mostly silent failures) - No structured logging or log levels (DEBUG, INFO, WARN) - Log format: descriptive label + colon + error object **Examples from code:** ```javascript console.error('Failed to fetch program:', err); console.error('Login error:', err); console.error('Update profile error:', err); ``` ## Comments **When to Comment:** - Section headers for major logical blocks (e.g., `// Coach section`, `// Today's action`, `// Quick stats`) - Data structure explanations (e.g., `// Uppvärmningsövningar baserat på muskelgrupp`) - Complex calculations or business logic - Not applied to simple conditionals or obvious code **JSDoc/TSDoc:** - Not used - no type annotations or formal documentation - Inline comments rare and minimal **Examples:** ```javascript // Mappa övningar till muskelgrupper function getMuscleGroups(exercises) { ... } // Beräkna progress const completedExercises = exercises.filter(ex => { ... }); // Check if log exists for this set const existing = await pool.query(...); ``` ## Function Design **Size:** - Page/component functions: 40-250 lines (includes JSX) - Helper functions: 5-30 lines - Backend route handlers: 10-50 lines **Parameters:** - Named parameters for component props: `{ children, requireOnboarding = true }` - Function parameters: individual arguments or destructured objects - Query parameters: destructured from request (e.g., `const { user_id, date } = req.query`) **Return Values:** - React components return JSX directly - Async functions return Promise - Helper functions return computed values or arrays - Route handlers return via `res.json()` or `res.status().json()` **Async/Await:** - Preferred over `.then()` chains - Used consistently in all async operations - Combined with try-catch for error handling **Examples:** ```javascript const fetchProgram = async () => { if (program) return; // Early return try { const res = await fetch(`${API_URL}/programs/1`); const data = await res.json(); setProgram(data); } catch (err) { console.error('Failed to fetch program:', err); } }; // Helper function function isSameDay(d1, d2) { return d1.getDate() === d2.getDate() && d1.getMonth() === d2.getMonth() && d1.getFullYear() === d2.getFullYear(); } ``` ## Module Design **Exports:** - Frontend: Default exports for pages/contexts: `export default Dashboard` - Frontend: Named exports for utilities: `export const useAuth = () => useContext(AuthContext)` - Backend: Direct route handlers with `app.get()`, `app.post()` etc. (not module exports) - Contexts: `export function AuthProvider` + `export const useAuth` **Barrel Files:** - Icons component (`Icons.jsx`) exports multiple icon definitions and helper functions - Most modules single-responsibility (one component/context per file) **Examples:** ```javascript // Context export pattern export function AuthProvider({ children }) { ... } export const useAuth = () => useContext(AuthContext); // Component export pattern export default function LoginPage() { ... } // Backend (no module export pattern, direct app routing) app.post('/api/auth/login', async (req, res) => { ... }); ``` ## State Management **Frontend:** - React `useState` hooks for local component state - React Context API for global auth state (`AuthContext.jsx`) - Parent component state passed down as props (e.g., `App.jsx` manages view, program, logs) - No Redux, Zustand, or Jotai **Backend:** - In-memory database connections via `Pool` (pg package) - No state persistence between requests - Request-scoped data via middleware (e.g., `req.user` from JWT) ## CSS/Styling **Approach:** Plain CSS with CSS variables - CSS variables defined in `:root`: `--bg-primary`, `--text-primary`, `--accent`, etc. - Dark theme with fitness-oriented color palette - Classes: descriptive kebab-case (e.g., `dashboard-header`, `calendar-day`, `page-main`) - Utility/modifier classes: `.active`, `.today`, `.has-workout`, `.loading` - No CSS-in-JS or utility framework (no Tailwind, Styled Components) --- *Convention analysis: 2026-02-15*