IrisFrontend Engineer
Back to roles
Debrief

How it went, with candor.

Overall
9.0/ 10
Strong hire
Summary

The candidate demonstrates deep, practical expertise in building high-craft, high-traffic frontend products in React/TypeScript. Their approaches to component design, state management, performance, accessibility, and product polish reflect a strong engineering instinct and mature product sensibility, backed by concrete examples from real-world trading UIs. Weaknesses are minimal and largely nuanced edge cases rather than fundamentals.

Strengths
  • Excellent separation of concerns between data processing (web workers) and rendering (React) [turn 3, 7]
  • Thoughtful state management for real-time data, balancing responsiveness and render efficiency [turn 3, 5, 7]
  • Measurement-driven performance tuning (profiling memoization) [turn 9]
  • Clear, accurate explanations of accessibility techniques for keyboard/screen readers [turn 15]
  • Strong sense for UX polish vs. technical robustness, evidenced by handling of error states and SSR edge cases [turn 5, 11, 13]
  • Demonstrates modern, compositional component patterns (e.g., Modal API) with accessibility by default [turn 17, 19]
  • Considers non-happy-path user experiences and nuanced issues, e.g., Portaled elements and focus trapping [turn 19]
Concerns
  • Accessibility/explanation briefly glossed over some ARIA nuance—could share more implementation evidence, but grasp is strong overall [turn 15]
  • SSR/data hydration risks acknowledged, but not deeply explored for highly interactive scenarios [turn 11, 13]
Competencies

Component design

9.5 / 10

Described reusable/compound Modal APIs, presentational container splits, and focused sub-components. Always favors composition over prop bloat, addresses real-world pitfalls [turn 7, 17, 19].

State management

9.0 / 10

Exemplary understanding of keeping heavy state out of React, delineating server/local derived data, and recovering from sync errors [turn 3, 5].

Performance

9.0 / 10

Uses web workers, memoization, profiling tools, and optimizations like minimal prop change; selects the right tools for scale [turn 1, 7, 9].

Communication

8.5 / 10

Explanations are clear, organized, and grounded in experience; sometimes verbose, but candid, and clarifies complex design/context [most turns, esp. 5, 7, 17].

Product sense

9.0 / 10

Strong attention to user trust, data validity, accessibility, non-happy paths, and custom interactions; keeps UX at the center [turn 5, 11, 13, 15, 19].

Talk ratio1552 words
YouIris
78%22%

Conversation

21 turns
Iris

Walk me through a frontend project you're proud of. What was your role, and what were the most interesting technical decisions?

You

One front-end project that I'm really proud of was my work on Coinbase Advanced Trade. I am one of the main senior front-end and mobile engineers on the team working across both React web and React Native mobile surfaces for high traffic trading experience used, uh, by millions of traders. My role involved own critical parts of the trading UI end-to-end, including order entry flows, real-time market data surfaces, and complex trading interactions where correctness, latency, and UX policy, policy were extremely important. Some of the most interesting technical decisions were around performance and real-time data handling. For example, we used web workers to move heavy order book processing off the main thread, which helped keep the UI responsive even when receiving frequent data updates. We also rely on server-sent events for real-time communication in certain flows, which was a good fit for streaming server to client updates without the extra complexity of bi-directional WebSockets where we didn't need them.

Iris

Can you talk more about how you structured the state management for those real-time order book updates—where did you keep the data, how did you handle synchronisation with server changes, and what tools or libraries did you use?

You

Sure. For real-time order book updates, I try to keep the heavy data processing out-outside of React state. We, we would receive snapshots and incremental updates from the server, then process them in a web worker instead of directly inside React components. The worker maintained the in-memory order book representation, applied deltas, sorted and aggregated price levels, and sent back a lightweight view model for the UI to render. On the React side, the state was mostly focused on renderable data, visible price levels, spread, mid-market price, loading error states, and user interactions. We avoided story-- storing the full mutable order book directly in React state because that could trigger too many re-renders and hurt performance. For synchronization, the pattern was snapshot first, then order incremental updates. We had to handle stale or out of order updates, reconnects, and cases where the local book could become invalid, in which case we would rebuild from fresh snapshot. The main tools were React, React Native, TypeScript, Web Workers, and server sent events from server to client streaming where bi-directional WebSockets were not necessary. The libraries were those behind, uh, the API Coinbase libraries.

