Skip to content

Instantly share code, notes, and snippets.

@HofmannZ
Last active March 27, 2025 14:02
Show Gist options
  • Save HofmannZ/7792547ee6681bc034fc8da58bd40449 to your computer and use it in GitHub Desktop.
Save HofmannZ/7792547ee6681bc034fc8da58bd40449 to your computer and use it in GitHub Desktop.
Senior Front-End Engineer Technical Interview

Senior Front-End Engineer Technical Interview

Introduction

During this 45-minute video call, you’ll complete three front-end exercises (~15 minutes each). Our stack includes Next.js (App Router), TypeScript, SCSS, and follows an Atomic Design pattern with atoms, molecules, and organisms folder structures.

You're encouraged to:

  • Think aloud and walk us through your decisions.
  • Keep consistency with code style and component organization.
  • Discuss trade-offs, accessibility, and component design patterns.

Exercise 1: Reusable Button Component

Problem Statement

Build a reusable <Button /> component that supports the following:

  • Variants: primary, secondary, text
  • States: default, disabled, loading, success
  • Styling: SCSS module with minimal visual feedback

The button will be rendered inside a pre-built form (provided). Your job is only to implement the Button component, keeping the style, state, and accessibility consistent with modern patterns.

Provided Structure

You’ll receive a components/molecules/form/component.tsx file that looks like this:

'use client';

import { useState, type FunctionComponent } from 'react';
import { Button } from '@/components/atoms/button/component';

export const Form: FunctionComponent = () => {
  const [state, setState] = useState<'default' | 'loading' | 'success'>('default');

  const handleSubmit = async () => {
    setState('loading');
    await new Promise((r) => setTimeout(r, 1500));
    setState('success');
    setTimeout(() => setState('default'), 2000);
  };

  return (
    <form onSubmit={(e) => { e.preventDefault(); handleSubmit(); }}>
      <Button
        variant="primary"
        state={state}
        onClick={handleSubmit}
        disabled={state === 'loading'}
      >
        Submit
      </Button>
    </form>
  );
}

Requirements

  • Implement components/atoms/button/component.tsx and component.module.scss
  • Follow atomic design principles and clean component structure
  • Use TypeScript to type all props

Exercise 2: Server/Client Component Composition

Problem Statement

Using the Next.js App Router, build the following component structure that demonstrates proper server/client boundaries:

UserInfo (Server Component)
  └── UserFormWrapper (Client Component)
        └── UserName (Server Component)

Component Responsibilities

  • UserInfo – Server Component

    • Fetches user data using a simulated server-side call (e.g. getUser()).
    • Renders a styled container (e.g. a card or div) with background color.
    • Calls and renders the <UserFormWrapper/> component.
  • UserFormWrapper – Client Component

    • Renders an input field and the submit button from Exercise 1.
    • Simulates a form, use the example code from Exercise 1 (, and no need to update the actual server name).
    • Wraps the <UserName /> server component.
  • UserName – Server Component

    • Receives the user name as a prop.
    • Renders a simple <h2> element with “Welcome back, Alice” or similar.

Requirements

  • Proper use of use client directive.
  • Understand the “client wrapping server” pattern and how Next.js composes them.
  • Use static/mock data (e.g. getUser() returns { name: 'Alice' }).
  • Organize files:
    • components/organisms/user-info/component.tsx
    • components/molecules/user-form-wrapper/component.tsx
    • components/atoms/user-name/component.tsx

Evaluation Criteria

  • Correctly configured boundaries between server and client components
  • Proper props handling between components
  • Ability to explain when server vs client should be used
  • Understanding of what breaks composition and what doesn’t

Exercise 3: Bug Fixing – useEffect Dependency

Problem Statement

The following component renders fine, but logs stale data under certain conditions. Your task is to find the bug, explain it, and fix it.

// components/organisms/Tracker.tsx
'use client';

import { useEffect, useState } from 'react';

type TrackerProps = {
  id: string;
};

export function Tracker({ id }: TrackerProps) {
  const [internalId, setInternalId] = useState(id);

  useEffect(() => {
    console.log('[Tracker] Currently tracking:', internalId);
  });

  return <div>Tracking ID: {internalId}</div>;
}

Task

  • Identify and fix the bug
  • Explain why this bug can go unnoticed
  • Discuss when useEffect runs, and how React handles closures and stale values

Conclusion

Throughout the exercises, we’re looking for:

  • Clear structure and reusability in component design
  • Awareness of accessibility and visual states
  • Understanding of React’s reactivity model and lifecycle
  • Solid grasp of server/client boundaries in the Next.js App Router
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment