Front End Engineer
Front End Engineer Roadmap and Interview Guide
This page is a complete roadmap for becoming a front end engineer and passing the interviews. It starts with how the web works and moves through HTML, accessibility, CSS, JavaScript, tooling, TypeScript, React, testing, rendering strategies, performance, security and the AI tools now used in daily work. Each topic is explained here so you can learn from this page alone; where a subject has its own detailed skill roadmap, we summarise it and link to it.
It suits complete beginners, designers moving into code, back end developers who want to own the UI, and junior front end developers aiming for mid or senior roles. The second half of the page is an interview guide: the rounds you will face, real questions with strong answers, portfolio projects that hiring managers take seriously, and a ten-week preparation plan.
- Level
- Beginner to job-ready
- Time
- 6–12 months from zero at about 10–15 hours a week; 8–10 weeks of focused interview preparation if you already build web apps
- Scope
- 63 topics in 10 stages
- Before you start
- Comfort using a computer, a text editor and a web browser; No programming experience needed; the roadmap starts with how the web works and plain HTML; A laptop that can run Node.js, a modern browser and Git
What you will be able to do
- Explain how a page travels from server to screen, including DNS, HTTP, caching and the browser rendering pipeline
- Build accessible, responsive interfaces with semantic HTML, modern CSS and keyboard support
- Write clear JavaScript and strict TypeScript, and explain closures, the event loop and async code
- Build and test a React and Next.js app with sensible state management, routing and data fetching
- Measure and improve Core Web Vitals and defend against XSS, CSRF and insecure token storage
- Ship through Git, CI and preview deployments, and use AI coding assistants responsibly
- Pass coding, UI build, front end system design and behavioural interview rounds
What a Front End Engineer does
A front end engineer builds the part of a product people see and touch: pages, forms, dashboards, editors and every button in between. They turn designs into working, accessible interfaces, connect those interfaces to APIs, and make sure the result is fast on a cheap phone on a weak connection as well as on a developer's laptop. The job sits between design, product and back end engineering, so communication matters as much as code.
Day to day, the work is mostly JavaScript or TypeScript in a component framework such as React, with HTML and CSS underneath. Senior front end engineers also own architecture: how state is organised, how pages are rendered, how the design system evolves, how performance is protected and how the team tests and releases safely. Titles vary: front end developer, UI engineer, web engineer and software engineer (front end) usually describe the same job.
A typical week
- Turn designs into responsive, accessible components and review details with designers
- Build features in React or another framework, connecting UI to REST or GraphQL APIs
- Write unit, component and end-to-end tests, and fix failing checks in CI
- Review pull requests for correctness, accessibility, performance and readability
- Investigate bugs reported by users using DevTools, logs and error monitoring
- Measure page performance and fix regressions in loading speed or responsiveness
- Agree API contracts with back end engineers and plan work with product managers
- Use AI coding assistants for refactors, tests and documentation, then review their output carefully
What is expected at each level
Junior
- Builds well-defined components and pages from designs with guidance
- Writes semantic HTML, responsive CSS and readable JavaScript or TypeScript
- Adds tests for their own changes and fixes bugs with help from DevTools
- Asks for help early and responds well to code review
Mid
- Owns features end to end, from clarifying requirements to release and monitoring
- Makes sound choices on state management, data fetching and component structure
- Spots accessibility, performance and security problems in their own and others' code
- Reviews pull requests helpfully and mentors juniors on day-to-day work
Senior
- Designs front end architecture for a product area: rendering strategy, state, routing and testing approach
- Leads performance and accessibility work with measurable goals
- Influences API design and the design system, and negotiates trade-offs with product and design
- Raises the quality of the team through reviews, documentation and mentoring
Staff or Principal
- Sets front end direction across several teams, including framework, build and platform choices
- Leads large migrations such as a framework upgrade or TypeScript adoption with low risk
- Builds shared tooling and standards that make every team faster and safer
The interview loop
- Recruiter screen20–30 min
What it tests. Background, the stack you use, why this company, salary expectations, location and level.
How to prepare. Prepare a two-minute summary of your experience and one project you are proud of. Read the job post and know which framework and tools the team uses.
- Technical phone screen45–60 min
What it tests. JavaScript fundamentals and a small coding task in a shared editor: closures, async code, array manipulation or a utility such as debounce. Sometimes quick questions on CSS and the browser.
How to prepare. Implement common utilities from memory and talk while you code. Revise the event loop,
this, promises and array methods. Practise in coding practice. - Coding round (algorithms)45–60 min
What it tests. Easy to medium data structures and algorithms problems, usually in JavaScript or TypeScript, with attention to complexity, edge cases and clear code.
How to prepare. Cover arrays, strings, hash maps, stacks, queues, trees and recursion. Solve two problems a day for several weeks, and state Big O for each solution.
- UI build round60–90 min
What it tests. Building a working component or small app, such as a tabs widget, autocomplete, star rating, modal, data table or todo list, in plain JavaScript or React. Interviewers watch structure, state, accessibility and how you handle edge cases.
How to prepare. Build ten common widgets from scratch under time pressure, with keyboard support and ARIA where needed. Practise without a component library and without AI help.
- Front end system design45–60 min
What it tests. Designing a larger client application: requirements, component tree, data model, API, state management, performance, accessibility and trade-offs. Usually for mid level and above.
How to prepare. Use a fixed structure and practise five classic prompts: news feed, autocomplete, chat, image gallery and a form builder. Rehearse in system design practice with a timer.
- Behavioural and hiring manager45 min
What it tests. Collaboration with designers and back end engineers, ownership, handling disagreement, mistakes and feedback, and the impact of your past work.
How to prepare. Write six to eight stories in situation, task, action, result form covering a conflict, a failure, a hard bug, a performance win, mentoring and a decision you made with incomplete information.
Skill roadmaps for this role
Each skill below has its own complete roadmap. Learn the core ones first.
- CoreHTML Roadmap
Semantic, accessible HTML is the base of every interface and a frequent source of interview critique questions.
- CoreCSS Roadmap
Layout, responsive design and the cascade come up in UI rounds and in every day of the job.
- CoreJavaScript Roadmap
JavaScript fundamentals such as closures, async code and the DOM are tested in almost every front end interview.
- CoreGit and GitHub Roadmap
All team work flows through Git branches, pull requests and CI checks.
- CoreTypeScript Roadmap
Most front end codebases now use TypeScript, and job posts expect it.
- CoreReact Roadmap
React is the most requested UI framework, and its hooks and rendering model are standard interview topics.
- HelpfulNext.js Roadmap
Next.js is the common way to add server rendering, routing and data loading to React apps.
- HelpfulDesign System Roadmap
Front end engineers build and maintain the shared components and tokens that keep a product consistent.
- HelpfulData Structures and Algorithms Roadmap
Many companies include a general algorithms round, even for front end roles.
The Front End Engineer roadmap
- Stage 1How the web worksBeginner · 1–2 weeks · 5 topics
- Stage 2HTML and accessibilityBeginner · 2 weeks · 5 topics
- Stage 3CSS and layoutBeginner · 3 weeks · 6 topics
- Stage 4JavaScript in depthBeginner · 4 weeks · 7 topics
- Stage 5Version control and toolingBeginner · 2 weeks · 7 topics
- Stage 6Frameworks and ReactIntermediate · 5–6 weeks · 7 topics
- Stage 7Testing your appsIntermediate · 2 weeks · 5 topics
- Stage 8Rendering strategies, meta-frameworks and deploymentIntermediate · 3 weeks · 5 topics
- Stage 9Performance, security and offlineAdvanced · 3–4 weeks · 8 topics
- Stage 10Beyond the browser, AI tools and interview readinessAdvanced · 3–4 weeks · 8 topics
Stage 1 How the web works
Goal. Explain what happens between typing an address and seeing a page, and name the protocols and services involved.
How Does The Internet Work Core
The Internet is a global network of networks. Your laptop joins a local network, your provider routes traffic onwards, and packets travel through many routers until they reach the server that hosts a site. Data is split into small packets, each carrying a source and destination IP address. TCP sits on top of IP and turns those unreliable packets into an ordered, reliable stream by numbering them, acknowledging receipt and resending anything lost. Newer HTTP versions can run over QUIC, which uses UDP and handles reliability itself to cut connection set-up time.
Practice. Use your browser's network panel on a news site and count how many separate requests and domains the page needs before it is usable.
What is HTTP? Core
HTTP is the request and response protocol of the web. A client sends a method (GET, POST, PUT, PATCH, DELETE), a path, headers and sometimes a body; the server replies with a status code, headers and a body. Learn the status classes: 2xx success, 3xx redirects, 4xx client errors such as 401, 403 and 404, and 5xx server errors. Headers carry most of the interesting behaviour: content type, caching, cookies, compression and security policies.
HTTP/1.1 sends one request at a time per connection. HTTP/2 multiplexes many requests over one connection and compresses headers. HTTP/3 does the same over QUIC.
Practice. Open DevTools, reload a page, and for five requests write down the method, status code, content type and cache headers.
HTTPS Core
HTTPS is HTTP inside a TLS connection. TLS encrypts traffic so others on the network cannot read or change it, and the server's certificate proves that you are talking to the real owner of the domain. During the handshake the browser checks that the certificate is valid, unexpired and signed by a trusted certificate authority. Free, automated certificates are now standard, so every production site should use HTTPS.
Many browser features only work in a secure context: service workers, geolocation, the clipboard API and others. Mixed content, where an HTTPS page loads a script over plain HTTP, is blocked. The Strict-Transport-Security header tells the browser to always use HTTPS for your domain.
Practice. Inspect the certificate of three sites in your browser and note the issuer, validity dates and which names it covers.
DNS and Domain Name basics Core
A Domain Name such as example.com is a human-friendly label. DNS translates it into an IP address. The browser asks a resolver, which walks from the root servers to the top-level domain servers to the domain's authoritative servers, then caches the answer for the time-to-live set on the record. Common record types are A (IPv4 address), AAAA (IPv6), CNAME (an alias to another name), MX (mail) and TXT (verification and policies).
A dns-prefetch or preconnect hint can start lookups early for third-party origins.
Practice. Use a command-line tool such as dig or nslookup to find the A and CNAME records for a site you use daily.
Browsers and the rendering pipeline Core
Browsers parse HTML into the DOM and CSS into the CSSOM, combine them into a render tree, calculate layout (the size and position of every box), paint pixels into layers and composite those layers on the screen. JavaScript runs on the main thread, the same thread that does most of this work, so a long script blocks rendering and input.
Knowing the pipeline explains common advice. Scripts in the head without defer pause parsing. Changing width triggers layout again; changing transform or opacity can often skip straight to compositing. Reading a layout value such as offsetHeight right after writing a style forces a synchronous layout.
Practice. Record a performance profile while scrolling a heavy page and identify the layout, paint and scripting blocks in the timeline.
Stage 2 HTML and accessibility
Goal. Write semantic, accessible HTML pages with working forms, correct metadata and responsive media.
Semantic HTML Core
HTML describes the meaning of content, not its look. Use header, nav, main, article, section, aside and footer for page regions, a single logical heading outline from h1 downwards, lists for lists and table only for tabular data. Use a button for actions and an a element for navigation, never a clickable div.
Semantic markup gives you keyboard support, screen reader announcements and better search results for free. It also makes CSS and tests simpler, because elements have clear roles. Interviewers often ask you to critique a snippet full of div soup; point out the missing roles, headings and labels. The HTML Roadmap covers elements and attributes in depth.
Practice. Take a page built only from div and span elements and rewrite it with semantic elements, then check it with a screen reader.
Forms and validation Core
Forms are where users give you data, and where many accessibility bugs live. Every input needs a visible label connected with for and id. Choose the right type (email, tel, number, date) so mobile keyboards adapt, and set autocomplete values so browsers can fill addresses and passwords. Group related controls with fieldset and legend.
Built-in validation attributes such as required, minlength and pattern give quick feedback, but always validate again on the server. Show errors next to the field, in text rather than colour alone, and link them with aria-describedby. Submitting a form with Enter should work without extra JavaScript.
Practice. Build a sign-up form with five fields, inline error messages and full keyboard support, without any framework.
Accessibility Core
Accessibility means people using screen readers, keyboards, voice control, magnification or high contrast can use your product. The WCAG guidelines group requirements under four principles: perceivable, operable, understandable and compatible with assistive technology. Practical rules: every interactive element is reachable and usable by keyboard, focus is always visible, images have useful alt text (or empty alt if decorative), text contrast is sufficient, and motion respects prefers-reduced-motion.
ARIA adds roles and states when native HTML cannot express a widget, such as a tab list or combobox. The first rule of ARIA is to prefer a native element. Wrong ARIA is worse than none. Test with a real screen reader (VoiceOver, NVDA) and automated checkers such as axe, which catch only part of the problems.
Practice. Navigate an app you built using only the keyboard and a screen reader, and fix three problems you find.
Images, media and responsive markup Recommended
Images are often the heaviest part of a page. Serve modern formats such as WebP or AVIF, and let the browser pick a size with srcset and sizes. Use picture when you need different crops for different screens. Always set width and height (or an aspect ratio) so the layout does not jump while images load. Add loading="lazy" to images below the fold, but never to the main hero image.
Practice. Convert a page's images to responsive srcset markup and compare the bytes downloaded on a narrow and a wide window.
Metadata, SEO basics and HTML Templates Recommended
The document head holds information the page does not show: title, the meta description, the viewport tag that makes mobile layouts work, the language attribute on html, canonical links and social preview tags. Search engines reward pages that load fast, use real headings and links, and render meaningful HTML without waiting on scripts. Structured data in JSON-LD can describe products, articles and events.
The template element holds inert markup that scripts can clone and insert later; it is the basis of HTML Templates used by Web Components. Learn it now, because it shows how the browser treats markup that is parsed but not rendered.
Practice. Add a complete head section with title, description, viewport, canonical and social tags to a project, then test the social preview.
Stage 3 CSS and layout
Goal. Build responsive, maintainable layouts with modern CSS and explain the cascade, specificity and stacking.
The cascade, specificity and the box model Core
CSS decides which rule wins through the cascade: origin and importance first, then cascade layers, then specificity, then source order. Specificity counts IDs, then classes, attributes and pseudo-classes, then elements. Inheritance passes some properties, such as color and font, from parent to child.
Every element is a box with content, padding, border and margin. With the default content-box, width excludes padding and border, which surprises people; most projects set box-sizing: border-box globally. Learn margin collapsing, the difference between block, inline and inline-block, and how position (static, relative, absolute, fixed, sticky) and z-index create stacking contexts. The CSS Roadmap goes deeper into each of these.
Practice. Write five selectors that target the same element and predict which wins before checking in DevTools.
Flexbox and Grid Core
Flexbox lays items out in one direction. It is ideal for toolbars, navigation, centring and distributing space with justify-content, align-items, gap and the flex shorthand (grow, shrink, basis). Grid lays content out in two dimensions with rows and columns. Use it for page layouts, card galleries and anything that needs alignment across rows.
.cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
gap: 1rem;
}The snippet above builds a responsive gallery with no media queries. Interviewers often ask you to centre an element or build a holy-grail layout live; know both Flexbox and Grid answers and the trade-offs.
Practice. Rebuild the layout of a popular site's home page using Grid for the page and Flexbox for components.
Responsive design Core
Responsive design makes one codebase work from small phones to wide monitors. Start mobile first: write base styles for narrow screens, then add min-width media queries as space grows. Use relative units: rem for type and spacing, percentages and fr for layout, viewport units with care, and clamp() for fluid type that scales between a minimum and maximum.
Test with real devices as well as the DevTools device mode, because touch targets, on-screen keyboards and browser toolbars behave differently. Respect user settings: if someone increases their default font size, a layout built on rem adapts while one built on fixed pixels breaks.
Practice. Make a three-column marketing page that reads well at 320, 768 and 1440 pixels wide without horizontal scrolling.
Modern CSS Core
Modern CSS removes many reasons to reach for JavaScript or a preprocessor. Custom properties (CSS variables) hold design tokens and can change at runtime, which makes theming and dark mode simple. Container queries let a component respond to the size of its container rather than the viewport. The :has() selector styles a parent based on its children. Native nesting, cascade layers (@layer), logical properties such as margin-inline, and aspect-ratio are now widely supported.
Check support tables before relying on very new features, and use @supports for progressive enhancement. Knowing what the platform already does is a sign of seniority in interviews.
Practice. Build a card component that switches from stacked to side-by-side using a container query, with colours from custom properties.
Tailwind CSS Recommended
Tailwind CSS is a utility-first framework: you style elements with small classes such as flex, p-4 and text-sm directly in markup. A build step scans your files and generates only the classes you use. Its strengths are speed, a consistent spacing and colour scale, and no naming debates. Its weaknesses are long class lists and markup that mixes structure and style.
Many job posts list Tailwind, so learn it, but learn plain CSS first. You must understand what flex or grid-cols-3 does underneath to debug it.
Practice. Rebuild one of your plain-CSS components in Tailwind CSS and compare the readability and file sizes.
CSS architecture at scale Recommended
Large apps need rules that keep styles from leaking. Options include naming conventions such as BEM, CSS Modules (class names scoped per file at build time), CSS-in-JS libraries that generate styles from components, utility classes, and Shadow DOM encapsulation. Each trades off runtime cost, tooling and how easy it is to share tokens.
Whatever you pick, keep specificity low and flat, avoid !important except for utilities, put tokens in custom properties, and delete dead styles. Runtime CSS-in-JS can slow rendering and does not suit server components well, so many teams now prefer zero-runtime options.
Practice. Refactor a stylesheet with deep selectors into CSS Modules or BEM and measure how specificity changes.
Stage 4 JavaScript in depth
Goal. Write correct, readable JavaScript, explain closures, this and the event loop, and work directly with the DOM and browser APIs.
Language fundamentals Core
Start with values and types: the primitives (string, number, bigint, boolean, undefined, null, symbol) and objects, including arrays and functions. Learn let and const instead of var, strict equality ===, truthy and falsy values, template literals, destructuring, spread and rest, optional chaining and nullish coalescing.
Master the array methods map, filter, reduce, find, some, every and flatMap, and know which ones mutate (sort, splice, push) and which return copies (toSorted, slice). Immutability matters a lot in React. The JavaScript Roadmap covers the full language step by step.
Practice. Solve ten small data-transformation tasks on an array of order objects using only array methods, without loops.
Scope, closures and this Core
Scope decides where a variable is visible. let and const are block scoped; var is function scoped and hoisted. A closure is a function that remembers the variables of the scope where it was created, even after that scope has returned. Closures power callbacks, event handlers, module privacy, memoisation, and React hooks.
The value of this depends on how a function is called: as a method, with new, through call, apply or bind, or as a plain call. An arrow function takes this from the scope around it instead of setting its own. Interviews often show a loop that creates callbacks and ask what they print; the answer depends on whether the loop variable is block scoped.
Practice. Write a counter factory using a closure, then a memoise function that caches results by argument.
Prototypes, classes and modules Recommended
Every object has a prototype that it inherits properties from. The class syntax is a clearer way to set up prototypes, constructors and inheritance; it does not change how JavaScript works underneath. Know private fields (#name), static members and why composition is usually preferred over deep inheritance in UI code.
ES modules use import and export. They are static, which lets bundlers remove unused code (tree shaking). Dynamic import() loads a module on demand and returns a promise, which is the basis of code splitting.
Practice. Split a single-file app into ES modules and load a rarely used feature with dynamic import.
Asynchronous JavaScript and the event loop Core
JavaScript runs one task at a time on a single thread. Slow work such as network requests happens in the browser, and callbacks queue up to run when the thread is free. The event loop takes one task (a macrotask such as a timer or click handler), runs it to completion, then drains the whole microtask queue (promise callbacks, queueMicrotask), then lets the browser render if needed.
Promises represent future values; async and await make them read like normal code. Know Promise.all, allSettled, race and any, how to handle rejections with try and catch, and how to cancel requests with AbortController. Predicting the output order of mixed timers and promises is a very common interview question.
Practice. Write a function that fetches three endpoints in parallel, times out after two seconds and reports which ones failed.
DOM and events Core
The DOM is the live tree of nodes the browser builds from HTML. Select elements with querySelector, create them with createElement, and update them through properties such as textContent and classList. Avoid setting innerHTML with user data, because that invites XSS.
Events travel in three phases: capture down the tree, target, then bubble back up. Event delegation attaches one listener to a parent and checks event.target, which is efficient for long lists. Know preventDefault, stopPropagation, passive listeners for scroll and touch, and how to remove listeners to avoid leaks. Building a small widget in plain DOM code is a common practical round.
Practice. Build a to-do list in plain JavaScript with event delegation, keyboard support and no framework.
Web APIs Core
Browsers expose many Web APIs beyond the DOM. The most useful for front end work are fetch for HTTP, localStorage and sessionStorage for small key-value data, IndexedDB for larger structured data, URL and URLSearchParams for parsing addresses, the History API for client-side routing, IntersectionObserver for lazy loading and infinite scroll, ResizeObserver, requestAnimationFrame for smooth visual updates, and Web Workers for moving heavy computation off the main thread.
Also know the Clipboard, Notifications, Geolocation and Broadcast Channel APIs exist, and that many need a secure context or user permission. Reaching for a platform API before a library keeps bundles small.
Practice. Implement infinite scroll with IntersectionObserver and persist the last scroll position with sessionStorage.
Error handling and debugging Recommended
Production code fails in ways you did not expect. Throw Error objects, not strings, so you keep a stack trace. Handle errors where you can do something useful, such as showing a retry button, and let others bubble up. Listen for unhandledrejection and error events globally and report them to a monitoring service with enough context (route, user action, release version).
For debugging, prefer breakpoints and conditional breakpoints to scattered console logs. Learn to read minified stack traces with source maps.
Practice. Add global error reporting to a small app, trigger three kinds of failure and confirm each is captured with a useful stack.
Stage 5 Version control and tooling
Goal. Use Git and GitHub confidently and set up a modern build with a package manager, bundler, linter, formatter and type checker.
Version Control Systems and Git Core
Version Control Systems record every change to your code so you can review, undo and share work. Git is the standard. Learn the daily loop: status, add, commit, push, pull. Then branches, merging, rebasing, resolving conflicts, stash, restore and revert, and how to find a bad commit with bisect.
Write small commits with clear messages that explain why, not just what. Never rewrite history on a shared branch without warning. Most teams use short-lived feature branches merged through pull requests. The Git and GitHub Roadmap covers Git and GitHub in depth.
Practice. Create a repository, make conflicting changes on two branches and resolve the conflict by hand, then by rebasing.
GitHub and Repo Hosting Services Core
Repo Hosting Services store your Git repositories online and add collaboration: pull requests, code review, issues, project boards, and CI. GitHub is the most common; GitLab and Bitbucket are widely used in companies, and GitLab is often self-hosted. The ideas carry over between them.
Learn to open a clear pull request with a description, screenshots for UI changes and testing notes; to review others' code kindly and specifically; and to set up branch protection and required checks. GitHub Actions runs your lint, type check and tests on every push. GitHub Pages can host a static portfolio for free.
Practice. Add a CI workflow that runs lint and tests on every pull request to one of your projects, and protect the main branch.
Package Managers: npm, pnpm, Yarn and Bun Core
Package Managers install third-party code and record exact versions in a lock file. npm ships with Node.js. pnpm stores packages once on disk and links them, which is fast and strict about undeclared dependencies. Yarn introduced workspaces and offline caching. Bun is a fast all-in-one runtime with its own package manager and test runner.
Understand package.json fields, the difference between dependencies and devDependencies, semantic versioning ranges (^ and ~), why the lock file must be committed, and how scripts work. Check new packages before installing: maintenance, size, licence and security advisories. Supply-chain attacks through compromised packages are real.
Practice. Set up a project with pnpm workspaces containing an app and a shared UI package, and run a script across both.
Module Bundlers and build tools Core
Module Bundlers turn many source files into a few optimised files the browser can load. They resolve imports, transform TypeScript and JSX, remove unused code, split bundles, and add content hashes to file names for caching. Vite is the common default for new projects: a fast dev server using native ES modules, with Rollup for production builds. Rolldown is a Rust-based bundler built to replace Rollup inside Vite. esbuild and SWC (Speedy Web Compiler) are very fast compilers written in Go and Rust. Parcel offers zero configuration. webpack still runs many older apps.
You rarely write bundler config from scratch, but you must read it, understand source maps, environment variables and aliases, and analyse a bundle to find what makes it large.
Practice. Create a Vite project, build it, and use a bundle analyser to find and remove the largest dependency.
Linters formatters Core
Linters, formatters and type checkers catch problems before review. ESLint finds bugs and risky patterns, such as missing hook dependencies or unused variables, through configurable rules. Prettier formats code automatically so teams stop arguing about style. Biome is a fast Rust tool that combines linting and formatting in one binary and is growing in use.
Run them in the editor, in a pre-commit hook, and in CI so the main branch stays clean. Keep the rule set small and agreed; a wall of warnings that everyone ignores helps nobody. Add accessibility and React hooks lint plugins early.
Practice. Add ESLint and Prettier (or Biome) to a project, wire them to a pre-commit hook and fix every reported issue.
DevTools Usage Core
Browser DevTools are the front end engineer's main debugging tool. The Elements panel shows the live DOM and computed styles, and lets you toggle states such as hover and focus. The Console runs code in the page. The Sources panel sets breakpoints, including on DOM changes and XHR. The Network panel shows every request with timing, headers and the ability to throttle. Performance records a timeline of scripting, layout and paint. Memory takes heap snapshots to find leaks. Application shows storage, cookies, service workers and the manifest.
Practice. Find a memory leak in a demo app by comparing two heap snapshots before and after repeating an action.
TypeScript and Type Checkers Core
TypeScript adds static types to JavaScript and is now expected in most front end roles. Learn primitive and object types, unions, literal types, type narrowing, interfaces versus type aliases, generics, utility types such as Partial, Pick and Record, and how to type React props, events and hooks. Turn on strict mode.
Type Checkers run separately from the build: tools such as esbuild and SWC strip types without checking them, so run tsc --noEmit in CI. Avoid any; prefer unknown plus narrowing for data from the network, and validate it at runtime with a schema library. The TypeScript Roadmap covers advanced types and patterns.
Practice. Convert a small JavaScript app to strict TypeScript and add a runtime schema check for one API response.
Stage 6 Frameworks and React
Goal. Build a multi-page React app with typed components, sensible state, routing, data fetching and a shared component library.
Pick a Framework Core
Learn one component framework well rather than four badly. React has the largest job market and ecosystem. Vue.js offers an approachable template syntax and single-file components. Angular is a complete, opinionated platform with dependency injection and RxJS, common in large enterprises. Svelte compiles components to small, direct DOM updates. SolidJS uses fine-grained signals with JSX syntax and very fast updates.
The core ideas transfer: components, props, state, reactivity, lifecycle, routing and data fetching. Check job posts in your area and pick the most requested; for most people that is React.
Practice. Build the same small counter-and-list app in React and one other framework, and write down three differences.
React Core
React builds interfaces from components: functions that take props and return JSX. When state changes, React calls the component again and patches only the DOM nodes that differ. Learn the key hooks: useState and useReducer for state, useEffect for syncing with outside systems, useRef for mutable values and DOM nodes, useMemo and useCallback for caching, and useContext for passing values down.
Understand rendering: a parent render re-renders children by default, keys must be stable for list items, state updates are batched, and effects run after paint. Most effects that copy props into state are bugs; derive values during render instead. The React Roadmap covers hooks, patterns and performance in depth.
Practice. Build a searchable, sortable product table with derived state only and no effects that copy props into state.
State management Core
Sort state by type before picking a tool. Local UI state (an open menu) belongs in the component. Shared client state (a shopping cart) can live in context, a reducer or a small store such as Zustand or Redux Toolkit. Server state (data fetched from an API) is a cache with loading, error, refetching and invalidation needs; use a library such as TanStack Query or SWR instead of hand-written effects. URL state (filters, page number) belongs in the query string so links can be shared.
Most messy React apps put server data into a global store and then fight to keep it fresh. Explaining this split clearly is a strong signal in interviews.
Practice. Refactor an app that stores fetched data in a global store to use a server-state library, and delete the manual loading flags.
Routing with react-router Core
Client-side routing changes the view without a full page reload by updating the URL through the History API. react-router is the standard library for React single-page apps: nested routes, layouts, URL parameters, search params, and data loaders and actions that fetch before rendering. Meta-frameworks such as Next.js use file-based routing instead.
Good routing work includes restoring scroll position, moving focus to the new page heading for screen reader users, handling 404s, guarding private routes, and lazy loading route code so the first page stays small.
Practice. Add nested routes with a shared layout, a lazy-loaded settings page and a not-found page to a React app.
Data fetching, GraphQL, Apollo and Relay Modern Recommended
Most front ends talk to REST APIs with fetch. Handle loading, empty, error and success states for every request, cancel stale requests, and avoid waterfalls where one request waits for another unnecessarily.
GraphQL lets the client ask for exactly the fields it needs from a single endpoint, described by a typed schema. Apollo Client is a popular GraphQL client with a normalised cache and React hooks. Relay Modern, from the team that created GraphQL, is stricter: each component declares its data needs in a fragment and a compiler combines them, which scales well in very large apps. Learn the trade-offs: GraphQL removes over-fetching but adds caching and tooling complexity.
Practice. Build the same list-and-detail screen against a REST API and a public GraphQL API, and compare the requests made.
Forms in React Recommended
Forms are where React apps get complicated. Controlled inputs keep the value in state and re-render on each keystroke; uncontrolled inputs let the DOM hold the value and read it on submit, which is simpler and faster for large forms. Libraries such as React Hook Form manage registration, validation and errors with few re-renders, and pair well with schema validators like Zod. In newer React versions, form actions and useActionState handle pending and error states for server mutations.
Practice. Build a multi-step checkout form with schema validation, accessible errors and protection against double submit.
Design Systems and component libraries Recommended
Design Systems are shared sets of tokens, components, patterns and guidelines that keep a product consistent. Tokens store decisions such as colours, spacing, type scale and radii. Components such as Button, Input, Modal and Tabs implement those tokens with accessibility built in. Documentation shows when to use each one.
Front end engineers often build and maintain these libraries. Key skills: designing a clear component API (variants rather than dozens of boolean props), composition through children and slots, theming with custom properties, visual testing in a tool such as Storybook, and versioning changes so product teams can upgrade safely. Headless libraries provide behaviour and accessibility without styles. The Design System Roadmap covers this in depth.
Practice. Build a Button, Input and Modal with tokens, document them in Storybook and pass an automated accessibility check.
Stage 7 Testing your apps
Goal. Write fast unit and component tests, a few reliable end-to-end tests, and know what to test at each level.
Testing your apps: strategy Core
Tests let you change code without fear. Use many fast unit tests for logic, a solid layer of component or integration tests that render UI and interact with it the way a user would, and a small number of end-to-end tests for the critical journeys such as sign-up and checkout. Add static checks (types and lint) as the cheapest layer.
Test behaviour, not implementation: assert what the user sees and can do, not internal state or which hook ran. Tests that break on every refactor are a cost, not a safety net.
Practice. Write a short test plan for one feature listing which cases belong at unit, component and end-to-end level.
Unit tests with Vitest and Jest Core
Vitest and Jest are the main JavaScript test runners. Both offer describe, it, expect, mocking, snapshot tests and coverage. Vitest shares configuration with Vite and is fast with native ES modules and TypeScript; Jest has the longest history and runs many existing projects. The APIs are close, so skills transfer.
Write tests for pure functions such as formatters, reducers and validation rules. Mock only true boundaries like network and time; use fake timers for debounce and retry logic. Keep each test independent and readable as documentation.
Practice. Write Vitest tests for a debounce function using fake timers, including the edge case of rapid repeated calls.
Component tests with Testing Library Core
Testing Library renders a component into a test DOM (usually jsdom or happy-dom) and encourages queries that match how users find things: by role, label and text. Using getByRole('button', { name: 'Save' }) also checks accessibility, because the query fails if the button has no accessible name.
Simulate interaction with the user-event library, wait for async updates with findBy queries, and mock network calls at the request level with a tool such as Mock Service Worker so your components use their real fetching code. Vitest browser mode and Playwright component testing can run the same kind of tests in a real browser.
Practice. Test a login form: empty submit shows errors, a server error shows a message, and success redirects.
End-to-end tests with Playwright and Cypress Core
End-to-end tests drive a real browser through your running app. Playwright supports Chromium, Firefox and WebKit, runs tests in parallel, waits automatically for elements, and records traces you can replay to debug failures. Cypress runs inside the browser with an interactive runner that many developers find pleasant for writing tests.
Keep the E2E suite small and stable: test the critical paths, seed test data through APIs rather than the UI, use role-based selectors or dedicated test ids, and never use fixed sleeps. Run the suite in CI against a preview deployment for each pull request.
Practice. Write Playwright tests for sign-up and checkout, run them in CI and inspect a trace of a deliberate failure.
Visual and accessibility testing Optional
Some bugs are only visible. Visual regression tests take screenshots of components or pages and compare them with approved baselines, catching unintended style changes. Storybook-based services and Playwright's screenshot assertions are common choices. Keep fonts, data and animations stable to avoid noisy diffs.
Automated accessibility checks with axe can run inside component and E2E tests to catch missing labels, contrast problems and invalid ARIA. They find a meaningful share of issues, but not keyboard traps or confusing focus order, so manual checks remain necessary.
Practice. Add axe checks to your component tests and fix every violation they report.
Stage 8 Rendering strategies, meta-frameworks and deployment
Goal. Choose between client, server and static rendering, build with a meta-framework and deploy with previews and a custom domain.
Rendering patterns: CSR, SSR, SSG and ISR Core
Client-side rendering sends a mostly empty HTML shell and builds the page in JavaScript. It is simple to host and good for app-like screens behind a login, but slower to show content and weaker for search. Server-side rendering builds HTML per request, so content appears quickly and is easy to index; the page then hydrates to become interactive. Static site generation builds HTML at deploy time, which is fastest and cheapest for content that rarely changes. Incremental regeneration rebuilds static pages in the background after a set time or on demand.
Most real apps mix these per route. Know the costs too: SSR needs servers and careful caching, and hydration can delay interactivity on slow devices.
Practice. Build one page three ways (CSR, SSR, SSG) and compare time to first content and HTML size.
Server-side rendering with Next.js, Nuxt.js, SvelteKit and Tanstack Start Core
Meta-frameworks add routing, server rendering, data loading and build optimisation on top of a component library. Next.js is the most common choice for React: its App Router uses React Server Components, nested layouts, server actions and per-route caching. Nuxt.js plays the same role for Vue, SvelteKit for Svelte, and Tanstack Start is a newer React framework built around type-safe routing and server functions. Remix ideas now live on in React Router's framework mode.
Learn where code runs (server, client or both), how to keep secrets on the server, how caching and revalidation work, and how to handle loading and error boundaries. The Next.js Roadmap goes through the App Router in depth.
Practice. Build a blog in Next.js with a server-rendered list, a static post page and a server action for comments.
React Server Components and Streamed Responses Recommended
React Server Components run only on the server. They can read databases or call APIs directly and send rendered output, not their code, to the browser, so large dependencies never reach the client bundle. Client Components, marked with 'use client', handle state and events. The boundary between them is a key design decision.
Streaming sends HTML in chunks as data becomes ready. With Suspense boundaries, the shell and fast parts appear immediately and slower sections fill in later, instead of the whole page waiting for the slowest query. Streamed Responses also matter for AI features, where tokens arrive over time. Understand how streaming interacts with status codes and caching.
Practice. Add a Suspense boundary around a slow data section and observe the streamed HTML arriving in the network panel.
Static Site Generators: Astro, Eleventy and Vuepress Optional
Static Site Generators turn content, often Markdown, into plain HTML at build time. Astro ships zero JavaScript by default and adds interactive islands only where needed, using components from React, Vue, Svelte or others. Eleventy is a simple, flexible generator built on templates with no client framework. Vuepress and its successor VitePress are aimed at documentation sites built with Vue.
Practice. Build a documentation site with Astro or Eleventy that scores well on Lighthouse with almost no JavaScript.
Deployment and Hosting platforms Core
Deployment should be boring and automatic. Vercel and Netlify build from Git, give every pull request a preview URL, and run serverless or edge functions. Cloudflare Pages and Workers serve static assets and code from a large edge network. GitHub Pages hosts static sites for free. Render and Railway run full servers, background workers and databases with simple configuration.
Know the basics regardless of platform: environment variables per environment, build caching, custom domains with DNS, HTTPS certificates, redirects and headers, rollbacks, and the difference between serverless functions (short-lived, per request) and a long-running Node.js server.
Practice. Deploy a Next.js app with preview deployments, a custom domain and an environment variable that differs per environment.
Stage 9 Performance, security and offline
Goal. Measure and fix loading and runtime performance, defend against common web attacks, and make an app work offline.
Performance and Core Web Vitals Core
Performance is measured, not guessed. Core Web Vitals are the main user-centred metrics: Largest Contentful Paint (how quickly the main content appears), Interaction to Next Paint (how quickly the page responds to input) and Cumulative Layout Shift (how much content jumps). Also watch Time to First Byte and total JavaScript size.
Distinguish lab data, from a controlled test, and field data, from real users on real devices. Set a performance budget, for example a maximum script size per route, and check it in CI so regressions are caught in review instead of production.
Practice. Record the three Core Web Vitals for one of your apps in the lab and in the field, and explain any difference.
Lighthouse and measuring tools Core
Lighthouse audits a page for performance, accessibility, best practices and SEO, and lists concrete opportunities with estimated savings. Run it in an incognito window or in CI with a throttled mobile profile, and run it several times, because scores vary between runs.
The DevTools Performance panel shows exactly what the main thread did: long tasks, forced layouts and expensive renders. The React Profiler shows which components rendered and why. Treat the Lighthouse score as a guide to investigate, not a goal in itself.
Practice. Run Lighthouse on a slow page, pick the top two opportunities, fix them and record the before and after numbers.
Loading performance Core
Send less, send it sooner, and send it in the right order. Split code by route and load rarely used features on demand. Remove unused dependencies and prefer smaller ones. Compress text with Brotli or gzip. Optimise images with modern formats, correct sizes and lazy loading. Load fonts with font-display: swap, subset them and preload the critical one.
Use resource hints carefully: preload for a critical late-discovered file, preconnect for important third-party origins. Defer non-critical scripts and audit third-party tags, which are often the heaviest code on a page. Render important content on the server so it does not wait for JavaScript.
Practice. Cut the JavaScript of a sample app by at least a third using code splitting and dependency changes.
Runtime performance and rendering Recommended
A page that loads fast can still feel slow. Break long tasks over about 50 milliseconds into smaller pieces, move heavy work to a Web Worker, and avoid layout thrashing by batching DOM reads before writes. Virtualise long lists so only visible rows exist in the DOM.
In React, find unnecessary re-renders with the Profiler before optimising. Fixes include moving state down, splitting context, memoising expensive children with memo, and using useTransition or useDeferredValue to keep typing responsive while a large list updates. The React Compiler can add memoisation automatically, but you should still understand why renders happen.
Practice. Render a list of 10,000 rows, measure the input delay, then virtualise it and measure again.
Caching with Cache-Control and CDNs Core
Caching is the cheapest performance win. The Cache-Control header tells browsers and CDNs how long to keep a response. Hashed static assets such as app.3f9a1c.js can be cached for a year with immutable, because a new build produces a new name. HTML should usually use no-cache, which means revalidate before use, so users get new releases. ETags and Last-Modified allow cheap revalidation with 304 responses.
Know private versus public for personalised data, stale-while-revalidate for serving slightly old content while refreshing, and how a CDN key can vary by headers or cookies. Wrong caching causes some of the hardest bugs to debug.
Practice. Configure headers so hashed assets are cached for a year and HTML is always revalidated, then verify in the network panel.
Service Workers and Progressive Web Apps Recommended
A service worker is a script that sits between your page and the network. It can intercept requests and answer from a cache, which enables offline support, faster repeat visits and background sync. Common strategies are cache first for static assets, network first for HTML and API data, and stale-while-revalidate for content that can be slightly old.
Progressive Web Apps combine a service worker, a web app manifest and HTTPS so a site can be installed, launched full screen and work offline. Be careful with updates: an old service worker can keep serving stale files, so have a clear update and skip-waiting flow.
Practice. Make a notes app work offline with a service worker and a manifest, and test it with the network disabled.
Web Security Knowledge: XSS, CSRF, CORS and CSP Core
Front end engineers prevent many attacks. Cross-site scripting (XSS) happens when untrusted data runs as code; frameworks escape text by default, so the danger is raw HTML insertion, unsafe URLs such as javascript: links, and third-party scripts. Sanitise any HTML you must render. A Content Security Policy header limits which scripts may run, which reduces the impact of an XSS bug.
Cross-site request forgery tricks a logged-in browser into sending a request; SameSite cookies and tokens defend against it. CORS is a browser rule that blocks a page from reading responses from another origin unless the server allows it with headers; it is not a server-side protection. Learn the OWASP Security Risks list, especially injection, broken access control and vulnerable dependencies, and run dependency audits.
Practice. Add a strict Content Security Policy to an app, fix what it breaks, and write a short note on each directive.
Authentication Strategies Core
Most apps need sign-in. Session cookies store an ID that maps to server-side state; mark them HttpOnly, Secure and SameSite so scripts cannot read them. Token-based auth uses signed tokens such as JWTs; storing them in localStorage exposes them to any XSS, so many teams keep them in HttpOnly cookies instead. OAuth 2.0 with OpenID Connect lets users sign in with another provider, using the authorisation code flow with PKCE in browser apps. Passkeys use public-key credentials and resist phishing.
The front end handles redirects, token refresh, protected routes and logout across tabs, but real access checks always happen on the server.
Practice. Add sign-in with an OpenID Connect provider to an app, using HttpOnly cookies, and handle expiry and logout.
Stage 10 Beyond the browser, AI tools and interview readiness
Goal. Know the wider platform and AI tooling, and prepare for coding, UI and front end system design rounds.
Web Components: Custom Elements, Shadow DOM and templates Optional
Web Components are browser standards for reusable elements that work in any framework. Custom Elements let you define a new tag, such as <date-picker>, with a class that has lifecycle callbacks. Shadow DOM gives that element its own encapsulated DOM and styles, so page CSS does not leak in and component CSS does not leak out. HTML Templates and slots define the markup to clone and where light DOM content goes.
They suit design systems shared across teams that use different frameworks. Trade-offs include server rendering support, form participation, and styling across the shadow boundary, which uses custom properties and ::part. Libraries such as Lit reduce boilerplate.
Practice. Build a rating-stars custom element with Shadow DOM and use it in both a plain HTML page and a React app.
Mobile Apps: React Native, Flutter and Ionic Optional
Front end skills extend to mobile. React Native uses React components that render native platform views, so a React developer can be productive quickly; Expo makes setup and builds easier. Flutter, from Google, uses the Dart language and draws its own widgets, giving consistent visuals on every platform. Ionic wraps web code in a native shell with Capacitor, so it reuses HTML and CSS directly.
Know the trade-offs if a role mentions mobile: performance, access to device features, app store releases and how much code is really shared.
Practice. Port one screen of a React web app to React Native with Expo and list what changed.
Desktop Applications in JavaScript: Electron and Tauri Optional
Desktop Applications in JavaScript let web teams ship installable apps. Electron bundles Chromium and Node.js with your app; many well-known editors and chat apps use it. It is mature and consistent across platforms, but apps are large and memory-hungry. Tauri uses the operating system's own web view with a Rust back end, so apps are much smaller, at the cost of some rendering differences between platforms.
Practice. Wrap a small notes app in Tauri or Electron with one native menu item and file save.
AI-Assisted Coding tools Recommended
AI coding assistants are now part of normal front end work. GitHub Copilot suggests code inline in the editor. Cursor is an editor built around chat and multi-file edits. Claude Code, from Anthropic, works in the terminal and can read a repository, run commands and make changes across files. Antigravity is an agent-first editor from Google. Many assistants support reusable Skills or project instructions that teach them a team's conventions.
AI vs. Traditional Software Development: the work shifts from typing code to specifying, reviewing and testing it. Good uses include Refactoring with AI under good test coverage, Documentation Generation with AI, writing test cases, and AI-Powered Code Reviews that flag likely bugs before a human looks. You remain responsible for every line: check accessibility, security and performance, because generated UI code often misses them.
Practice. Use an AI assistant to refactor a component with tests in place, then review the diff line by line and record what you changed.
Implementing AI features in the front end Recommended
Many products now add AI features, and the front end owns the experience. Generative AI for Frontend Development includes chat interfaces, summarisation, smart search and form filling. AI Applications in Frontend Development also cover on-device models for tasks such as image classification. Most features call a model provider such as OpenAI, Anthropic (Claude) or Google Gemini through your own server, never directly from the browser with a secret key.
Implementing AI well means handling Streamed Responses token by token, showing progress, letting users stop generation, rendering Markdown output safely, handling rate limits and errors, and making the interface honest about uncertainty. Treat model output as untrusted input: never insert it as raw HTML.
Practice. Build a chat UI that streams a model's reply from your own API route, supports stop and retry, and sanitises output.
How LLMs Work, Prompt Engineering and AI Agents Optional
How LLMs Work in brief: a large language model predicts the next token from the text so far, using patterns learned from a huge amount of data. It has a limited context window, can produce confident but wrong answers, and its output varies between runs. Prompt Engineering is the craft of giving clear instructions, context, examples and an output format, such as JSON validated against a schema.
AI Agents let a model call tools in a loop to complete a task, such as searching, then filling a form. The Model Context Protocol defines one shared way for an assistant to reach tools and data, with each integration running as a small server. Front end engineers increasingly build the interfaces where people approve or correct agent actions.
Practice. Write a prompt that turns a product description into validated JSON, and test it on twenty varied inputs.
Data structures and algorithms for front end interviews Core
Many companies, especially larger ones, include a general coding round. Front end candidates usually face easy to medium problems: arrays and strings, hash maps, two pointers, stacks, queues, recursion, trees and simple graph traversal. Tree questions map naturally to the DOM, such as finding a node or flattening a nested structure.
Front-end-specific coding rounds ask you to implement utilities in JavaScript: debounce, throttle, Promise.all, deep clone, an event emitter, array flat, curry, or a small templating function. Explain time and space complexity in Big O terms. Practise in coding practice and follow the Data Structures and Algorithms Roadmap for patterns.
Practice. Implement debounce, throttle, Promise.all and an event emitter from memory, with tests, in under an hour.
Front end system design Core
Mid and senior candidates usually face a front end system design round: design a news feed, an autocomplete, a photo gallery, a chat app or a collaborative editor. Use a clear structure: requirements (functional and non-functional), component architecture, data model and state, API between client and server (REST, GraphQL, WebSockets or server-sent events), then deep dives on performance, accessibility, offline support, internationalisation and security.
Discuss concrete trade-offs: pagination with cursors versus offsets, normalising data in a client cache, optimistic updates and rollback, list virtualisation, and image loading. Draw the component tree and data flow. Practise with system design practice and time yourself to about 45 minutes.
Practice. Design an autocomplete component end to end in 45 minutes, covering API, caching, keyboard handling and race conditions.
Projects to build
Build these in order. Each one should end up in a public repository with a short README that explains your decisions.
- Accessible portfolio siteBeginner
Build a personal site in plain HTML and CSS with a home page, project pages and a contact form. It must be responsive from 320 pixels up, pass an automated accessibility check, work fully by keyboard and score highly on Lighthouse. Host it on GitHub Pages with a custom domain.
Semantic HTML · Responsive CSS · Accessibility · DNS and hosting
- Kanban board with TypeScript and testsIntermediate
Build a task board with columns, drag and drop that also works by keyboard, local persistence and undo. Use strict TypeScript, a reducer for state, Vitest and Testing Library for components, and two Playwright tests for the main journeys, all running in CI.
TypeScript · State management · Testing · Accessible drag and drop
- Mini design systemIntermediate
Create a small component library: tokens as CSS custom properties with light and dark themes, plus Button, Input, Select, Modal, Tabs and Toast. Document each in Storybook with usage guidance, run accessibility and visual tests, and publish it as a versioned package used by another of your apps.
Design tokens · Component API design · Storybook · Package publishing
- Next.js storefront with a performance budgetAdvanced
Build a shop with server-rendered product pages, a client-side cart, sign-in through OpenID Connect and a checkout form. Set a budget for JavaScript size and Core Web Vitals, enforce it in CI, and report field data from the deployed site. Write up the trade-offs you made in the README.
Next.js · Rendering strategies · Authentication · Performance budgets
- Streaming AI assistant interfaceAdvanced
Build a chat interface that calls a model through your own API route, streams tokens, renders Markdown safely, supports stop, retry and editing of earlier messages, and stores conversations offline with IndexedDB. Include a strict Content Security Policy and tests for the streaming states.
Streamed responses · Security · IndexedDB · AI integration
Preparation plan
- Weeks 1–2JavaScript fundamentals and utilities
Revise closures,
this, prototypes, the event loop and promises; write a one-page summary of each in your own words.Implement debounce, throttle, Promise.all, deep clone, curry and an event emitter with tests.
Solve one or two easy algorithm problems a day in coding practice.
- Weeks 3–4HTML, CSS and accessibility
Build five layouts from screenshots with Grid and Flexbox, timed at 30 minutes each.
Build tabs, modal, accordion and combobox widgets in plain JavaScript with full keyboard and ARIA support.
Audit one of your projects with axe and a screen reader and fix everything you find.
- Weeks 5–6React, TypeScript and testing
Rebuild the widgets in React with strict TypeScript, and add Testing Library tests for each.
Revise hooks, rendering, keys, stale closures and state management patterns; explain each aloud.
Continue algorithms practice at medium level, focusing on arrays, hash maps, trees and recursion.
- Weeks 7–8Performance, security and rendering
Profile your portfolio app, improve its Core Web Vitals and record before and after numbers for your stories.
Revise caching headers, CORS, CSP, XSS, CSRF and authentication storage, and write answers to the common questions.
Build one small page with SSR, SSG and streaming in Next.js to speak from experience.
- Weeks 9–10System design, behavioural and mock interviews
Practise five front end system design prompts in system design practice with a 45-minute timer.
Write six to eight behavioural stories and rehearse them aloud.
Do at least three full mock interviews, including a live UI build, and track weak areas in progress page.
Interview questions
Try to answer each question out loud before you open the answer.
What is printed, and in what order? <code>console.log(1); setTimeout(() => console.log(2)); Promise.resolve().then(() => console.log(3)); console.log(4);</code>Junior
It prints 1, 4, 3, 2. The two plain logs run first as part of the current script task. The promise callback goes into the microtask queue and the timer callback into the task queue. When the script finishes, the event loop drains all microtasks before taking the next task, so 3 prints before 2, even though the timeout delay is zero. A zero timeout means "as soon as possible after at least zero milliseconds", not "now". This ordering is why a long chain of promise callbacks can delay rendering.
What happens when you type a URL into the browser and press Enter?Junior
The browser parses the URL and checks its caches. It resolves the domain through DNS, opens a TCP connection (or QUIC for HTTP/3) and performs a TLS handshake for HTTPS. It sends the HTTP request; a CDN or server responds, perhaps after a redirect. The browser parses the HTML into the DOM, finds CSS, scripts and images and fetches them, builds the CSSOM, runs scripts, then calculates layout, paints and composites. I would mention where caching skips steps and that render-blocking CSS and synchronous scripts delay the first paint.
Implement a debounce function and explain when you would use it instead of throttle.Junior
function debounce(fn, wait) {
let timer;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), wait);
};
}Each call resets the timer, so fn runs once the calls stop for wait milliseconds, with the latest arguments and the original this. I use debounce for search inputs and resize handling, where only the final value matters. Throttle runs at most once per interval during continuous activity, which suits scroll position tracking. In production I would add a cancel method and maybe a leading option.
Why does React need keys on list items, and why is the array index often a bad key?Junior
Keys let React match items between renders, so it can keep the right component state and DOM node for each item when the list changes. If I use the index and an item is inserted at the top, every item's key shifts: React reuses the wrong components, so input values, focus or local state appear on the wrong row, and it does extra work. Keys should be stable and unique among siblings, usually a database ID. The index is fine only for static lists that never reorder, insert or delete.
A user reports that clicking 'Save' sometimes saves old data. The handler reads state set in a useEffect. How do you investigate?Mid
I suspect a stale closure. A callback created during one render sees the state values from that render; if it is stored somewhere, such as an interval, a memoised callback with missing dependencies or an event listener added once in an effect, it keeps reading old values. I would reproduce it, check the dependency arrays, and look at the hooks lint warnings. Fixes include correct dependencies, using the functional updater setX(prev => ...), deriving values during render instead of copying them in an effect, or keeping the latest value in a ref when an external listener needs it.
How would you build an accessible custom dropdown or combobox?Mid
First I would ask whether a native select works, because it is accessible by default. If not, I follow the ARIA combobox pattern: an input with role="combobox", aria-expanded and aria-controls pointing at a listbox of option elements, and aria-activedescendant marking the highlighted option while focus stays in the input. Keyboard: arrows move, Enter selects, Escape closes, Tab leaves. The selected option has aria-selected. I announce result counts through a live region, ensure visible focus and contrast, and test with a screen reader, not just axe.
When would you choose client-side rendering, server-side rendering or static generation?Mid
Static generation suits content that changes rarely and is the same for everyone, such as documentation and marketing pages: fastest and cheapest, served from a CDN. Server-side rendering suits pages that need fresh or personalised data and good search indexing, such as product pages or feeds, at the cost of server work per request and careful caching. Client-side rendering suits highly interactive screens behind a login, such as an editor or dashboard, where SEO does not matter. Most apps mix them per route, and incremental regeneration or streaming can blend the benefits.
The Largest Contentful Paint on our product page is slow on mobile. How do you approach it?Mid
I check field data first to confirm the problem and which devices are affected, then reproduce with Lighthouse and the Performance panel on a throttled profile. I identify the LCP element, usually the hero image or heading, and break the time into server response, resource load delay, load time and render delay. Typical fixes: make the image discoverable in HTML rather than injected by JavaScript, add fetchpriority="high" and remove lazy loading from it, serve a correctly sized modern format, cache HTML at the edge, and cut render-blocking CSS and fonts. Then I verify in field data after release.
How do you prevent cross-site scripting in a React application?Mid
React escapes text in JSX by default, so the main risks are the escape hatches. I avoid dangerouslySetInnerHTML; when I must render HTML, such as Markdown or CMS content, I sanitise it with a maintained sanitiser. I validate URLs before putting them in href to block javascript: links, avoid building code from strings, and treat model and third-party output as untrusted. I add a strict Content Security Policy with nonces so injected scripts cannot run, keep auth tokens in HttpOnly cookies so an XSS bug cannot steal them, and audit dependencies and third-party scripts.
Where should a browser app store authentication tokens?Mid
My default is an HttpOnly, Secure, SameSite cookie holding a session ID or token, because JavaScript cannot read it, so an XSS bug cannot steal it. I then protect state-changing requests against CSRF with SameSite settings and, where needed, a CSRF token. localStorage is simple but readable by any script on the page, so a single XSS flaw or compromised dependency leaks the token. Keeping a short-lived access token in memory with a refresh token in an HttpOnly cookie is a common middle ground for single-page apps calling separate APIs.
You see a CORS error in the console. What does it mean and how is it fixed?Junior
The browser blocked my page from reading a response from a different origin because the server did not allow it. CORS is enforced by the browser, not the server; the request may even have reached the server. For non-simple requests the browser first sends an OPTIONS preflight. The fix is on the server: return Access-Control-Allow-Origin for my origin, plus allowed methods and headers, and Access-Control-Allow-Credentials if cookies are sent, in which case the origin cannot be a wildcard. In development a dev-server proxy avoids the issue. Disabling CORS in the browser is never a fix.
Design the front end for an autocomplete search box used on a large e-commerce site.Senior
Requirements: suggestions as you type, keyboard and screen reader support, fast on mobile. Components: input, listbox, option rows, recent searches. Data: debounce input around 200 milliseconds, cancel stale requests with AbortController or ignore out-of-order responses, and cache results per query in memory with a size limit so backspacing is instant. API: a GET endpoint returning a small, ranked list with highlighted ranges, cacheable at the CDN for popular prefixes. Accessibility: the ARIA combobox pattern and a live region for counts. Also discuss minimum query length, error and empty states, analytics on selection, and internationalisation of matching.
Design a news feed with infinite scroll that stays fast after hundreds of items.Senior
I would server-render the first page for fast content, then fetch more with cursor-based pagination, triggered by an IntersectionObserver sentinel near the end. Data goes into a normalised client cache keyed by post ID so updates such as likes apply everywhere. To stay fast I virtualise the list so only visible items and a small buffer are in the DOM, reserve image space to avoid layout shift, lazy load media and pause off-screen video. New posts appear behind a "new posts" banner rather than shifting content. Likes are optimistic with rollback on failure. I would restore scroll position on back navigation and keep keyboard and screen reader access to every item.
How would you organise state in a large React application?Senior
I classify state before choosing tools. Server state goes in a query cache such as TanStack Query or framework loaders, with clear keys and invalidation. URL state, such as filters and tabs, goes in the route so links are shareable. Form state stays in a form library. Truly global client state, such as the current user or theme, goes in a small store or context, split so unrelated updates do not re-render everything. Everything else stays local and is lifted only when needed. I would also set conventions for where fetching happens, keep derived values computed rather than stored, and document the rules so teams do not reinvent them.
Tell me about a time you disagreed with a designer or product manager.Mid
A strong answer describes a real disagreement with stakes, such as a design that failed contrast requirements or an animation that hurt performance on low-end phones. Explain how you understood their goal first, brought evidence such as a contrast check, a prototype or performance numbers, offered alternatives that kept the intent, and agreed a decision. Finish with the result and what you learned, for example that sharing accessibility checks earlier in the design process avoids late conflict. Avoid stories where you simply won the argument.
Describe a bug you shipped to production and what you did about it.Mid
Pick a real, specific incident. Describe how it was noticed, the immediate fix or rollback, and how you communicated with affected people. Then explain the root cause, for example a caching header that served old HTML after a release or a timezone bug in date formatting, and the lasting change you made: a test, a monitoring alert, a lint rule or a checklist item. Interviewers look for ownership, calm and learning, not perfection. Do not blame teammates.
Common mistakes
- Jumping to React before understanding HTML, CSS and JavaScript; spend real time on the platform first, because framework bugs are usually platform misunderstandings.
- Using div and span for everything; use semantic elements and native controls so keyboard and screen reader support come for free.
- Copying props into state with useEffect; derive values during render and keep one source of truth.
- Storing fetched data in a global store and syncing it by hand; use a server-state library with caching and invalidation.
- Treating accessibility as a final polish step; test with the keyboard and a screen reader while you build each component.
- Optimising without measuring; profile first with the Performance panel or Lighthouse and fix the biggest cost.
- Storing auth tokens in localStorage by default; prefer HttpOnly cookies and add a Content Security Policy.
- Writing tests that check implementation details; query by role and label and assert on what the user sees.
- Accepting AI-generated UI code without review; check it for accessibility, security and performance like any other code.
Ready-for-interview checklist
- I can explain what happens from typing a URL to seeing a rendered page, including caching.
- I can build a responsive layout with Flexbox and Grid without a CSS framework.
- I can write semantic, accessible HTML and test it with a keyboard and a screen reader.
- I can predict the output of code mixing timers, promises and async functions.
- I can implement debounce, throttle, Promise.all and an event emitter from memory.
- I can build a React app in strict TypeScript with routing, forms and server-state caching.
- I can explain when to use CSR, SSR, SSG and streaming, and build each in Next.js.
- I can write unit, component and end-to-end tests and run them in CI.
- I can measure Core Web Vitals and fix a slow LCP or poor INP.
- I can explain XSS, CSRF, CORS and CSP, and where to store auth tokens.
- I can set correct Cache-Control headers for HTML and hashed assets.
- I can design a feed or autocomplete in a 45-minute front end system design round.
- I can tell six behavioural stories with clear results.
Where this role leads
Full Stack Developer: add Node.js, databases and API design to own features from database to UI.
Mobile Developer: use React Native or Flutter to bring your UI skills to native apps.
UX Designer: move closer to research and interaction design, using your understanding of what is buildable.
Software Architect: grow from front end architecture into designing whole systems across teams.
Engineering Manager: lead a front end or product team and develop the engineers in it.
Related roadmaps
- HTML RoadmapSemantic structure, forms, media, accessibility and SEO basics.
- CSS RoadmapCascade, layout with flexbox and grid, responsive design, animation.
- JavaScript RoadmapLanguage core, async, the event loop, modules and the DOM.
- TypeScript RoadmapTypes, generics, narrowing, utility types and project setup.
- React RoadmapComponents, hooks, state, data fetching, performance and testing.
- Next.js RoadmapApp Router, server components, data fetching, caching and deployment.
FAQ
How long does it take to become a front end engineer?
From zero, most people need six to twelve months of steady study at ten to fifteen hours a week to reach a junior level, with several real projects to show. People who already code in another language or work in design often move faster. Getting hired also depends on your portfolio, your network and how much interview practice you do, so start applying once you can build and explain a tested React app.
Should I learn React, Vue or Angular first?
For most people React is the best first choice because it has the most job posts and learning material. Vue is easier to start with and popular in some regions and agencies. Angular is common in large enterprises and banks. Check job listings where you want to work. Whichever you pick, learn plain JavaScript first; the core ideas transfer between frameworks in a few weeks.
Do front end engineers need to know data structures and algorithms?
It depends on the company. Large technology companies usually include at least one general algorithms round, mostly easy to medium problems. Many smaller companies focus on practical UI builds and JavaScript questions instead. Prepare the fundamentals either way: arrays, hash maps, trees and recursion, plus front-end-specific utilities such as debounce and Promise.all.
Is front end development still worth learning with AI coding tools?
Yes. AI assistants write a lot of boilerplate, but they often produce interfaces with accessibility gaps, security holes and performance problems, and someone has to notice and fix them. Teams still need engineers who understand the browser, can design component architecture and can judge whether generated code is correct. Learn the fundamentals deeply and use AI tools to move faster, not to skip understanding.