Iris

How did you handle error states and reconnection logic when the order book data stream broke or became invalid—what did the user see, and how did you decide when to show it versus silently resync in the background?

You

Of course, we handle it based on whether the data was still trustworthy. For brief disconnections, we kept the last valid order book visible and silently tried to reconnect or resync in the background, so we didn't interrupt the user unnecessarily. But if we detected the book was invalid, like missed sequence numbers, stale data, or failed resync, we stopped showing it as a live and display loading or unavailable state. The rule was simple. Recover silently when safe, but show a clear state when there is any risk, uh, the user could make a trading decision, uh, from incorrect data

Iris

Let’s dig into the frontend side—how did you design the React components for the order book UI to make them composable and performant, especially given all those real-time updates?

You

I designed the order book UI around small focused components. A container component handled data subscription state boundaries, while presentational components rendered rows, price levels, spread, depth bars, and loading error states. That made the UI easier to compose and test because most of the components only received, uh, already processed, uh, props. For performance, I avoided putting high frequency raw updates directly into the React state. The heavy processing happened outside the render path, and React receives a lightweight view model. Then we used, uh, memoization, stable keys, and careful prop shapes, so only the rows or sections that actually changed needed to re-render. The main principle was to keep React responsible for rendering, not for continuously calculating the order book. The separation kept the components reusable while also making the UI smoother under, you know, uh, real-time market updates.

Iris

Can you give a concrete example of how you used memoization—maybe with React.memo or useMemo—in your order book components, and how you confirmed it made a measurable performance difference?

You

A good example would be the order book row component. Each row receives props like price, size, total, and depth percentage. And I wrapped, uh, with React memo, so it would only re-render when that specific level changed. We also used, uh, useMemo for derived values like, uh, formatted prices, uh, grouped levels, and visible rows instead of recalculating, uh, their functions on every market update. To confirm the impact, I used React Dev Tools Profiler and browser performance tools to compare renders before and after that, and also to check the web workers', uh, performance and, you know, the stack trace of running.

Iris

If your order book UI needed to also support server-side rendering, what changes would you need to make to your current component and state architecture, and what new challenges would you expect?

You

I think I would keep the SSR layer limited to the static sh-shell, uh, layout, market title, empty loading state, and maybe an initial snapshot if, if available. Anything browser-only like web workers, uh, live SSE subscriptions, measurements, or virtualization logic will need to start only after hydration, usually inside useEffect or client-only components. The main challenges would be hydration mismatch and stale data. Real-time order book data changes so fast that the server render snapshot could already be outdated by the time the compo-- the client hydrates. So I probably would design the UI to treat SSR data as an initial placeholder, then quickly validate and re-sync from the live stream before marking the book as fully, uh, live.

Iris

With that in mind, how would you structure your components to avoid hydration mismatches when dealing with data that may already be stale by hydration—any specific techniques or patterns you’d use to minimize flashes or user confusion?

You

I would avoid rendering highly volatile order book rows as live on the server. The server would render a stable shell, market header, column labels, skeleton rows, and a clear connecting or loading market data state. Then after rehydration, the client would start the stream, fetch or validate a fresh snapshot, and only then render the live book

Iris

How do you ensure keyboard accessibility and screen reader support for complex, custom interactive components like your real-time order book or a custom select—can you walk me through your approach and any tools or roles you rely on?

You

I would say that my approach is to start with native HTML whenever possible and only go custom when the product really needs. For something like custom select, I'll follow the aria-combobox, listbox pattern, proper role, aria-expanded, uh, you know, aria-active, descendant, these kinds of properties native from the HTML elements. Keyboard support for arrows, Enter, Escape, Tab, visible focus state. Uh, and for something like real-time order book, I would usually avoid making every row interactive unless necessary. So I would structure it semantically, and I would see important status changes like reconnecting or market data unavailable with aria-live and avoid overwhelming screen readers with, you know, every single price update. I would test with keyboard-only navigation, React testing library, uh, Lighthouse, and ideally VoiceOver or NVDA to confirm the experience actually works.

