Skip to content

Latest commit

 

History

History
158 lines (124 loc) · 8.87 KB

File metadata and controls

158 lines (124 loc) · 8.87 KB

PolicyEngine App Development Guidelines

CRITICAL: NEVER MERGE WITHOUT CI PASSING

NEVER run gh pr merge until ALL CI checks show "pass" status.

Before merging ANY PR:

  1. Run gh pr checks [PR_NUMBER] --repo PolicyEngine/policyengine-app
  2. Verify EVERY check shows "pass" (not "pending" or "fail")
  3. Wait if any checks are still "pending"
  4. Only merge when you see: CI pass, Lint pass, Vercel pass (the CI check name may include a Node version like CI (22.x))

If you merge before CI completes, you risk breaking production.

Build & Test Commands

  • Install: make install (npm ci & black)
  • Start dev server: make debug (or npm start)
  • Run all tests: make test or npm run test
  • Run single test: npx jest path/to/test.js or with pattern: npx jest -t "test name pattern"
  • Lint & format: make format (runs prettier & eslint fix, use this before committing)
  • Check lint only: npm run lint
  • Coverage report: Check the coverage/ directory after running tests

Code Style Guidelines

  • Node version: Use Node >=22.0.0 (use nvm to manage versions)
  • Formatting: Uses Prettier (default config) with ESLint
  • React:
    • Functional components with hooks
    • No need to import React in most files due to new JSX transform (React 17+)
    • Only import React when using React namespace features directly (React.lazy, React.Suspense, etc.)
    • Use named exports from React (e.g., import { useState, useEffect } from "react")
  • Imports:
    • Group by external/internal
    • Prefer named imports
    • Keep imports organized and minimize unused imports
  • Testing: Jest with React Testing Library; tests in __tests__ directory with .test.js suffix
  • File naming: Use PascalCase for components, camelCase for utilities
  • TypeScript: Gradually adopting; new files should use TypeScript when possible
  • Error handling: Use try/catch for API calls; display user-friendly error messages
  • Pre-commit hooks: Uses husky and lint-staged to enforce linting on commit
  • Component size: Keep functions less than 150 lines after formatting

Common Patterns & Libraries

  • UI Components: Uses Ant Design (antd) for UI components (Button, Switch, Dropdown, etc.)
  • State management: No global state - prefer props and lifting state up
  • React Router: Uses react-router-dom v6 with search params for state preservation
  • Charts/Graphs: Uses plotly.js and react-plotly.js for data visualization
  • Markdown: Uses react-markdown with plugins for rendering markdown content
  • Page Structure: Typically follows Header -> PageHeader -> Content -> Footer pattern
  • Country-specific content: Use the countryId hook and conditionals/props to handle US/UK differences
  • Image loading: Use require() for dynamic images rather than direct string paths

Common Gotchas & Best Practices

  • Use the spread operator for state updates: setState({...state, property: value})
  • Use regex with global flag (/pattern/g) when replacing multiple occurrences in strings
  • findInTree function navigates variable hierarchies using path strings like "input.household.children"
  • URL-encoded parameters need proper decoding (e.g., %5B to [, %5D to ])
  • React.useEffect with empty deps array ([]) runs once on mount, no array runs on every render
  • Always include all dependencies in React hooks' dependency arrays (especially with useCallback and useEffect)
  • For shared components used across multiple country pages (UK/US), create a common component and pass country info as props
  • When creating new pages, ensure they follow the same page structure as existing ones (i.e., include Header/Footer)
  • Follow the "PolicyEngine React commandments" in src/README.md for component structure
  • Add docstrings to all components and graceful error handling
  • When making changes, follow existing patterns in the codebase
  • Run npm run lint -- --max-warnings=0 locally to ensure the CI pipeline will pass (CI uses zero tolerance for warnings)

