Beyond the Tutorials: What Frontend Interviews Really Test and Why It Matters

Bridgit KaniniBridgit Kanini
10 min read

You’ve got the basics down — React, HTML/CSS, a couple of CRUD apps. Maybe even a few projects on your GitHub that you're proud of. You’re officially not in tutorial hell anymore. Hurray!

But when you sit across from an interviewer and they ask:

“Can you talk about performance optimization in your projects?”

or

“What’s the hardest bug you’ve ever solved?”

That’s when things get real.

This isn’t about white-boarding algorithms. It’s about showing that you understand how to build for the real world — where page load times matter, bundles grow without warning, and features need to work on a 4G phone in a rural town, not just your MacBook Pro.

This article is for frontend devs who want to move beyond tutorials and prepare for interviews that test how you think, how you debug, and how you solve problems.


The Bug That Made Me a Better Developer

Let’s start with the classic interview question:
"What’s the most difficult bug you’ve dealt with?"

This question is really an opportunity to show off — just a little — that you know your way around modern web development. But how do you make sure you’re telling a story that’s compelling, technically solid, and gives the interviewer insight into how you think?

Here’s an example of how I’d go about it:

In one of my earlier projects, I had built a dashboard that worked beautifully on desktop. But users on mobile were complaining that it was sluggish and sometimes didn’t respond at all.

I ran Lighthouse audits and noticed long scripting times. Turned out, I had rendered an entire table of thousands of rows—even when most weren’t visible.

That moment introduced me to:

Lazy Loading

Example:

const HeavyComponent = React.lazy(() => import('./HeavyComponent'));

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <HeavyComponent />
    </Suspense>
  );
}

Virtualization

Example:

import { FixedSizeList as List } from 'react-window';

const MyList = ({ items }) => (
  <List height={400} itemCount={items.length} itemSize={35} width={300}>
    {({ index, style }) => <div style={style}>{items[index]}</div>}
  </List>
);

The results? Page load dropped from 8 seconds to under 2 seconds, and time-to-interactive was cut in half.


Optimization Isn’t a Buzzword, It’s a Habit

The word “optimization” gets thrown around a lot in interviews, but what does it actually mean in a frontend context?

Real-World Examples

ConceptWhere I Applied It
Code SplittingBroke up monolithic bundle into dynamic imports
Tree ShakingSwitched from lodash to lodash-es
MemoizationUsed useMemo() & useCallback() around complex renders
Image OptimizationUsed srcSet & compressed WebP images
useEffect HygieneCleaned up subscriptions & timers

When you talk about these things in interviews, don’t just drop the term—tell the story of when you used it, and how it made something faster, smoother, or more reliable.


From Component Hell to Clean Architecture

How do you structure your React projects?

In a recent team project, we had components bloated with logic, props drilling all the way down, and repeated logic across screens. It wasn’t scalable.

So I proposed and led a refactor into:

  • Feature-based folders (e.g., /auth, /dashboard)

  • Hooks for business logic, shared across screens

  • Context API to lift state where needed

  • Error boundaries and Suspense for resilience

This made onboarding faster, reduced bugs, and made features more isolated for testing.


"Explain Virtual DOM" — But Show You Actually Get It

Now, when asked what the Virtual DOM is, I keep it simple:

“It’s React’s lightweight representation of the actual DOM. When state changes, React compares the new Virtual DOM with the previous one, and updates only what’s changed in the real DOM—this is what makes React fast.”

But then I go further:

const MemoizedList = React.memo(({ items }) => {
  return (
    <ul>
      {items.map(item => <li key={item.id}>{item.name}</li>)}
    </ul>
  );
});

That’s how you go from buzzword to proof.


Bundles, Build Tools & The Day I Discovered Source Maps

Debugging a production bug in a minified JS file taught me the power of source maps and bundle analyzers.

// Analyze your build size
pnpm add -D webpack-bundle-analyzer

With it, I learned:

  • One tiny package was pulling in half a megabyte of unused code

  • I could replace moment.js with native Intl.DateTimeFormat

  • I could switch to PNPM for faster, leaner installs


Testing Like a Dev Who Cares

When asked, “Do you write tests?”—your answer should never be a plain “Yes.”

Instead, talk about:

  • Testing stateful logic in custom hooks

  • Writing E2E tests with Cypress, or Playwright

  • Catching regressions before they ship

// React Testing Library
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import LoginForm from './LoginForm';

