Code Style Guide
Code Style Guide
Section titled “Code Style Guide”Follow these standards to keep the codebase consistent and maintainable.
General Principles
Section titled “General Principles”- Clarity over cleverness - Write code that’s easy to understand
- Consistency - Follow existing patterns in the codebase
- Simplicity - Don’t over-engineer solutions
- Document intent - Comments explain “why”, not “what”
TypeScript/JavaScript
Section titled “TypeScript/JavaScript”Formatting
Section titled “Formatting”We use Prettier with these settings:
{ "semi": true, "singleQuote": true, "tabWidth": 2, "trailingComma": "es5", "printWidth": 100}Naming Conventions
Section titled “Naming Conventions”// Variables and functions: camelCaseconst userName = 'John';function getUserData() { }
// Constants: UPPER_SNAKE_CASEconst MAX_RETRIES = 3;
// Classes and types: PascalCaseclass UserService { }interface UserProfile { }type ResponseData = { };
// Files: kebab-caseuser-profile.tsxapi-client.ts
// React components: PascalCaseUserProfile.tsxTypeScript
Section titled “TypeScript”// Prefer interfaces for objectsinterface User { id: string; name: string; email: string;}
// Use type for unions/intersectionstype Status = 'pending' | 'active' | 'deleted';
// Always type function parameters and returnsfunction getUser(id: string): Promise<User | null> { // ...}
// Avoid `any` - use `unknown` if type is truly unknownfunction processData(data: unknown) { if (typeof data === 'string') { // TypeScript now knows data is string }}Functions
Section titled “Functions”// Prefer arrow functions for callbacksconst users = data.map((item) => item.user);
// Use regular functions for hoistingfunction handleSubmit() { }
// Keep functions small and focused// If a function is > 30 lines, consider splitting it
// Document complex functions/** * Fetches scholarship data from the API * @param source - Scholarship source key * @param options - Filter options * @returns Array of scholarships or null on error */async function fetchScholarships( source: string, options?: FilterOptions): Promise<Scholarship[] | null> { // ...}Async/Await
Section titled “Async/Await”// Prefer async/await over .then()async function getData() { try { const response = await fetch('/api/data'); const data = await response.json(); return data; } catch (error) { console.error('Failed to fetch:', error); return null; }}
// Use Promise.all for parallel operationsconst [users, posts] = await Promise.all([ fetchUsers(), fetchPosts()]);Components
Section titled “Components”// Use function components with TypeScriptinterface ButtonProps { label: string; onClick: () => void; disabled?: boolean;}
export function Button({ label, onClick, disabled = false }: ButtonProps) { return ( <button onClick={onClick} disabled={disabled} className="btn-primary" > {label} </button> );}// Custom hooks start with "use"function useScholarships(source: string) { const [data, setData] = useState<Scholarship[]>([]); const [loading, setLoading] = useState(true); const [error, setError] = useState<Error | null>(null);
useEffect(() => { // ... }, [source]);
return { data, loading, error };}State Management
Section titled “State Management”// Keep state as local as possible// Lift state only when necessary// Use URL state for shareable UI state (filters, pagination)CSS/Tailwind
Section titled “CSS/Tailwind”Class Organization
Section titled “Class Organization”<!-- Order: layout → sizing → spacing → typography → colors → effects --><div class=" flex items-center justify-between w-full max-w-4xl p-4 mx-auto text-sm font-medium bg-white text-gray-900 rounded-lg shadow-md">Custom Classes
Section titled “Custom Classes”/* Use @apply sparingly - prefer Tailwind utilities */.glass-card { @apply bg-white/80 backdrop-blur-md border border-white/20 rounded-lg;}Responsive Design
Section titled “Responsive Design”<!-- Mobile-first approach --><div class=" flex flex-col md:flex-row gap-4 md:gap-8">Component Structure
Section titled “Component Structure”---// Importsimport Layout from '../layouts/Layout.astro';import Button from '../components/Button';
// Props interfaceinterface Props { title: string;}
// Props and logicconst { title } = Astro.props;const data = await fetchData();---
<!-- Template --><Layout title={title}> <main> <h1>{title}</h1> <Button client:load /> </main></Layout>
<style> /* Scoped styles */</style>Client Directives
Section titled “Client Directives”<!-- Only hydrate when visible --><HeavyComponent client:visible />
<!-- Hydrate on page load --><InteractiveComponent client:load />
<!-- Hydrate when idle --><LowPriorityComponent client:idle />API/Workers
Section titled “API/Workers”Response Format
Section titled “Response Format”// Always return JSONfunction jsonResponse(data, status = 200) { return new Response(JSON.stringify(data), { status, headers: { 'Content-Type': 'application/json' } });}
// Consistent error formatreturn jsonResponse({ error: 'Not found', code: 'NOT_FOUND'}, 404);Error Handling
Section titled “Error Handling”try { const data = await riskyOperation(); return jsonResponse(data);} catch (error) { console.error('Operation failed:', error); return jsonResponse({ error: 'Internal server error', message: process.env.NODE_ENV === 'development' ? error.message : undefined }, 500);}Commit Messages
Section titled “Commit Messages”<type>(<scope>): <description>
[body]
[footer]Types:
feat: New featurefix: Bug fixdocs: Documentationstyle: Formatting (no code change)refactor: Code restructuringtest: Testschore: Build/config changes
Examples:
feat(web): Add scholarship deadline remindersfix(api): Handle empty roster responsedocs: Update API referencerefactor(web): Extract scholarship filters to hookFile Organization
Section titled “File Organization”src/├── components/│ ├── ui/ # Reusable UI components│ ├── layout/ # Layout components│ └── features/ # Feature-specific components├── pages/ # Route pages├── lib/ # Utilities, API clients├── types/ # TypeScript types└── styles/ # Global stylesTesting
Section titled “Testing”// Descriptive test namesdescribe('ScholarshipCard', () => { it('displays the scholarship title', () => { }); it('shows deadline in correct format', () => { }); it('hides expired scholarships by default', () => { });});
// Arrange-Act-Assert patternit('filters scholarships by GPA', () => { // Arrange const scholarships = mockScholarships;
// Act const filtered = filterByGpa(scholarships, 3.5);
// Assert expect(filtered).toHaveLength(5); expect(filtered.every(s => s.gpaRequirement <= 3.5)).toBe(true);});Checklist
Section titled “Checklist”Before submitting code:
- Code follows style guide
- TypeScript has no errors
- Linting passes
- Build succeeds
- Tests pass (if applicable)
- Commit messages are clear