Moves
Everything you re-google
Short explanations, copy-ready snippets, and tags so you can find them again.
Testing & shipping
Behavior tests, accessibility, release checks, and recovery.
Test the behavior users depend on
Choose an observable outcome and test it through roles and labels. For example, submit invalid input and assert the visible error, rather than checking private state or CSS classes. Use small module tests for rules and a few browser tests for the critical journeys. The snippet assumes your local app has an Email field and a Save button; adapt it to your actual interface.
Check keyboard access and automated accessibility
Run an automated scan on the rendered state, then use Tab, Shift+Tab, Enter, Space, and Escape manually. Check focus visibility, focus order, drawer or dialog closing, and focus returning to the opener. Include errors and expanded controls, not only the initial page. Automated rules catch some defects; they cannot establish that the whole experience is accessible.
Investigate flaky browser tests
Replace fixed sleeps with assertions that wait for the expected state. Give tests independent accounts or records, control third-party responses, and keep traces from failures. Check whether the application, test data, or selector is unstable before adding retries. A test that passes on retry still needs investigation.
Verify the production build before release
Run checks and build, serve the generated production output using the framework's documented command, and exercise critical routes. Verify direct loads, unknown-route status, assets, and mobile navigation. After deployment, repeat a focused smoke check on the real URL; local build success alone does not establish a successful release.
Keep secrets out of browser bundles
Treat every value shipped to the browser as public. Vite exposes variables with its configured public prefix, including VITE_ by default, in client code. Keep private credentials on the server or in the deployment secret store, use minimal permissions, and never print them in build logs. If a credential leaks, revoke or rotate it; deleting the file does not remove repository history.
Make CI validate the same release inputs
Install from the committed lockfile, use a supported pinned runtime, and run lint, typechecking, tests, and build before release. Keep deployment credentials out of untrusted pull-request jobs. Protect the release branch with required checks, and verify that the deployment corresponds to the tested commit. This is guidance for your project pipeline, not a ready-to-copy workflow.
Capture errors with useful context
Record the failure, request or correlation ID, release identifier, and operation so you can connect a report to the deployed code. Keep stack traces on the server and show a recoverable message to the user. Exclude secrets and sensitive payloads from logs, and check that alerts reach someone who can act. Use structured fields rather than concatenating untrusted text.
Change database schemas in compatible stages
Use an expand-and-contract rollout: add the new structure first, deploy code compatible with old and new versions, backfill and validate data, then retire the old structure after the rollback window. Estimate locking and table rewrite costs before production changes. Application rollback is not automatically a database rollback.
Prove a backup can restore
Restore a backup into a separate environment and verify schema, representative records, application access, and the time required. A successful backup command proves creation, not recovery. Account for roles, permissions, object storage, and external services separately; a database dump does not contain your entire application. Record the recovery procedure and repeat it after significant changes.
Prepare rollback before publishing
Identify the last known-good artifact and the exact rollback action before deploying. Record a trigger, an owner, and a verification checklist. Confirm the previous application remains compatible with current data and configuration. After rollback, verify user journeys and error rates; switching a deployment alone does not prove recovery.
CSS
Layout, centering, and the snippets you re-google every week.
Center anything
Flexbox is the shortest path to both-axis centering. `place-items: center` on a grid does the same in one line if the parent has a height.
Flexbox essentials
Flex works on one axis at a time. Set `flex-direction` first, then reason about `justify-content` (main axis) and `align-items` (cross axis). `gap` replaces margin hacks.
Grid essentials
Grid is two-dimensional. `repeat(auto-fit, minmax(...))` gives a responsive card layout without a single media query.
Truncate and clamp text
Single-line truncation needs `overflow`, `white-space`, and `text-overflow` together. Multi-line uses the widely supported `-webkit-line-clamp`.
Sticky header that actually sticks
`position: sticky` fails silently when an ancestor has `overflow: hidden`/`auto`, or when no offset is set. Give it a `top` and check the ancestor chain.
JavaScript
Array methods, fetch, promises, and browser storage.
Array methods you reach for
`map` transforms, `filter` narrows, `reduce` folds. All three return new values — none of them mutate. `sort` and `reverse` DO mutate, so copy first with `toSorted` or a spread.
fetch JSON with error handling
`fetch` only rejects on network failure — a 404 or 500 still resolves. Always check `res.ok` yourself.
Promises and async patterns
Run independent work in parallel with `Promise.all`. Use `allSettled` when one failure shouldn't kill the batch, and `race`/`AbortController` for timeouts.
localStorage without the footguns
localStorage stores strings only, is synchronous, and throws in private mode or when full. Wrap reads in try/catch and never touch it during server rendering.
Debounce and throttle
Debounce waits until the noise stops (search inputs). Throttle guarantees a steady rate (scroll, resize).
Git / HTTP
Everyday git commands, status codes, and REST conventions.
Git commands for daily work
Ninety percent of git use is this handful of commands. Learn `switch` and `restore` — they split the overloaded `checkout` into two clear jobs.
Undoing things in git
Pick by blast radius: `restore` for files, `reset --soft` to re-do a commit message, `revert` for anything already pushed, `reflog` when you think work is gone.
HTTP status codes worth memorizing
2xx succeeded, 3xx go elsewhere, 4xx the caller is wrong, 5xx the server is wrong. These are the ones that come up in real APIs.
REST basics
Nouns in the path, verbs in the method. GET must be safe and cacheable, PUT/DELETE idempotent, POST neither.
HTTP headers that matter
Caching and content negotiation live in headers. `Cache-Control` decides whether your CDN does any work at all.
Game dev
Game loops, input, collision, and sprites in plain TypeScript and Canvas.
Fixed-timestep game loop
Run physics in fixed steps and render as often as the screen allows. An accumulator carries leftover time between frames, so a 60 Hz and a 144 Hz monitor simulate the same game. Clamp the frame time so a backgrounded tab doesn't try to catch up on minutes of updates. Phaser, Godot, and Unity do this for you; write it yourself when you're on plain Canvas or a renderer like PixiJS.
Frame-rate independent movement
Speeds should be per second, not per frame. Moving 4 px every frame means a 144 Hz player moves 2.4× faster than a 60 Hz one. Multiply by the elapsed time (delta time) instead. Good enough for simple games; use a fixed timestep when collisions or physics must be consistent.
Keyboard input without stuck keys
Track which keys are held in a Set and read it during update, instead of moving things inside event handlers. Use `e.code` (physical key) so WASD works on any keyboard layout. Clear the set on blur: if the player alt-tabs while holding a key, keyup never fires and the character walks forever.
Box collision (AABB)
Axis-aligned bounding boxes are the cheapest useful collision check: two rectangles overlap unless one is fully to the side of, above, or below the other. To resolve a hit, push the moving box out along the axis with the smaller overlap. Very fast objects can pass through thin walls between frames (tunneling) — use smaller steps or a physics engine like Rapier for that.
Sprite sheet animation on canvas
Pack animation frames side by side in one image and draw one slice at a time with the 9-argument `drawImage`. Pick the frame from elapsed time, not a frame counter, so the animation plays at the same speed on every monitor.
Crisp pixel-art scaling
Render at the game's native low resolution, then scale the canvas up with CSS. Turn off smoothing in both places, and scale by whole numbers — a 2.5× scale makes some pixels wider than others. Leftover space becomes letterboxing.