typescript

Exponential backoff with jitter for retries

Immediate retries are a great way to stampede a struggling dependency. I use exponential backoff with jitter so retries spread out naturally and don’t synchronize across instances, and I cap the maximum delay so worst-case latency doesn’t become unbou

Axios API client with interceptors

A centralized API client provides a single place to configure authentication, error handling, and request/response transformations. I use axios for its interceptor support and automatic JSON transformation. Request interceptors attach the JWT token fr

Zustand for lightweight state management

Zustand provides a minimalist alternative to Redux with less boilerplate and better TypeScript support. I create stores with create that hold state and actions. Unlike Context, Zustand doesn't cause unnecessary re-renders—components only update when t

React Router with protected routes

React Router v6 provides declarative routing with data loading and authentication guards. I wrap protected routes in a ProtectedRoute component that checks authentication state from context and redirects to login if needed. The Navigate component hand

Frontend: normalize and display server validation errors

Server-side validation is the source of truth, but raw error payloads are rarely UI-friendly. I normalize validation errors into a Record<field, message> shape so forms can render them consistently. The tricky detail is mapping server field path

TypeScript path aliases (tsconfig + bundler)

Deep relative imports are a maintainability tax. Once a project grows, ../../../ becomes noise and refactors get painful. I define a small set of path aliases (like @/* for app code) and keep them consistent across TypeScript, Jest/Vitest, and the bun

Form handling with React Hook Form

React Hook Form provides performant form handling with minimal re-renders. Unlike controlled components that re-render on every keystroke, it uses uncontrolled inputs with refs. The register function connects inputs to the form state, and handleSubmit

ESLint config that avoids bikeshedding

I want linting to catch bugs, not fuel style debates. I use ESLint for correctness rules (unused vars, no-floating-promises, React hooks rules) and let Prettier handle formatting. I keep overrides minimal and justified. I also treat lint as part of CI

Infinite scroll with Intersection Observer

Infinite scroll loads more content as users reach the bottom of a list, improving perceived performance over pagination. I use the Intersection Observer API to detect when a sentinel element becomes visible, then trigger the next page fetch. React Que

Typed env parsing with zod

Shipping a deploy with a missing env var is an easy way to create a confusing outage. process.env is just a bag of strings, so I parse env at startup, validate required variables, and fail fast with a clear message. The other win is type safety: once

Markdown rendering with react-markdown

Rich text content from Rails often comes as Markdown. The react-markdown library renders Markdown to React components with customizable styling and sanitization. I configure it to use syntax highlighting via react-syntax-highlighter for code blocks, c

React app structure with Vite and TypeScript

Vite provides lightning-fast dev server startup and hot module replacement compared to Create React App. I scaffold React projects with TypeScript for type safety across the entire frontend. The folder structure separates concerns: components for reus