Expensify Coding Standards
Coding standards for the Expensify App. Each standard is a standalone file in rules/ with reasoning, examples, and applicability conditions.
Categories
| Category |
Prefix |
Focus |
| Performance |
PERF-* |
Render optimization, memo patterns, useEffect hygiene, data selection |
| Consistency |
CONSISTENCY-* |
Platform checks, magic values, unused props, ESLint discipline, localization, file naming, JSDoc |
| Clean React Patterns |
CLEAN-REACT-PATTERNS-* |
Composition, component ownership, state structure, prop typing, function components |
| UI |
UI-* |
Loading indicators, scrollable pages, styling conventions |
Quick Reference
Performance
- PERF-1 — No spread in renderItem
- PERF-2 — Return early before expensive work
- PERF-3 — Use OnyxListItemProvider in renderItem
- PERF-5 — Shallow over deep comparisons
- PERF-6 — Derive state from props
- PERF-7 — Reset via key prop
- PERF-8 — Handle events in handlers
- PERF-9 — No useEffect chains
- PERF-10 — No useEffect parent communication
- PERF-11 — Optimize data selection
- PERF-12 — Prevent memory leaks
- PERF-13 — Hoist iterator-independent calls
- PERF-14 — Use useSyncExternalStore
- PERF-15 — Clean up async Effects
- PERF-16 — Guard double initialization
- PERF-17 — Pass raw source, index on demand (no pre-built digest)
- PERF-18 — Use usePreMountDestination for RHP pre-mounting
- PERF-19 — Collection selectors return only what the consumer uses
Consistency
- CONSISTENCY-1 — No platform-specific checks in components
- CONSISTENCY-2 — No magic numbers/strings
- CONSISTENCY-3 — No code duplication
- CONSISTENCY-4 — No unused props
- CONSISTENCY-5 — Justify ESLint disables
- CONSISTENCY-6 — Proper error handling
- CONSISTENCY-7 — Localize all user-visible copy
- CONSISTENCY-8 — Localize numbers, amounts, dates and phone numbers
- CONSISTENCY-9 — Name files after what they export
- CONSISTENCY-10 — Follow the JSDoc style guidelines
- CONSISTENCY-11 — Track future work in an issue, not a TODO comment
- CONSISTENCY-12 — Name callbacks for what they do, not the event they handle
- CONSISTENCY-13 — Document component props with a JSDoc block comment
- CONSISTENCY-14 — Non-trivial new files start with a header description
- CONSISTENCY-15 — Comments explain why the code exists, not what it does
- CONSISTENCY-16 — Write comments as plain, natural sentences
- CONSISTENCY-17 — No AI-generated jargon in code or comments
- CONSISTENCY-18 — Pluralize with PluralForm, not ternaries on a count
Clean React Patterns
- CLEAN-REACT-PATTERNS-0 — React Compiler compliance
- CLEAN-REACT-PATTERNS-1 — Composition over configuration
- CLEAN-REACT-PATTERNS-2 — Components own their behavior
- CLEAN-REACT-PATTERNS-3 — Context-free component contracts
- CLEAN-REACT-PATTERNS-4 — No side-effect spaghetti
- CLEAN-REACT-PATTERNS-5 — Keep state narrow
- CLEAN-REACT-PATTERNS-6 — Import the exported prop type instead of ComponentProps
- CLEAN-REACT-PATTERNS-7 — Do not inline prop types on exported components
- CLEAN-REACT-PATTERNS-8 — Use function components, not class components
- CLEAN-REACT-PATTERNS-9 — Use TypeScript types, not propTypes or defaultProps
UI
- UI-1 — Use the correct loading indicator based on navigation context
- UI-2 — New pages must be scrollable
- UI-3 — Do not use inline style objects
Usage
During development: When writing or modifying src/ files, consult the relevant standard files for detailed conditions, examples, and exceptions.
During review: The code-inline-reviewer agent loads all standards from this directory. See .claude/agents/code-inline-reviewer.md.
1---2name: coding-standards3description: Provides coding standards for React Native — performance patterns, consistency rules, and clean React architecture. Use when writing, modifying, or reviewing code.4---56# Expensify Coding Standards78Coding standards for the Expensify App. Each standard is a standalone file in `rules/` with reasoning, examples, and applicability conditions.910## Categories1112| Category | Prefix | Focus |13|----------|--------|-------|14| Performance | `PERF-*` | Render optimization, memo patterns, useEffect hygiene, data selection |15| Consistency | `CONSISTENCY-*` | Platform checks, magic values, unused props, ESLint discipline, localization, file naming, JSDoc |16| Clean React Patterns | `CLEAN-REACT-PATTERNS-*` | Composition, component ownership, state structure, prop typing, function components |17| UI | `UI-*` | Loading indicators, scrollable pages, styling conventions |1819## Quick Reference2021### Performance22- [PERF-1](rules/perf-1-no-spread-in-renderitem.md) — No spread in renderItem23- [PERF-2](rules/perf-2-early-return.md) — Return early before expensive work24- [PERF-3](rules/perf-3-onyx-list-item-provider.md) — Use OnyxListItemProvider in renderItem25- [PERF-5](rules/perf-5-shallow-comparison.md) — Shallow over deep comparisons26- [PERF-6](rules/perf-6-derive-state-from-props.md) — Derive state from props27- [PERF-7](rules/perf-7-reset-via-key-prop.md) — Reset via key prop28- [PERF-8](rules/perf-8-events-in-handlers.md) — Handle events in handlers29- [PERF-9](rules/perf-9-no-useeffect-chains.md) — No useEffect chains30- [PERF-10](rules/perf-10-no-useeffect-parent-comm.md) — No useEffect parent communication31- [PERF-11](rules/perf-11-optimize-data-selection.md) — Optimize data selection32- [PERF-12](rules/perf-12-prevent-memory-leaks.md) — Prevent memory leaks33- [PERF-13](rules/perf-13-hoist-iterator-calls.md) — Hoist iterator-independent calls34- [PERF-14](rules/perf-14-use-sync-external-store.md) — Use useSyncExternalStore35- [PERF-15](rules/perf-15-cleanup-async-effects.md) — Clean up async Effects36- [PERF-16](rules/perf-16-guard-double-init.md) — Guard double initialization37- [PERF-17](rules/perf-17-pass-raw-index-on-demand.md) — Pass raw source, index on demand (no pre-built digest)38- [PERF-18](rules/perf-18-use-pre-mount-destination.md) — Use usePreMountDestination for RHP pre-mounting39- [PERF-19](rules/perf-19-scalar-collection-selectors.md) — Collection selectors return only what the consumer uses4041### Consistency42- [CONSISTENCY-1](rules/consistency-1-no-platform-checks.md) — No platform-specific checks in components43- [CONSISTENCY-2](rules/consistency-2-no-magic-values.md) — No magic numbers/strings44- [CONSISTENCY-3](rules/consistency-3-no-code-duplication.md) — No code duplication45- [CONSISTENCY-4](rules/consistency-4-no-unused-props.md) — No unused props46- [CONSISTENCY-5](rules/consistency-5-justify-eslint-disable.md) — Justify ESLint disables47- [CONSISTENCY-6](rules/consistency-6-proper-error-handling.md) — Proper error handling48- [CONSISTENCY-7](rules/consistency-7-localize-copy.md) — Localize all user-visible copy49- [CONSISTENCY-8](rules/consistency-8-localize-numbers-dates.md) — Localize numbers, amounts, dates and phone numbers50- [CONSISTENCY-9](rules/consistency-9-file-naming.md) — Name files after what they export51- [CONSISTENCY-10](rules/consistency-10-jsdoc.md) — Follow the JSDoc style guidelines52- [CONSISTENCY-11](rules/consistency-11-no-todo-comments.md) — Track future work in an issue, not a TODO comment53- [CONSISTENCY-12](rules/consistency-12-callback-named-for-action.md) — Name callbacks for what they do, not the event they handle54- [CONSISTENCY-13](rules/consistency-13-document-props.md) — Document component props with a JSDoc block comment55- [CONSISTENCY-14](rules/consistency-14-new-file-header.md) — Non-trivial new files start with a header description56- [CONSISTENCY-15](rules/consistency-15-comment-why.md) — Comments explain why the code exists, not what it does57- [CONSISTENCY-16](rules/consistency-16-plain-comment-style.md) — Write comments as plain, natural sentences58- [CONSISTENCY-17](rules/consistency-17-no-ai-jargon.md) — No AI-generated jargon in code or comments59- [CONSISTENCY-18](rules/consistency-18-plural-form.md) — Pluralize with PluralForm, not ternaries on a count6061### Clean React Patterns62- [CLEAN-REACT-PATTERNS-0](rules/clean-react-0-compiler.md) — React Compiler compliance63- [CLEAN-REACT-PATTERNS-1](rules/clean-react-1-composition-over-config.md) — Composition over configuration64- [CLEAN-REACT-PATTERNS-2](rules/clean-react-2-own-behavior.md) — Components own their behavior65- [CLEAN-REACT-PATTERNS-3](rules/clean-react-3-context-free-contracts.md) — Context-free component contracts66- [CLEAN-REACT-PATTERNS-4](rules/clean-react-4-no-side-effect-spaghetti.md) — No side-effect spaghetti67- [CLEAN-REACT-PATTERNS-5](rules/clean-react-5-narrow-state.md) — Keep state narrow68- [CLEAN-REACT-PATTERNS-6](rules/clean-react-6-no-componentprops.md) — Import the exported prop type instead of ComponentProps69- [CLEAN-REACT-PATTERNS-7](rules/clean-react-7-no-inline-prop-types.md) — Do not inline prop types on exported components70- [CLEAN-REACT-PATTERNS-8](rules/clean-react-8-no-class-components.md) — Use function components, not class components71- [CLEAN-REACT-PATTERNS-9](rules/clean-react-9-no-proptypes.md) — Use TypeScript types, not propTypes or defaultProps7273### UI74- [UI-1](rules/ui-1-correct-loading-indicator.md) — Use the correct loading indicator based on navigation context75- [UI-2](rules/ui-2-new-page-scrollview.md) — New pages must be scrollable76- [UI-3](rules/ui-3-no-inline-styles.md) — Do not use inline style objects7778## Usage7980**During development**: When writing or modifying `src/` files, consult the relevant standard files for detailed conditions, examples, and exceptions.8182**During review**: The code-inline-reviewer agent loads all standards from this directory. See `.claude/agents/code-inline-reviewer.md`.