docs: map existing codebase

This commit is contained in:
2026-02-15 21:49:31 +01:00
parent e629a20cec
commit 348330af4b
7 changed files with 1503 additions and 0 deletions
+244
View File
@@ -0,0 +1,244 @@
# 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<JSON | null>
- 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*