Iris

When designing a reusable Modal component for a design system, what would its API look like, and how would you keep it flexible without becoming a kitchen sink?

You

I would probably keep the core API focused on the modal behavior, so like with props like open, onOpen change, title, description, children, and maybe size or variant. The component should handle the hard accessibility parts by default. So focus trap, uh, escape to close, uh, scroll locking, and returning focus to the trigger. And most importantly, to keep it flexible, I would use 100% the React composition-- component composition approach. Uh, I would compose it with sub-components instead of adding too many props. So Modal.Root, Modal.Header, Modal.Footer, uh, that lets teams cus-customize layout and con-content while the design system still owns behavior, spacing, and styling conventions. So yeah, um, mostly I would avoid one-off props [chuckles] unless they solve a common pattern across the product.

Iris

Can you give an example of a tricky edge case or accessibility nuance you encountered while building a composable modal component, and how you solved or would solve it?

You

Uh, one tricky ed- case is focus management, uh, when the modal contains, uh, Portaled components like dropdowns, tooltips, or date pickers. A naive focus trap can treat those elements as outside, quote-unquote, outside the modal, and immediately pull focus back, breaking keyboard navigation. So I think I would solve it, uh, by using a battle-tested primitive like radius dialog or React area, uh, making sure Portal, uh, children are registered within the modal focus scope and testing with keyboard-only navigation plus voiceover

Iris

Thanks for sharing your detailed approaches—you gave me a great sense of how you work.

Raw evaluation JSONfor the take-home rubric
{
  "overallScore": 9,
  "summary": "The candidate demonstrates deep, practical expertise in building high-craft, high-traffic frontend products in React/TypeScript. Their approaches to component design, state management, performance, accessibility, and product polish reflect a strong engineering instinct and mature product sensibility, backed by concrete examples from real-world trading UIs. Weaknesses are minimal and largely nuanced edge cases rather than fundamentals.",
  "strengths": [
    "Excellent separation of concerns between data processing (web workers) and rendering (React) [turn 3, 7]",
    "Thoughtful state management for real-time data, balancing responsiveness and render efficiency [turn 3, 5, 7]",
    "Measurement-driven performance tuning (profiling memoization) [turn 9]",
    "Clear, accurate explanations of accessibility techniques for keyboard/screen readers [turn 15]",
    "Strong sense for UX polish vs. technical robustness, evidenced by handling of error states and SSR edge cases [turn 5, 11, 13]",
    "Demonstrates modern, compositional component patterns (e.g., Modal API) with accessibility by default [turn 17, 19]",
    "Considers non-happy-path user experiences and nuanced issues, e.g., Portaled elements and focus trapping [turn 19]"
  ],
  "concerns": [
    "Accessibility/explanation briefly glossed over some ARIA nuance—could share more implementation evidence, but grasp is strong overall [turn 15]",
    "SSR/data hydration risks acknowledged, but not deeply explored for highly interactive scenarios [turn 11, 13]"
  ],
  "perCompetency": [
    {
      "competency": "Component design",
      "score": 9.5,
      "notes": "Described reusable/compound Modal APIs, presentational container splits, and focused sub-components. Always favors composition over prop bloat, addresses real-world pitfalls [turn 7, 17, 19]."
    },
    {
      "competency": "State management",
      "score": 9,
      "notes": "Exemplary understanding of keeping heavy state out of React, delineating server/local derived data, and recovering from sync errors [turn 3, 5]."
    },
    {
      "competency": "Performance",
      "score": 9,
      "notes": "Uses web workers, memoization, profiling tools, and optimizations like minimal prop change; selects the right tools for scale [turn 1, 7, 9]."
    },
    {
      "competency": "Communication",
      "score": 8.5,
      "notes": "Explanations are clear, organized, and grounded in experience; sometimes verbose, but candid, and clarifies complex design/context [most turns, esp. 5, 7, 17]."
    },
    {
      "competency": "Product sense",
      "score": 9,
      "notes": "Strong attention to user trust, data validity, accessibility, non-happy paths, and custom interactions; keeps UX at the center [turn 5, 11, 13, 15, 19]."
    }
  ],
  "recommendation": "strong_hire"
}