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

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

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

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

API pagination response contract (page info)

For list endpoints, the frontend needs predictable pagination metadata, not just an array. I return items plus pageInfo (endCursor, hasNextPage) so building infinite scroll is straightforward and the API stays extensible if you later add totals (which

OpenAPI generation for REST endpoints

API docs shouldn’t be a wiki page that drifts from reality. I generate an OpenAPI spec from code-adjacent definitions so changes get reviewed alongside implementation. The frontend benefits too: typed clients, mock servers, and even contract tests bec

API error shape that frontend can rely on

Inconsistent error responses cause death-by-a-thousand-cuts on the frontend. If one endpoint returns a string, another returns nested objects, and a third throws HTML, you end up with messy UI conditionals everywhere. I use a small set of stable error

Prisma: avoid N+1 with include/select

Prisma makes it easy to write readable queries, but you can still create N+1 patterns by fetching parents and then fetching children in a loop. I prefer using include or select to get related data in one query when the cardinality is reasonable. I als

React Hook Form + Zod resolver

Forms are where type safety and UX collide. react-hook-form keeps re-renders low, and Zod gives me a single schema I can share between frontend and backend if I want. I wire zodResolver so field-level errors show up automatically, and I keep a stable

Feature flags with a typed registry

Ad-hoc feature flags turn into a mess of magic strings faster than most teams expect. I keep a typed registry so flags are discoverable and refactor-safe, and I resolve them centrally (user/org/rollout percentage) instead of scattering logic across co

tRPC router pattern for type-safe APIs

Maintaining separate REST types and frontend client types can be a lot of overhead in TypeScript-heavy teams. With tRPC, the API types flow directly to the client, which reduces duplication and keeps refactors safe. Runtime validation still matters, s