it('displays error on empty submit', () => {
  render(<LoginForm />);
  userEvent.click(screen.getByText(/Submit/i));
  expect(screen.getByText(/required/i)).toBeInTheDocument();
});

From Buzzwords to Real Impact

Here’s the real lesson:

Most interviewers don’t care if you memorize every hook or know the React docs by heart.

They care if you know how to solve problems. They care if you've been in the trenches — debugging layout issues at midnight, optimizing bundles for low-end devices, fixing bugs you can’t reproduce easily.

So here’s what I leave you with:

  • Build projects that simulate the real world (think dashboards, marketplaces, admin panels)

  • Optimize not just for performance, but for clarity and scalability

  • Don’t just say “I used lazy loading.” Tell them why, when, and what changed

Because interviews aren’t exams.
They’re conversations about what kind of developer you are — and how you think.


Common Buzzwords — That Are Really Engineering Wisdom

Here are some of the frontend buzzwords you’ll hear in interviews — and more importantly, what they really mean in practice.

10 Concepts to Know, Live, and Breathe

1. Lazy load images & components

Definition:
Lazy loading is a design pattern that delays the loading of non-critical resources until they’re needed, improving initial load time and performance.

Why It Matters:
Why load everything at once if the user may never scroll to it? By splitting your code and images, you can serve a faster, more responsive experience.

React Example – Components:

import React, { Suspense } from 'react';

const LazyComponent = React.lazy(() => import('./HeavyComponent'));

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <LazyComponent />
    </Suspense>
  );
}

For images:

<img src="image.jpg" loading="lazy" alt="..." />

Or using IntersectionObserver:

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      entry.target.src = entry.target.dataset.src;
      observer.unobserve(entry.target);
    }
  });
});

2. Make YOUR UI Accessible (WCAG)

Definition:
Accessibility (a11y) ensures your app can be used by people with disabilities — from keyboard users to screen readers.

Why It Matters:
It’s not just about compliance — it’s about empathy. Plus, it's required by law in many countries.

Best Practices:

  • Use semantic HTML (<button>, <nav>, <header>)

  • Use ARIA attributes when necessary

  • Ensure focus is visible and manageable

  • Always test with keyboard navigation

Code Tip:

<button aria-label="Close" onClick={closeModal}>
  <span aria-hidden="true">&times;</span>
</button>

3. Infinite Scrolling / Pagination

Definition:
Load more data as the user scrolls or paginates through content — improving performance and UX by not loading everything upfront.

When to Use What:

  • Infinite scroll for feeds (e.g., Twitter)

  • Pagination for search (e.g., Google)

With react-window (virtualization):

import { FixedSizeList as List } from 'react-window';

<List
  height={400}
  itemCount={items.length}
  itemSize={35}
  width="100%"
>
  {({ index, style }) => (
    <div style={style}>{items[index]}</div>
  )}
</List>

4. Design for Mobile

Definition:
Responsive design ensures your UI works across different screen sizes, from mobile to desktop.

Why It Matters:
Over 50% of users browse on mobile. If your app breaks on phones, you’ve already lost.

Code Tip:

.container {
  display: grid;
  grid-template-columns: 1fr;
}

@media(min-width: 768px) {
  .container {
    grid-template-columns: 1fr 1fr;
  }
}

5. Handle Browser Compatibility

Definition:
Ensure your site works consistently across all major browsers.

Why It Matters:
Different browsers interpret code slightly differently. Testing ensures a consistent user experience.

How to Do It:

  • Use Can I Use to check feature support

  • Test with BrowserStack or in-browser dev tools

  • Avoid non-standard APIs

Tools: BrowserStack, Sauce Labs, or real devices.


6. Optimize Bundle Size

Definition:
Bundle size refers to the amount of JavaScript and assets downloaded when your app loads.

Smaller bundles = faster apps.

Why It Matters:
Large bundles slow down page load and can frustrate users, especially on mobile networks.

Strategies:

  • Code splitting (React.lazy + Suspense)

  • Tree shaking (remove unused exports via modern bundlers like Vite or Webpack)

  • Dynamic imports

Code Tip:

const Modal = React.lazy(() => import('./Modal'));

7. Handle Forms Effectively

Definition:
Forms are central to most apps — they need to be intuitive, validated, and performant.

Why It Matters:
Bad form UX = rage quits.

Good form UX = conversions.

React Hook Form:

import { useForm } from 'react-hook-form';

