All jobs / Frontend / web developer
Tooling interview questions
Tooling questions a Frontend / web developer can be asked, from first job to senior. Open one to see the strongest answer and why it works.
How do you commit a CSS fix that accidentally includes a .env file in the working tree?
The strongest answer: Leave the secret out of the commit, add .env to gitignore, and rotate the key if it was ever committed
Why it works: Secrets do not belong in git. Unstage, ignore, rotate if they leaked.
- Never commit secrets.
- Unstage .env; gitignore it.
- Commit only the CSS.
- If it was pushed, rotate the key — history rewrite is not enough.
Your new team uses both ESLint and Prettier. What does each one do, and why have both?
The strongest answer: Prettier formats — spacing, quotes, line breaks — with no debate; ESLint finds likely bugs and enforces code rules. Run both on save and in CI, with ESLint’s formatting rules off so they don’t fight
Why it works: Right — a formatter and a linter answer different questions: how it looks versus whether it is probably wrong.
- Formatter for looks, linter for mistakes.
- Prettier: automatic formatting.
- ESLint: bug patterns and rules.
- Run both on save and in CI.
You need to ship a small button-style change. How do you use git?
The strongest answer: Branch from up-to-date main, keep the change focused, open a PR, and leave build output out of git
Why it works: A short-lived branch and a reviewable PR is how teams ship even tiny CSS.
- Small change, small branch.
- Update main, branch, commit the button CSS.
- Open a PR; let CI run.
- Don't commit dist/ or force-push shared branches.
CI installed different package versions than your laptop. Strongest fix?
The strongest answer: Commit the lockfile and install in CI with npm ci (or the equivalent) so the lock is the source of truth
Why it works: Reproducible installs are a lockfile plus a clean install command. That is the interview answer.
- Lock the graph, install from the lock.
- Commit package-lock / pnpm-lock / yarn.lock.
- CI: npm ci (or pnpm i --frozen-lockfile).
- Never commit node_modules.
A user reports that the Save button “does nothing”. You can reproduce it in your browser.
How do you use DevTools to find out where it fails?
The strongest answer: Console first for errors, then the Network tab: was a request sent, with what payload, what status and response came back; if nothing was sent, set a breakpoint in the click handler and step through
Why it works: Exactly — split the problem: did the click run, did a request leave, what came back. Each tab answers one of those in seconds.
- Observe before you guess.
- Console: any errors?
- Network: request, payload, status, response.
- Breakpoint in the handler if nothing is sent.
You need an API base URL in a Vite app without leaking a private key. What do you do?
The strongest answer: Expose only public values via import.meta.env.VITE_* ; keep secrets on the server
Why it works: Anything with the Vite public prefix is in the browser bundle. Base URLs yes; private keys no.
- Client env is public.
- VITE_* only for non-secrets (public API URL).
- Secrets stay on the server.
- Don't commit private keys.
Fast Refresh resets a component's state on every edit. What usually caused it?
The strongest answer: The file exports a component plus other values in a way that breaks the refresh contract — split the file; don't run side effects at module scope
Why it works: Vite / React Fast Refresh remounts when the module is not a clean component export. That's the interview detail.
- Keep component modules refresh-friendly.
- One component family per file when state keeps resetting.
- Don't mix random exports and module-scope fetches.
- Edit source, not dist.
A half-rolled feature is erroring in production. Strongest frontend move?
The strongest answer: Turn the remote flag off without waiting for a full deploy, then fix — don't leave users on the broken path
Why it works: Flags exist so you can stop blast radius in minutes. Then you fix.
- Stop the bleed first.
- Kill the flag.
- Confirm error rate drops.
- Then ship the fix and a post-incident note.
What does a bundler such as Webpack or Vite’s production build actually do for you, and what breaks tree shaking?
The strongest answer: It follows imports from the entry points into a module graph, transforms files through loaders or plugins, splits and minifies chunks, and drops unused exports — which needs static ES module imports and side-effect-free packages
Why it works: Right — graph, transform, split, optimise. Tree shaking depends on static imports; CommonJS or modules with side effects force the bundler to keep code.
- Entry, graph, transform, chunks.
- Loaders and plugins transform files.
- Static ES imports enable tree shaking.
- Side effects keep dead code alive.
Three product teams ship the same header with three bugs. How do you organize frontend platform work?
The strongest answer: A platform module with a clear API, versioning, and owners — products consume it and do not fork it
Why it works: Platform is an owned product: interface, release train, support. Snippets are how bugs multiply.
- Treat shared UI as a product.
- One owned package and API.
- Version and changelog.
- Products depend; they don't fork.
A critical vulnerability is published in a package three levels down your dependency tree. The scanner is red on every frontend repository.
What is your process?
The strongest answer: Check whether the vulnerable code is reachable in what we ship, upgrade the direct dependency that pulls it in, use a dated override only if no release fixes it, and verify via lockfile and CI
Why it works: Right — triage by exposure, fix at the direct dependency, keep any override temporary and visible, and let the lockfile prove what is installed.
- Triage, fix at the source, verify.
- Is the vulnerable code reachable?
- Upgrade the direct parent dependency.
- Overrides are dated stopgaps.
Shared packages in a monorepo keep causing diamond-dependency breaks. What do you enforce?
The strongest answer: Public package APIs, a changeset/version policy, and no deep imports into /src
Why it works: The public export map is the product. Deep imports and '*' versions are how diamonds appear.
- Treat package entrypoints as API.
- Export a public surface.
- Version through changesets.
- Ban deep /src imports and forced publishes.
How do you run a frontend hiring loop that predicts the work, not trivia?
The strongest answer: Pair on a realistic UI plus a11y and a trade-off talk, scored on a written rubric — not an algorithms-only screen for a CSS-heavy role
Why it works: The loop should look like the job: build, explain, listen. Rubrics keep interviewers honest.
- Hire for the work they will do.
- Pair on a real UI.
- Talk a11y and trade-offs.
- Score a rubric; skip trivia quizzes.
A bad deploy blanks checkout in one browser. What is the incident response?
The strongest answer: Detect via RUM and errors, roll back or flag-off, communicate, then bisect — don't only fix-forward with no rollback path
Why it works: Frontend incidents are real incidents: mitigate first (rollback/flag), then find the commit.
- Mitigate, then investigate.
- Confirm on RUM/errors.
- Rollback or kill the flag.
- Comms, then a timeline — no public blame.
A breaking change in the design system will hit forty apps. How do you ship it?
The strongest answer: Codemods, dual-run, and a deprecation window — major version, migrate the highest-traffic apps first
Why it works: A DS major is a migration program. Traffic order reduces blast radius.
- Breaking changes get a runway.
- Ship a major with a codemod.
- Deprecate, dual-run, then remove.
- Never retag latest.
You must remove a public hook from the platform package. How do you deprecate?
The strongest answer: Timeline, lint or codemod, dual export, metrics on remaining usage, then remove
Why it works: Public API is a promise. Deprecation is observable and reversible until the date.
- Deprecate in public.
- Warn in types and lint.
- Track remaining usage.
- Remove after the advertised date, not before.
Error rate spikes but only on a feature-flagged route. How do you set severity and act?
The strongest answer: Severity by user impact, disable the flag, preserve RUM and sourcemaps, then write the timeline
Why it works: SEV follows checkout/login impact, not the beauty of the chart. Flags are the fastest mitigation.
- Impact, then mitigate.
- Judge SEV by users, not error count alone.
- Kill the flag; keep artifacts.
- Write the timeline while it is fresh.
Interviewers disagree on what 'senior frontend' means. How do you make hiring consistent?
The strongest answer: A written rubric — a11y, performance, JS, system design, collaboration — scored independently and calibrated
Why it works: Calibration is how a loop stays fair. Years-of-React is a proxy, not a skill.
- Write the bar down.
- Score skills, not vibes.
- Calibrate interviewers on the same packet.
- Don't proxy seniority with years or pedigree.
Frontend is on-call for a peak-traffic storefront. What does a good playbook include?
The strongest answer: Dashboards, rollback, flag map, owners, a comms template, and known-bad browsers — practiced, not theoretical
Why it works: On-call for FE is rehearsed mitigation. The playbook names which flag and which rollback, not 'figure it out'.
- Practice the frontend incident.
- List dashboards, flags, and rollback.
- Name owners and comms.
- Never hotfix by editing minified prod.