Convo — Technical Assessment Prep

Senior Frontend Engineer · React + Angular + TypeScript · Based on your CV and JD

22
Questions
8
Categories
2
Test questions
HIGH
Likely from Cat 1+2
🏗️
Micro-frontend architecture
Highest probability — direct JD requirement + your Turborepo background
VERY LIKELY
1
"Describe how you would architect a micro-frontend system for a multi-team product suite. How do you define boundaries, handle shared shell integration, and keep things consistent?"
▾
Answer framework — BSIC (Boundaries → Shell → Integration → Consistency)
Boundaries: Split by business domain, not tech layer. Each micro-frontend owns its route, data fetching, and deployment pipeline — no shared mutable state across boundaries. Team topology drives the split.
Shell / host app: Owns routing, auth token distribution, global error boundaries, and analytics. Mounts remotes dynamically. Contains zero business logic — it's infrastructure only.
Integration pattern: Module Federation (Webpack 5) for runtime composition. Each remote exposes a manifest; shell resolves at runtime — not build time. Shared dependencies (React, design-system) declared in shared config to avoid duplicate bundles.
Consistency: Shared component library with typed APIs. Storybook for documentation. Visual regression tests in CI — a remote cannot ship a component that breaks the design system.
Your evidence to cite
At Quecko I owned this across 5 products on a Turborepo monorepo — defined product boundaries, shared integration contracts, and a component library adopted by 4 external squads. CI/CD quality gates cut cross-team regressions by 50%.
Don't say this
Don't say "iframes" as a primary pattern — it's outdated. Don't conflate monorepo with micro-frontend; explain why Turborepo gave you equivalent domain isolation.
2
"What are the biggest failure modes in micro-frontend architectures and how do you prevent them?"
▾
Three real failure modes with solutions
Shared dependency hell: Different remotes load different React versions → runtime errors. Solution: strict singleton: true in Module Federation shared config, enforced via linting.
Design drift: Each team styles independently → UI inconsistency. Solution: design tokens as the single source of truth, visual regression in CI, a platform team that owns the component library.
Performance degradation: Too many remotes = too many network waterfalls. Solution: route-based code splitting, preload critical remotes, lazy-load the rest. Track bundle size as a CI metric.
Your evidence
Encountered design drift across the 5-product portfolio at Quecko — solved it with a typed component library and Storybook documentation. Teams couldn't diverge without breaking shared types.
3
"How do you handle communication between micro-frontends without creating tight coupling?"
▾
Communication patterns — ranked by coupling level
URL / router state (lowest coupling): Remotes read from the URL — no direct dependency. Works for navigation and filter state.
Custom events / event bus: Shell defines a typed event contract. Remotes publish and subscribe without knowing each other. EventEmitter or a tiny pub/sub library.
Shared state (use sparingly): Auth context, user preferences, feature flags — global only when truly global. Never business data. Use a context provider in the shell.
What to avoid: Direct imports between remotes. One remote importing another's components creates build-time coupling — defeats the architecture.
🎨
Design system ownership
Direct JD requirement — "own design-system adoption, component APIs and cross-application consistency"
VERY LIKELY
4
"How would you build a design system in React + TypeScript that serves multiple product teams? Walk through your key decisions."
▾
Answer framework — TAGE (Tokens → API → Governance → Enforcement)
Tokens first: Design tokens (colors, spacing, typography, radii) as the single source of truth — CSS custom properties or Style Dictionary. Teams consume tokens, never hardcoded values. One token change propagates everywhere.
Component API design: Composable over configurable — prefer children and slots over a prop explosion. Strict TypeScript types on every prop; the type IS the documentation. Semantic variants (variant="danger") not visual ones (color="red").
Governance: Platform team owns core library. Product teams extend locally, cannot fork. Breaking changes ship with deprecation cycles — old + new coexist for one version, then old is removed. Semantic versioning enforced.
Enforcement: Storybook for discovery. Visual regression (Chromatic / Percy) in CI — component screenshots diff on every PR. ESLint rules to prevent raw colour values. Review checklist for external squads.
Your evidence
Built and owned the shared component library at Quecko — typed React + TypeScript, adopted across 5 products, 4 external teams. Reduced cross-team integration bugs by 40%.
5
"A team keeps bypassing your design system and writing custom CSS. How do you handle it?"
▾
This is a people + process problem, not a technical one
Diagnose first: Why are they bypassing it? Missing component? Inflexible API? Poor documentation? Fix the root cause — don't just enforce.
Make compliance easier than bypassing: If writing custom CSS is faster, the system has failed. Every override should require more effort than using the system correctly.
Tooling enforcement: ESLint custom rules flagging raw hex values. Storybook required for every new component. Visual regression CI fails on undocumented UI changes.
Short term: Review the specific case — if their need is legitimate, add it to the system. If it's a shortcut, pair with them and implement it correctly together.
6
"How do you write a component API that works for both simple and complex use cases without becoming unmaintainable?"
▾
Compound component pattern + sensible defaults
Start with the 80% case: Simple props for the common use case. <Button variant="primary">Save</Button> should just work with zero config.
Compound components for the 20%: For complex cases, expose sub-components. <Select><Select.Trigger/><Select.Options>...</Select.Options></Select> — flexible without a prop explosion.
Never add props for one consumer: If only one team needs it, they can extend locally. One-off props pollute the API for everyone.
TypeScript discriminated unions: Use them for mutually exclusive prop combinations — the type system prevents invalid states before runtime.
⚡
Real-time UI & telemetry
JD: "telemetry/observability user interfaces and real-time updates" — your Blackjack.market + Joni.ai are perfect evidence
LIKELY
7
"How would you architect a real-time telemetry dashboard that shows live operational data — low latency, always consistent, never broken on reconnect?"
▾
Architecture: Event-driven state machine
Transport: WebSocket for push; SSE as fallback for environments that block WS. Never poll — polling is not real-time, it's periodic latency.
State model: Server pushes diffs, client applies them to a local state model, React renders from state — never from raw events. This decouples the render cycle from the event rate.
Reconnect logic: Exponential backoff with jitter. On reconnect, fetch a snapshot to sync state — don't assume the diff stream is complete. Show "reconnecting..." UI clearly, restore silently when stable.
Performance: Throttle renders to 60fps max using requestAnimationFrame. For high-frequency updates, batch state changes outside React and flush on the next frame. Virtualise long lists.
Your evidence
Built Blackjack.market's WebSocket state machine at Quecko — sub-100ms real-time updates, event-driven state transitions, silent reconnection. Same pattern as Joni.ai's streaming LLM interface.
8
"A telemetry widget shows stale data when the WebSocket reconnects. How do you debug and fix it?"
▾
Systematic debug approach
Reproduce: Simulate disconnect in DevTools (Network tab → offline), reconnect, observe state. Check the Redux/Zustand store or local state — is it stale in state, or is it stale in the WebSocket stream?
Root cause A — missed snapshot on reconnect: On reconnect, the client rejoins the event stream mid-sequence. Without a server-side snapshot on reconnect, it has a gap in the diff history. Fix: fetch a REST snapshot on every reconnect to resync.
Root cause B — stale closure: WebSocket message handler closed over old state. Fix: use a ref to hold current state in the handler, or use the functional updater form of setState.
Root cause C — event sequence mismatch: Events arrived out of order. Fix: server-side sequence numbers + client-side reorder buffer before applying diffs.
⚛️
React & TypeScript depth
Your core stack — they will probe senior-level patterns, not basics
MODERATE
9
"Walk me through how you'd handle complex shared state across micro-frontends. What are the trade-offs of different approaches?"
▾
Options ranked by coupling (low to high)
URL state: Zero coupling. Works for shareable, serialisable state (filters, selected IDs). Limitation: can't hold complex objects.
Custom events / event bus: Typed contract, loose coupling. Each remote subscribes without importing the other. Good for notifications and cross-remote side effects.
Shell-provided context: Auth, user prefs, feature flags. Shell owns the store; remotes consume via context. No remote-to-remote coupling. Never put business data here.
Shared state library (Zustand/Redux): Use only when the above aren't enough. Expose a typed slice, not the full store. Risk: tight coupling if not disciplined.
Senior signal
Mentioning the trade-offs unprompted — "I'd use URL state unless I needed reactivity, then typed events, then shell context only for truly global concerns" — shows architectural thinking, not just knowledge.
10
"What TypeScript patterns do you use to make component APIs safe and self-documenting?"
▾
Four patterns that show senior TypeScript depth
Discriminated unions: Mutually exclusive prop combinations — type ButtonProps = {variant:'primary'} | {variant:'link'; href:string}. The type system prevents invalid combinations before runtime.
Generic components: List<T> that accepts items and a renderItem — type-safe without knowing the data shape. Avoids casting to any.
Mapped types for variants: type Variants = 'primary'|'secondary'|'danger' then Record<Variants, CSSProperties> — adding a variant forces you to add its styles or the build fails.
Strict props over index signatures: Never [key:string]: unknown in component props. Explicit types or mapped types only — preserves autocomplete and catch-at-compile-time.
11
"How do you prevent unnecessary re-renders in a complex React application without making the code unmaintainable?"
▾
The right answer is: profile first, optimise second
Profile before optimising: React DevTools Profiler shows exactly what renders and why. Never add memo/callback blindly — it has cost too.
State colocation: Keep state as close to where it's used as possible. Global state causes global re-renders. The best optimisation is not lifting state unnecessarily.
React.memo for stable components: Wrap components that receive stable props but re-render because a parent re-renders. Only effective when props are reference-stable — pair with useMemo / useCallback on the parent side.
Selector pattern: With Zustand/Redux, select only the slice of state you need. Components re-render only when their slice changes — not the whole store.
🔺
Angular — the gap question
They WILL ask this. Prepare an honest, confident answer. This wins or loses the screen.
CERTAIN TO BE ASKED
12
"Your CV shows strong React but not much Angular. This role needs both. How do you see yourself ramping up, and how fast?"
▾
The exact answer — memorise this structure
Lead with honesty: "My production depth is React and TypeScript — I won't oversell Angular experience I don't have." This immediately builds trust.
Show what transfers: "The architectural thinking transfers directly — component lifecycle, dependency injection is structurally similar to React context, RxJS observables map to the event streams I've built, TypeScript is the same language. I'm not starting from zero."
Be specific about ramp time: "Given my TypeScript depth and the architectural overlap, I'd be reviewing existing Angular code confidently in week 1, contributing in week 2-3, and leading Angular work by month 2. I've done faster ramps — I learned Next.js in production at Quecko."
Flip it: "The bigger value I bring is the micro-frontend and design system ownership this role needs — most Angular engineers don't have that either."
Do NOT say this
"I know Angular" if you don't — they may follow up with specifics. Don't say "I can learn anything" — it sounds vague. Be specific and honest.
13
"What do you know about Angular's component model, change detection, and how it differs from React?"
▾
What you CAN say accurately
Component model: Angular components are class-based with decorators (@Component), template HTML, and styles — more structured than React's function components. Two-way data binding with [(ngModel)] vs React's controlled components.
Change detection: Angular uses Zone.js to detect changes automatically — any async operation (setTimeout, HTTP, events) triggers a change detection cycle. React uses the virtual DOM diff. Angular's OnPush strategy is equivalent to React.memo — only re-check when inputs change.
Dependency injection: Angular has a built-in DI container — services are injectable singletons by default. In React you'd use Context or a state library for the same pattern.
RxJS: Angular uses Observables (RxJS) for async data and events — equivalent to Promises but with stream operators (map, filter, switchMap). My WebSocket event streams are the same mental model.
🧪
Testing strategy
JD explicitly lists component, integration, E2E testing and visual regression
MODERATE
14
"Walk through your frontend testing strategy. What do you test at each layer and why?"
▾
Testing pyramid — frontend version
Unit (component) tests: Test component logic and rendering in isolation. React Testing Library — test what the user sees, not implementation details. Fast, cheap, run on every commit. Cover: conditional rendering, error states, user interactions.
Integration tests: Test components working together with real data flow. Mock the network layer only. Test: forms submitting, data loading states, multi-step flows.
Visual regression (Storybook + Chromatic): Screenshot every component in every state on every PR. Diff against baseline. Catches unintended design system changes before they ship.
E2E (Playwright): Test critical user journeys only — login, key workflows, payment flows. Expensive and slow — reserve for the paths that must never break.
Your evidence
At Quecko I wrote Playwright E2E suites and introduced Storybook + visual regression. CI/CD quality gates cut QA regressions by 50%. I set these as team standards for external squads too.
15
"A visual regression test is flaky — sometimes passes, sometimes fails with pixel-level diffs. How do you fix it?"
▾
Common causes and fixes
Anti-aliasing / font rendering differences: Screenshots differ between OS. Fix: run all visual regression tests in a fixed Docker image (Linux only) — eliminate environment variance.
Animation frames captured mid-animation: Component is still transitioning when screenshot is taken. Fix: disable CSS animations in test mode (* { animation: none !important }) or wait for a stable state.
Dynamic content (dates, random IDs): Snapshot contains "Today, 26 Sep" which changes daily. Fix: mock dates and dynamic values before rendering in Storybook stories.
Set a pixel threshold: Allow 0.1% pixel diff tolerance — catches real regressions but ignores subpixel antialiasing noise. Most tools (Chromatic, Percy) support this natively.
🚀
Performance engineering
JD: "browser performance engineering" — your 28pt PageSpeed score is perfect evidence
MODERATE
16
"A Studio interface loads slowly. Walk through how you'd diagnose and fix the performance problem."
▾
Systematic performance debug — measure, identify, fix
Measure first: Lighthouse / WebPageTest for initial load. React DevTools Profiler for runtime rendering. Performance tab in DevTools for long tasks. Never optimise without data.
Initial load — bundle size: webpack-bundle-analyzer to find large dependencies. Code-split at the route level — each micro-frontend should be its own chunk. Lazy-load non-critical remotes.
Initial load — network: Preload critical assets. Preconnect to API hosts. Use a CDN. HTTP/2 for parallel requests. Eliminate render-blocking scripts.
Runtime — render performance: Profile with React DevTools to find expensive components. Virtualise long lists (react-window). Debounce search inputs. Batch state updates.
Your evidence
Improved PageSpeed scores by average 28 points across 10+ client projects at Cyber Peak through systematic performance auditing — asset optimisation, lazy loading, render-blocking elimination.
17
"How do you make a data-heavy dashboard accessible without killing performance?"
▾
Accessibility + performance together
Virtualise the list, not the DOM: Render only visible rows (react-window / react-virtual). Screen readers still navigate the full list through ARIA — use aria-rowcount and aria-rowindex.
Pause updates when not visible: Use IntersectionObserver to pause live-updating widgets when off-screen. Announce updates to screen readers with aria-live="polite" — not "assertive" (too aggressive for frequent updates).
Charts: SVG charts are accessible with role="img" + aria-label + a visually-hidden data table as fallback. Canvas charts need more work — generate an accessible alternative.
Respect prefers-reduced-motion: Disable animations for users who need it — improves performance too as a side effect.
💬
Behavioural / situational
CV-based questions — they will pull from your Joni.ai, Quecko, and multi-team experience
MODERATE
18
"Tell me about a time you had to establish frontend standards for external implementation teams. How did you do it?"
▾
STAR format — use your Quecko story
Situation: At Quecko we had 4 external implementation squads building on the same design system. Without standards, each team would diverge — breaking the shared UI consistency.
Task: I owned setting the standards — component API contracts, review processes, and documentation — so external teams could contribute without breaking the system.
Action: Wrote a component contribution guide, created Storybook documentation for every shared component, built a review checklist for external PRs, and set up visual regression CI that blocked merges with design system violations.
Result: Cross-team integration bugs dropped by 40%. Release cycle time reduced by 35%. The checklist became the team's onboarding document for new squads.
19
"Describe a situation where a performance issue made it to production. How did you handle it?"
▾
Be honest — every senior engineer has this story
The story structure: Identify what happened → how you detected it → immediate mitigation → root cause fix → prevention added to process.
Key signal to interviewers: What did you add to your process so it doesn't happen again? CI bundle size limits, performance budgets in Lighthouse CI, required profiling sign-off before merging complex components.
If you don't have a specific story: "We caught a rendering issue in staging on the Joni.ai project — a component was re-rendering on every keystroke due to an unstable reference. I added React DevTools profiling to our pre-release checklist as a result."
20
"How do you review code from a contractor or junior developer on the frontend? What do you look for?"
▾
Shows your standards + mentorship approach
First pass — correctness: Does it do what the ticket says? Is there a test? Does it handle loading, error, and empty states?
Second pass — design system: Is it using the right components? Any raw hardcoded values that should be tokens? Would it pass visual regression?
Third pass — TypeScript: Any any casts? Prop types explicit or implicit? Could the type system have caught this bug at compile time?
Tone: Comments are about the code, not the person. Always explain why, not just what. Suggest, don't dictate on style. Block only on correctness and security issues — let style debates go to the linter.
21
"Why Convo specifically? What draws you to this role?"
▾
Don't wing this — prepare it
Role alignment: "The Studio and sales-cockpit work is the kind of complex analytical UI I've been building at Quecko — real-time data, multi-team consistency, design system ownership. It's exactly my stack."
Product interest: "Convo builds collaboration tools that people use in their daily work — the quality bar for real-time UI is high. That's where I do my best work."
Technical challenge: "The micro-frontend architecture for a product at this scale, with external implementation squads, is the exact challenge I want to own next."
22
"What questions do you have for us?" (Always asked — always matters)
▾
Ask 2-3 of these — shows you've thought deeply about the role
"How are the micro-frontend boundaries currently defined — are there existing Module Federation configurations or is this greenfield?"
"What does the relationship look like between the platform team that owns the design system and the external implementation squads?"
"What's the current state of front-end observability — are you using error monitoring and performance tracking in the Studio interface today?"
"What would a strong first 30 days look like for this role?"
Never ask
Salary in the first screen. "What does the company do?" (you should know). "How many vacation days?" — save those for after the offer.