function MyForm() {
  const { register, handleSubmit, formState: { errors } } = useForm();

  return (
    <form onSubmit={handleSubmit(data => console.log(data))}>
      <input {...register('email', { required: true })} />
      {errors.email && <p>Email is required</p>}
    </form>
  );
}

8. Build Responsive Navigation

Definition:
Design menus and navigation that work across devices — touch, keyboard, and screen reader.

Why It Matters:
Navigation is your app’s map. If it’s confusing or inaccessible, users will leave.

Code Tip – Hamburger Menu:

import { useState } from 'react';

function MobileNav() {
  const [isOpen, setIsOpen] = useState(false);

  const toggleMenu = () => setIsOpen(prev => !prev);

  return (
    <div>
      <button
        onClick={toggleMenu}
        aria-label="Toggle menu"
        aria-expanded={isOpen}
        aria-controls="mobile-menu"
        className="text-2xl"
      ></button>

      <nav
        id="mobile-menu"
        className={`${isOpen ? 'block' : 'hidden'} mt-2`}
      >
        <ul className="space-y-2">
          <li>
            <a href="/home" className="block text-blue-600 hover:underline">
              Home
            </a>
          </li>
          {/* Add more links here */}
        </ul>
      </nav>
    </div>
  );
}

9. Add Smooth Animations

Definition:
Animations bring your UI to life — transitions, hover effects, modals, etc.

Why It Matters:
They guide users, create delight, and improve usability — if done subtly.

With Framer Motion:

import { motion } from 'framer-motion';

<motion.div
  initial={{ opacity: 0 }}
  animate={{ opacity: 1 }}
  transition={{ duration: 0.5 }}
>
  Hello World!
</motion.div>

10. Set Up State Management

Definition:
State management is how you handle and share dynamic data (like user info or form inputs) across your app.

When to Use What:

  • useState/useReducer → local component logic

  • Context → light global state (e.g. theme, auth)

  • Redux/Zustand/Recoil → complex apps with lots of shared logic

Code Tip – Zustand:

import { create } from 'zustand';

const useStore = create(set => ({
  count: 0,
  increment: () => set(state => ({ count: state.count + 1 }))
}));

function Counter() {
  const { count, increment } = useStore();
  return <button onClick={increment}>{count}</button>;
}

9 Interview Questions That Are Really Just Good Engineering Prompts

Don’t get psyched out by “tricky” questions. Most interviewers just want to know how you think about tradeoffs, architecture, and user experience.

1. How do you design a scalable, reusable component library for a large web app?
→ Talk about atomic design, design systems, and using Storybook for isolated component testing.

2. How do you ensure responsiveness in your application across different devices?
→ Mention Flexbox, Grid, media queries, and maybe even CSS-in-JS libraries like Emotion or Styled Components.

3. How do you implement and optimize a UI component like a modal or a dropdown?
→ Explain useRef, useEffect, event delegation, closing on outside click/ESC, and accessibility.

4. How do you approach managing state in complex React apps?
→ Context for global light data, Redux for large apps, Zustand or Recoil for leaner needs, useReducer for local logic-heavy state.

5. What’s your approach to error boundaries and handling unexpected errors in React?
→ Mention ErrorBoundary components, logging tools like Sentry, and user-friendly error states.

6. How do you handle routing in single-page applications?
→ React Router, dynamic routing, nested routes, and lazy-loaded route components.

7. How do you ensure accessibility in your web applications?
→ Semantic HTML, ARIA attributes, keyboard navigation, and screen reader support.

8. How do you handle form validation in a React app?
→ Client-side validation with Yup + React Hook Form, plus server-side error messaging for edge cases.

9. How do you optimize an application for high interactivity (e.g., complex forms or real-time updates)?
→ Throttling, debouncing, useMemo, useCallback, and WebSockets if needed.


Final Thoughts: Build, Break, Brag (a Little)

The best way to prepare for these interviews? Build something ambitious, break it, fix it, and write about it. The more you internalize these patterns, the more natural your answers will feel.

And if all else fails, don’t be afraid to say,
“I don’t know offhand, but here’s how I’d figure it out…”
That’s also a flex.


Action step:
Pick one concept from this article—lazy loading, bundle analysis, testing—and revisit one of your old projects. Can you improve it using what you’ve just read?

Let your projects be your prep.
Let your bugs be your brag.

0
Subscribe to my newsletter

Read articles from Bridgit Kanini directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Bridgit Kanini
Bridgit Kanini