frontend

React Error Boundary + error reporting hook

Frontend errors are inevitable, so I’d rather control the blast radius. I wrap unstable sections with an ErrorBoundary that shows a friendly fallback and captures context for reporting. I also avoid spamming the error tracker by including a fingerprin

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

Debounced search input (React)

Search boxes are a classic place to accidentally fire a request on every keystroke. I debounce the value that triggers the query (not the input rendering) so typing stays responsive, and I cancel/ignore stale requests so results don’t arrive out of or

IntersectionObserver infinite scroll hook

Scroll listeners are easy to get wrong and they can cause performance issues on long lists. IntersectionObserver lets the browser do the hard work: I put a sentinel div at the bottom of the list and trigger fetchNextPage when it becomes visible. I als

Vite env handling: explicit prefixes only

Leaking secrets into the browser bundle is an easy mistake. Vite only exposes env vars with the VITE_ prefix, and I keep that rule strict. I also define a small typed wrapper so components don’t read import.meta.env directly everywhere. The wrapper gi

MSW for frontend API mocking in tests

Brittle test suites often come from mocking fetch at every call site. MSW lets me mock at the network layer: components make real HTTP calls, but the test environment intercepts them and returns deterministic responses. That keeps tests closer to real

Playwright smoke test for auth flow

When auth breaks in the UI, it’s expensive and it always seems to happen at the worst time. I keep one or two Playwright smoke tests that cover the critical path: login, navigate, create something, logout. The goal isn’t to test every edge case; it’s

Accessible modal with focus trap

Modals are accessibility traps—literally. Without focus management, keyboard users can tab into the page behind the modal and get lost. I trap focus within the dialog while it’s open, restore focus to the trigger on close, and support Escape to dismis

Frontend: copy-to-clipboard with fallback

Copying code is a core interaction in a snippets app, and it needs to work reliably across browsers. The modern API is navigator.clipboard.writeText, but it requires HTTPS and permissions in some contexts. I try it first, and if it fails I fall back t

Sentry initialization with release + environment

Noisy error reporting without context turns into a pile of untriaged alerts. I initialize Sentry early, set the release from the git SHA, and tag the environment so I can separate staging from production. I also set a sample rate and capture only what

Prettier config for consistent formatting

Formatting consistency matters, but humans shouldn’t be the ones enforcing it in code review. Prettier makes diffs smaller and reviews more focused on logic. I keep the config minimal and aligned with team expectations (singleQuote, trailing commas, ~

React Query optimistic update for likes

Interactive UI should feel instant even when the network isn’t. With optimistic updates, I update the cache immediately and roll back if the server rejects the mutation. The trick is to keep optimistic state small and obvious: update a count and a boo