Code Style Guide
Coding standards and conventions for the Constellation project.
Table of Contents
- TypeScript/JavaScript
- React Components
- File Organization
- Naming Conventions
- Import Organization
- Code Formatting
TypeScript/JavaScript
Use Strict Type Mode
// โ
GOOD
function processUser(user: User): Promise<void> {
// ...
}
// โ BAD
function processUser(user: any): any {
// ...
}
Prefer Const/Let Over Var
// โ
GOOD
const CONSTANT_VALUE = 'value';
let mutableValue = 0;
// โ BAD
var oldStyle = 'avoid this';
Use Template Literals
// โ
GOOD
const message = `Hello, ${name}! You have ${count} items.`;
// โ BAD
const message = 'Hello, ' + name + '! You have ' + count + ' items.';
Avoid Double Negatives
// โ
GOOD
const isAvailable = true;
if (isAvailable) { }
// โ BAD
const isNotUnavailable = true;
if (!isNotUnavailable) { }
Use Nullish Coalescing
// โ
GOOD
const value = config.value ?? 'default';
// โ BAD
const value = config.value || 'default'; // Fails for falsy values
Destructuring
// โ
GOOD
const { name, email } = user;
const { title = 'Untitled' } = props;
// โ BAD
const name = user.name;
const email = user.email;
React Components
Naming Convention
// โ
GOOD - PascalCase for components
export function UserProfile() { }
export const WorkspaceCard = () => { };
// โ BAD - camelCase for components
export function userProfile() { }
export const workspaceCard = () => { };
Functional Components Only
// โ
GOOD
export function MyComponent() {
return <div>Content</div>;
}
// โ BAD - Class components (legacy)
class MyComponent extends React.Component { }
Component Structure
'use client';
import React from 'react';
import { useHook } from '@/src/hooks/use-hook';
import { Button } from '@/src/components/ui/Button';
interface ComponentProps {
title: string;
onChange?: (value: string) => void;
}
export function MyComponent({ title, onChange }: ComponentProps) {
const [state, setState] = React.useState('');
return (
<div>
<h1>{title}</h1>
<Button onClick={() => setState('new')}>Click me</Button>
</div>
);
}
Order: 1. Imports 2. Type/Interface definitions 3. Component declaration 4. Props interface 5. Hook usage 6. State and effects 7. Event handlers 8. Render JSX
Props Interface
// โ
GOOD
interface CardProps {
title: string;
description?: string;
onClose: () => void;
children?: React.ReactNode;
}
export function Card({ title, description, onClose, children }: CardProps) {
// ...
}
// โ BAD - Inline props without type
export function Card(props: any) {
// ...
}
Use 'use client' For Interactive Components
// โ
GOOD
'use client';
import { useState } from 'react';
export function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
Avoid Direct DOM Manipulation
// โ
GOOD
export function InputField({ value, onChange }: Props) {
return (
<input
value={value}
onChange={(e) => onChange(e.target.value)}
/>
);
}
// โ BAD
export function InputField() {
useEffect(() => {
document.getElementById('input').value = 'test'; // Direct manipulation
}, []);
return <input id="input" />;
}
Key in Lists
// โ
GOOD
{items.map((item) => (
<Item key={item.id} {...item} />
))}
// โ BAD - Using index as key
{items.map((item, index) => (
<Item key={index} {...item} />
))}
Conditional Rendering
// โ
GOOD - Ternary for simple conditions
{isLoading ? <Spinner /> : <Content />}
// โ
GOOD - Logical AND for show/hide
{isVisible && <Content />}
// โ
GOOD - Early return for complex logic
if (!isReady) return null;
// โ BAD - Inline if-else
{if (isLoading) return <Spinner />} {/* Syntax error */}
File Organization
File Structure
src/
โโโ components/
โ โโโ ui/ # Shadcn/ui components
โ โ โโโ Button.tsx
โ โ โโโ Card.tsx
โ โ โโโ index.ts # Export barrel
โ โโโ common/ # Shared components
โ โ โโโ Header.tsx
โ โ โโโ Footer.tsx
โ โ โโโ Header.test.tsx
โ โโโ workspace/ # Feature-specific
โ โโโ WorkspaceCard.tsx
โ โโโ WorkspaceCard.test.tsx
โ โโโ WorkspaceList.tsx
โโโ hooks/
โ โโโ use-mobile.tsx
โ โโโ use-mobile.test.tsx
โ โโโ index.ts # Export barrel
โโโ lib/
โ โโโ api.ts # API client
โ โโโ utils.ts # Utilities
โ โโโ auth.ts # Auth logic
โ โโโ schemas/ # Zod schemas
โ โโโ user.ts
โ โโโ workspace.ts
โโโ services/
โ โโโ userService.ts
โ โโโ workspaceService.ts
โ โโโ apiClient.ts
โโโ types/
โโโ user.ts
โโโ workspace.ts
โโโ index.ts # Export barrel
One Component Per File
// โ
GOOD
MyComponent.tsx # Component
MyComponent.test.tsx # Tests
MyComponent.stories.tsx # Storybook (if using)
// โ BAD
MyComponents.tsx # Multiple components in one file
Barrel Exports
// โ
GOOD - src/components/ui/index.ts
export { Button } from './Button';
export { Card } from './Card';
export { Dialog } from './Dialog';
// Usage
import { Button, Card } from '@/src/components/ui';
Naming Conventions
Constants
// โ
GOOD - UPPER_SNAKE_CASE
const MAX_ATTEMPTS = 3;
const API_BASE_URL = 'https://api.example.com';
const FEATURE_FLAGS = { BETA_EDITOR: true };
// โ BAD
const maxAttempts = 3;
const api_url = 'https://api.example.com';
Functions & Variables
// โ
GOOD - camelCase
function getUserData() { }
const userName = 'John';
const isActive = true;
// โ BAD
function get_user_data() { }
const user_name = 'John';
const IsActive = true;
Boolean Variables
// โ
GOOD - prefix with is/has/can
const isLoading = true;
const hasError = false;
const canEdit = true;
const shouldRefresh = false;
// โ BAD
const loading = true;
const error = false;
Event Handlers
// โ
GOOD - prefix with on
function handleClick() { }
function handleSubmit() { }
const onClick = () => { };
// โ BAD
function click() { }
function submit() { }
API-related Functions
// โ
GOOD - clear intent
async function fetchUserData() { }
async function createWorkspace() { }
function deleteWorkspace() { }
// โ BAD
async function getUser() { }
async function addWorkspace() { }
Import Organization
Import Order
// 1. External packages
import React, { useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import { z } from 'zod';
// 2. Internal modules (absolute imports)
import { Button } from '@/src/components/ui/Button';
import { useWorkspace } from '@/src/hooks/use-workspace';
import { apiClient } from '@/src/lib/api';
import type { User } from '@/src/types/user';
// 3. Relative imports (if necessary)
import { helper } from './helper';
// 4. Side effects
import './styles.css';
Absolute Imports
// โ
GOOD - Absolute imports
import { Button } from '@/src/components/ui/Button';
import { useWorkspace } from '@/src/hooks/use-workspace';
// โ BAD - Relative imports (hard to refactor)
import { Button } from '../../components/ui/Button';
import { useWorkspace } from '../../../hooks/use-workspace';
Type Imports
// โ
GOOD - Separate type imports
import { Button } from '@/src/components/ui/Button';
import type { ButtonProps } from '@/src/components/ui/Button';
// โ BAD - Mixed imports
import { Button, type ButtonProps } from '@/src/components/ui/Button';
Code Formatting
Line Length
Keep lines under 100 characters for readability.
// โ
GOOD
const formattedText = `Welcome ${userName}, you have ${itemCount} items`;
// โ BAD - Too long
const excessivelyLongVariableNameThatMakesLineUnreadablyLongWhenUsed = 'value';
Function Parameters
// โ
GOOD
export function processUserData(
userId: string,
options: ProcessOptions,
callback: (result: Result) => void
): Promise<void> {
// ...
}
// โ BAD
export function processUserData(userId: string, options: ProcessOptions, callback: (result: Result) => void): Promise<void> {
// ...
}
Object Formatting
// โ
GOOD - Single line for simple objects
const config = { timeout: 5000, retries: 3 };
// โ
GOOD - Multi-line for complex objects
const config = {
timeout: 5000,
retries: 3,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
};
Comments
// โ
GOOD - Explains why, not what
// Cache user data for 5 minutes to reduce API calls
const USER_CACHE_TTL = 300000;
// โ
GOOD - Explains non-obvious code
// Convert timestamp to milliseconds (API returns seconds)
const timestampMs = timestamp * 1000;
// โ BAD - Obvious comments
// Set loading to true
setLoading(true);
// โ BAD - Outdated comments
// This fixes bug #123 (bug no longer exists)
const value = config.value ?? 0;
JSDoc for Public APIs
// โ
GOOD
/**
* Formats a date for display
* @param date - The date to format
* @param locale - Optional locale string (default: 'en-US')
* @returns Formatted date string
* @example
* formatDate(new Date('2024-01-15'))
* // Returns: 'Jan 15, 2024'
*/
export function formatDate(date: Date, locale: string = 'en-US'): string {
// ...
}
Tools & Automation
ESLint
# Check code style
bun lint
# Auto-fix issues
bun lint --fix
Prettier
Configured automatically for: - Indentation (2 spaces) - Line length (100 characters) - Semicolons - Single quotes - Trailing commas
TypeScript Strict Mode
Enable in tsconfig.json:
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true
}
}
Common Patterns
Custom Hook Pattern
// โ
GOOD
export function useUserData(userId: string) {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
(async () => {
try {
const data = await apiClient.get(`/users/${userId}`);
setUser(data);
} catch (err) {
setError(err as Error);
} finally {
setLoading(false);
}
})();
}, [userId]);
return { user, loading, error };
}
Component with API Call
// โ
GOOD
'use client';
interface UserCardProps {
userId: string;
}
export function UserCard({ userId }: UserCardProps) {
const { user, loading, error } = useUserData(userId);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
if (!user) return null;
return (
<div className="p-4 border rounded">
<h2>{user.name}</h2>
<p>{user.email}</p>
</div>
);
}
Error Handling
// โ
GOOD
async function fetchData() {
try {
const response = await apiClient.get('/data');
return response;
} catch (error) {
logger.error('Failed to fetch data', error);
throw new Error('Failed to fetch data');
}
}
Checklist Before Commit
- โ All TypeScript types are correct
- โ
No
anytypes used (except where necessary) - โ Components are properly named (PascalCase)
- โ Imports are organized correctly
- โ No console.log statements (use logger)
- โ Error handling is present
- โ Tests are written
- โ
ESLint passes:
bun lint - โ Code is readable and well-commented
- โ No hardcoded values in components
Related Documentation
- ๐ CONTRIBUTING.md - Contribution guidelines
- ๐งช TESTING.md - Testing standards
- ๐๏ธ ARCHITECTURE.md - Architecture patterns
Last Updated: January 2026