Accessibility Guidelines

  • Color contrast: Ensure text remains readable on hover states - avoid blue text on blue backgrounds
  • Prefer text underlines or other non-color indicators for hover states when possible
  • Add appropriate ARIA attributes to interactive and multimedia elements:
    • Use aria-label for iframes, images, and controls that need better descriptions
    • Include title attribute for iframes
  • Avoid using logical operators (&&) for compound assignments in event handlers - use explicit code blocks with braces {}
  • Test all interactive elements with keyboard navigation (Tab key)
  • When using ANTD components, check for accessibility-specific props and options
  • Image elements should always have descriptive alt text
  • Maintain focus visibility for keyboard users
  • Test with a screen reader periodically to verify interface usability

Blog Posts

General Content Guidelines

  • Keep URLs in blog post markdown files short (without query parameters) to prevent line-breaking issues
  • When adding blog posts, remember to remove the title (with the single #), description, and cover image
  • Use proper Markdown footnote syntax ([^1]) instead of superscript footnotes
  • New blog posts in posts.json should be added at the beginning of the array (most recent first)
  • For new blog posts from Medium, install mediumexporter and use it to download the post content
  • Image file paths should match the blog post filename in the posts.json entry

Writing Style Guidelines

  • Use factual, objective language throughout - avoid adjectives like "significantly," "slightly," or "progressively"
  • Present data without qualitative judgments - let numbers speak for themselves
  • Do not use title case for section headings or bullet points; use sentence case instead
  • Always use sentence case for headings (capitalize only the first word and proper nouns)
  • Avoid phrases like "small impact" or "large effect" - instead specify the exact percentage or numerical change
  • Don't round numbers unless necessary, and when rounding, indicate the level of precision
  • Ensure all chart titles could be quoted out of context and still provide full information
    • Example: "Income tax threshold freeze to 2030: Change in net income by income decile"
    • Include the specific reform name in the chart title
  • When describing change, specify baseline and reform values when possible (e.g., "from 12.20% to 12.23%")
  • Focus on "what" rather than "why" in descriptions of results
  • Avoid words that imply value judgments (e.g., "burden," "benefit," "progressive," "regressive")
  • When describing higher-numbered deciles, prefer "higher-income" over "rich" or "wealthy"
  • When describing lower-numbered deciles, prefer "lower-income" over "poor"
  • Use precise language: "would" rather than "could" or "might" when describing modeled outcomes

Article Review Standards

Based on our UK VAT thresholds article improvements, apply these standards to all PolicyEngine articles:

1. Active Voice and Conciseness

  • Use active voice with clear subjects (e.g., "The UK requires..." not "Businesses are required...")
  • Remove redundancy - Don't repeat information in multiple sentences
  • Eliminate wordiness - "We estimate that" → just state the finding
  • Avoid empty phrases - "It is important to note that" → just state the fact
  • Combine related sentences to reduce repetition

2. Data and Claims

  • Only use adjectives/adverbs supported by data - avoid "substantial," "significant," "slightly" unless quantified
  • Be precise about data sources - clearly attribute who constructed/analyzed what
  • Remove obvious statements - e.g., "Higher thresholds reduce revenue" when a chart shows this
  • Avoid hedging without reason - "approximately" only when rounding, not for exact model outputs

3. Structure and Flow

  • Lead with findings - put key results upfront, methodology details later
  • Remove duplicate information - don't present same data in both table and chart
  • Keep introductions tight - 1-2 paragraphs maximum
  • Make transitions implicit - avoid "In this section, we will..."

4. Technical Writing

  • Spell out acronyms on first use - "Retail Price Index (RPI)" then RPI thereafter
  • Clarify baselines and assumptions - be explicit about what's held constant
  • Describe distributions accurately - avoid "clustering" unless data shows clear bunching
  • Use consistent terminology - pick one term and stick with it

5. Conclusions

  • Keep conclusions factual - summarize findings without speculation
  • Be specific about future work - only mention planned analyses, not aspirations
  • Avoid promotional language - let the analysis speak for itself

6. Titles and Subtitles

  • Make titles action-oriented - "How X affects Y" rather than "Modelling X"
  • Include key finding in subtitle when possible
  • Avoid redundant location markers for country-specific sites (don't say "UK" on UK site)