Foreword
This guide is built for interviewing — and being — a Lead Frontend Engineer at the bar of companies like Anthropic, Facebook (Meta), Airbnb, Uber, Stripe, Vercel, and ThoughtWorks. It is intentionally harder than the average React-interview cheat sheet: it expects the candidate has shipped at scale, has opinions backed by production scars, and can reason from first principles.
The guide follows the natural arc of a frontend system from zero to production — each section covers decisions, trade-offs, hard questions, model answers, and deep-dive references. Use the navigation on the left; use the search box to jump fast. Every coloured reference link goes to canonical documentation (MDN, web.dev, React docs, Next.js docs, RFCs, engineering blogs).
01Project Inception — From Zero to Plan (Deep Dive)
The first 2–4 weeks of a frontend project determine the next 2 years. A Lead is judged less on writing code than on asking the right questions before any code is written. This section is the full curriculum for becoming exceptional at inception — read it in order, do the exercises, then re-read it before any project kickoff.
Sub-sections in this deep-dive
- Why Inception Matters — The Cost of Skipping It
- The Discovery Workshop — Step by Step
- Stakeholder Mapping & Power Dynamics
- Requirements Engineering — Asking the Right Questions
- Prioritization Frameworks (MoSCoW, RICE, ICE, Kano, WSJF)
- Writing the Product Engineering Brief
- Non-Goals — The Most Underrated Section
- Defining Success — Metrics, OKRs, North Stars
- Pre-Mortems — Imagining Failure Before You Start
- Estimation Under Uncertainty
- Risk Mapping & Mitigation
- Conway's Law & Team Topology
- Building Shared Understanding (Event Storming, Story Mapping)
- The Tech Lead's Inception Toolkit
- 30/60/90 Day Plans
- Influence Without Authority
- The Art of the First Week
- Common Inception Anti-Patterns
- Hard Questions Bank
- Practice Exercises — Run Your Own Inception
- Full Resource Library (Courses, Books, Talks, Articles)
Why Inception Matters — The Cost of Skipping It
The cheapest bug to fix is the one in the requirements doc; the most expensive is the one shipped to production after a year of building the wrong thing. Inception is where you discover whether the project should exist, what success means, and what failure modes lie ahead — before you spend headcount on the wrong solution.
The Cost Curve of Decisions
This is the Boehm cost curve, popularized in software engineering since the 1980s and validated again at modern scale:
| Stage | Relative cost to change | What's changeable here |
|---|---|---|
| Requirements / Inception | 1× | Scope, problem definition, success metrics |
| Design | 3–6× | Architecture, tech stack, team shape |
| Implementation | 10× | Code structure, libraries |
| Testing / Pre-prod | 15–40× | Bugs, integration issues |
| Production | 40–100× | Behaviour fixes; customer trust; rework |
The implication for Lead Engineers: aggressive investment in inception pays back disproportionately. Spending an extra week to nail down scope can save 3 months of rework downstream.
What You Are Actually Solving
Inception is the answer to four questions, in this order:
- Why? — What's the business or user pain that justifies headcount on this work?
- For whom? — Which user segment, in which context, with which devices?
- What does done look like? — A measurable definition of success.
- What is explicitly NOT in scope? — Non-goals.
If you can't answer all four in two sentences each, inception isn't complete. Most projects ship without satisfying #3 and #4 — and that's why they're declared "done" but feel unsuccessful.
The Discovery Workshop — Step by Step
An inception workshop (also called a "kickoff workshop," "Lean Inception," or "Big Picture EventStorming") is a structured 2–5 day collaborative session that aligns engineering, product, design, and stakeholders before any building begins. ThoughtWorks popularized the modern version; Marty Cagan and Teresa Torres formalized the discovery half.
The Typical Agenda (Adapted from ThoughtWorks Lean Inception)
Vision, users, jobs-to-be-done
Write the elevator pitch. Identify primary & secondary personas. Map the jobs each persona is trying to accomplish.
Goals, non-goals, current-state journey
Define the business objectives (NSM + supporting metrics). Walk the current user journey end-to-end on a wall. Identify pain points.
Feature brainstorm, MVP scope, sequencing
Generate feature ideas; group by user benefit. Use MoSCoW or RICE to size and prioritize. Sketch the MVP.
Architecture sketch, risks, dependencies
High-level architecture (no commitments). Identify external dependencies. List the top 10 risks. Run a pre-mortem.
Engineering Brief + roadmap + next steps
Author the brief. Define the first 30/60/90 days. Identify open questions and decision owners.
The Inputs You Must Gather
- Business objectives — what KPI moves if we ship this? Acquisition, activation, retention, revenue, cost-to-serve, NPS? Vanity vs north-star.
- User research — primary personas, jobs-to-be-done, accessibility needs (locale, device, assistive tech), bandwidth profile, churn data.
- Constraints — deadline (regulatory? market-event? competitive?), budget, headcount, vendor obligations, contractual SLAs.
- Existing landscape — current systems (FE + BE), auth model, design system, observability stack, data warehouse, A/B platform.
- Non-functional requirements — SLA, p95/p99 latency, geographic distribution, WCAG level, compliance (SOC 2, HIPAA, GDPR, PCI), RPO/RTO.
- Definition of success — measurable; what does the org celebrate or count as a failure?
Outputs of the Workshop
- Product Engineering Brief (Section 1.6).
- User journey map (current & target).
- Prioritized feature backlog (MoSCoW or RICE-scored).
- Top-10 risk register.
- Architecture sketch (whiteboard-level — not code).
- 30/60/90 day plan.
- Open questions with named decision owners.
Try it yourself
- Pick a personal project (real or imagined — e.g., "a habit tracker for parents").
- Solo-run a 90-minute mini-inception: write the elevator pitch (1 paragraph), 3 personas, top 5 user jobs, target NSM, top 3 risks, 3 non-goals.
- Review the brief 3 days later — what feels obvious now that wasn't on day 1? That's the discovery payoff.
Stakeholder Mapping & Power Dynamics
Inception is also where you learn who can derail your project. Map this consciously — don't discover it three months in.
The Power × Interest Grid (Mendelow 1991)
| Low interest | High interest | |
|---|---|---|
| High power | Keep satisfied — minimal but consistent updates; don't surprise them | Manage closely — frequent 1:1s, co-author key decisions |
| Low power | Monitor — broadcast updates suffice | Keep informed — they'll surface useful info; valuable allies |
For every stakeholder you can name, plot them in this grid. The biggest project killers are high-power / low-interest people whose "no" can stop everything — they need a relationship before there's a problem.
The Modern Lead's RACI
RACI = Responsible, Accountable, Consulted, Informed. Draw it for every major decision. Anti-pattern: too many A's (no clear owner) or too many C's (decision paralysis).
| Role | Owns | Lead FE's relationship |
|---|---|---|
| Product Manager | Problem, priorities, scope | Daily collaboration; you push back on scope. |
| Design Lead | UX, IA, design system inputs | Negotiate feasibility; flag a11y & perf tax. |
| Backend Lead | API contracts, data model | Co-design API shape; advocate for FE ergonomics. |
| Platform / DevOps | CI/CD, infra, observability | Define FE deploy strategy within their constraints. |
| Security | Threat model, compliance | Engage early; CSP, auth, data residency need sign-off. |
| Data / Analytics | Instrumentation, A/B platform | Define tracking schema as part of feature spec. |
| QA / SDET | Test strategy, automation | Co-author testing pyramid; align on E2E ownership. |
| Legal / Privacy | Cookie banner, T&C, data residency | Loop in for any new tracking or third-party. |
| Customer Support | User pain at the coalface | Often your best source of "what's actually broken." |
| Marketing / Growth | SEO, performance marketing constraints | Influences URL design, rendering strategy, analytics. |
| Finance / Procurement | Vendor approval, budget | Tool/CDN/observability spend goes through them. |
Reading the Org Chart
The org chart is a political map. Three signals to read:
- Reporting line of the sponsor. A VP-sponsored project survives reorgs; a director-sponsored project may not.
- Cross-functional dependencies. Every team you depend on has its own priorities. Map them at inception so you're not surprised when they don't ship.
- Skip-level allies. A senior staff engineer two levels above can unblock you faster than your direct manager. Build relationships before you need them.
Requirements Engineering — Asking the Right Questions
The deepest skill in inception is asking questions that surface what people haven't said. PMs underspecify; users articulate symptoms not causes. A Lead's questioning instinct is what separates a good kickoff from a great one.
The 5 Whys (Sakichi Toyoda, Toyota Production System)
For every stated requirement, ask "why?" five times. Each "why" pushes from feature → outcome → underlying problem.
EXWorked Example
PM: "We need a dark mode toggle."
Why? Users have asked for it.
Why? Some complain the app is too bright at night.
Why? They use it in bed before sleep.
Why? Our session metrics show 28% of sessions are 10pm-2am.
Why? Our users use the app to wind down — they're not work-focused at that hour.
Real requirement: Reduce eye strain and respect circadian context — which could also be auto-dim, blue-light filtering, or a "calm mode" beyond just dark.
The Mom Test (Rob Fitzpatrick)
Three rules for questions that get real answers, not the answers people think you want:
- Talk about their life, not your idea.
- Ask about specifics in the past, not opinions about the future.
- Talk less, listen more.
Bad: "Would you use a feature that…?" (Yes — they're being polite.)
Good: "Tell me about the last time you tried to do X. What happened?"
5W2H — A Requirements Checklist
- What exactly are we building?
- Why are we building it? (Business and user)
- Who will use it? Who is responsible for it?
- Where will it run? (Device, geography, network conditions)
- When does it ship? Driven by what?
- How will we know it worked?
- How much — cost, scope, performance budget?
Questions a Senior Lead Always Asks
- "What does failure look like for this project?"
- "If we could only ship one thing, which one would it be?"
- "What's the cost of doing nothing?"
- "Has anyone tried to solve this before? What happened?"
- "Who's the most opinionated stakeholder we haven't consulted yet?"
- "What would change our mind about this approach?"
- "What's the deadline driven by? Is it real?"
- "Whose budget pays for this? Whose headcount?"
- "What happens to this project if [key person] leaves?"
- "What are we NOT going to do?"
Drill: The Probe Ladder
- Take a 1-line feature request from your current backlog ("Add a filter to the dashboard").
- Generate 10 clarifying questions across the 5W2H grid.
- Rank them by which would most change your implementation if answered.
- Take the top 3 to your PM. Notice how the conversation shifts.
Prioritization Frameworks — Picking What to Build First
Prioritization is the most leveraged conversation in inception. A Lead doesn't just rubber-stamp the PM's list — they bring frameworks that make trade-offs explicit and defensible.
MoSCoWMust / Should / Could / Won't
Classify each requirement. Forces the team to commit to a "Won't" list — usually the most revealing column. Best for early-stage scoping.
Pitfall: Everything becomes a "Must." Rule: no more than 60% of effort in Must; if higher, the project is over-scoped.
RICEReach × Impact × Confidence ÷ Effort
Used at Intercom, popularized in product. Each feature scored:
- Reach — users affected per time period.
- Impact — 0.25 (minimal), 0.5, 1 (medium), 2, 3 (massive).
- Confidence — 50%, 80%, 100%.
- Effort — person-months.
Forces explicit reasoning. Excellent for mid-project re-prioritization meetings.
ICEImpact × Confidence × Ease
Lighter-weight RICE, used at Sean Ellis's growth-hacking framework. Useful when reach is similar across options.
KANOBasic / Performance / Excitement
Categorizes features by user reaction:
- Basic / Threshold — required for the product to be acceptable. Users don't notice them; their absence kills the product.
- Performance / Linear — more = better. Speed, storage, completeness.
- Excitement / Delighters — unexpected, raise satisfaction non-linearly. Become "Basic" over time.
- Indifferent — users don't care; cut these.
- Reverse — users dislike these (unwanted complexity).
Use to ensure you have the right mix — all Basic + no Excitement = forgettable product; lots of Excitement + missing Basics = broken.
WSJFWeighted Shortest Job First (SAFe)
(Cost of Delay) ÷ Job Size = priority score. Cost of Delay = User-Business Value + Time Criticality + Risk Reduction. Designed for backlogs of similar-sized items where time pressure varies. Common in enterprise / regulated environments.
OPPOpportunity Solution Tree (Teresa Torres)
Tree: Desired Outcome → Opportunities (user needs/pains) → Solutions → Experiments. Forces continuous discovery — never jump straight to solutions. Excellent for navigating from a goal (NSM) down to validated, testable feature ideas.
Choosing a Framework
| Situation | Pick |
|---|---|
| Early scoping, mixed stakeholder room | MoSCoW (simple, communicable) |
| Comparing many features quantitatively | RICE |
| Fast lightweight ranking | ICE |
| Ensuring product is satisfying | Kano |
| SAFe / regulated environment | WSJF |
| Continuous discovery, outcome-driven | Opportunity Solution Tree |
| Tactical sprint planning | Eisenhower (urgent × important) |
Drill: Score Your Backlog
- Take 8 items from your current backlog (real or invented).
- Score each using RICE.
- Re-rank from your current order.
- Identify the biggest mismatch — that's where political priority is overriding objective priority.
- Decide: is that mismatch justified by context, or should you push back?
Writing the Product Engineering Brief
The brief is the single artifact of inception. Done right, it survives reorgs, prevents scope creep, and serves as a calibration point for every future decision. Aim for 4–8 pages. Below 4 pages = under-thought; above 8 pages = nobody reads it.
The Canonical Template
# <Project Name> — Engineering Brief Owner: <name> · Status: Draft / Approved · Last updated: <date> ## 1. TL;DR (3 sentences max) What we're building, who for, why now. ## 2. Problem Statement The user / business pain in 1–2 paragraphs. Cite evidence (metrics, support tickets, user interviews). No solutions yet. ## 3. Users & Jobs-to-be-Done Primary persona(s) and the specific jobs they're hiring this product to do. ## 4. Goals Measurable success criteria (leading + lagging metrics). "We will know this worked when X moves from Y to Z by <date>." ## 5. Non-Goals Explicit list of what we are NOT solving in this project. The most-referenced section after launch. ## 6. Solution Sketch High-level approach (no architecture yet — that's the next doc). 1–2 paragraphs + a sketch if helpful. ## 7. Open Questions Top 5–10 unanswered questions, each with named owner and due date. ## 8. Risks & Mitigations Top risks (technical, organizational, market) with mitigation plans or "accepted risk" call-outs. ## 9. Milestones & Sequencing 30 / 60 / 90 day plan with dependencies. No specific dates yet. ## 10. Stakeholders & Decision Owners RACI for the major decisions. ## 11. Appendix Research, links to design docs, ADRs, related projects.
What Makes a Brief Good
- Specific, not aspirational. "Reduce checkout abandonment from 32% to 25% by Q3" beats "Improve checkout."
- Cites evidence. Every claim ("users want X") has a citation (ticket, survey, interview, metric).
- Has named owners. Every open question has a person and a date.
- Acknowledges what's unknown. Pretending to know what you don't kills credibility.
- Reads in 15 minutes. If a senior leader can't get the gist in 15 minutes, it's too long.
- Has a kill criterion. "We'll stop this project if metric X hasn't moved by Y." Engineering honesty.
Design Docs vs ADRs vs RFCs vs Engineering Briefs
| Document | Scope | Lifespan |
|---|---|---|
| Engineering Brief | The whole project; why & what | The whole project (months/years) |
| Design Doc | How to build a major component / feature | Pre-build through launch |
| RFC (Request for Comments) | Proposed change across teams; cross-cutting decisions | Days to weeks; archived after decision |
| ADR (Architecture Decision Record) | One decision + context + consequences | Permanent — historical record |
| One-Pager / Pitch | Sell an idea to leadership | Until decision |
Reference: Will Larson — Design Docs at Stripe · Industrial Empathy — Design Docs at Google · Pragmatic Engineer — Scaling via RFCs
Non-Goals — The Most Underrated Section
The fastest way to spot a senior Lead is to read their non-goals section. It signals discipline, focus, and the courage to disappoint stakeholders deliberately.
Why Non-Goals Are Hard
- Stakeholders don't ask for non-goals — they ask for goals.
- Writing "we won't build X" feels like a defeat in a culture that rewards ambition.
- Non-goals require political will — you'll have to defend the omission.
- Without them, scope drifts silently. With them, anyone trying to add scope must explicitly remove the "won't."
Good Non-Goals Are Specific
| Bad non-goal | Good non-goal |
|---|---|
| "Optimize performance" | "INP below 200ms for users on mid-tier Android" (this is a goal) |
| "Not redesigning" | "We will NOT redesign the existing search UI; we'll reuse the v3 component library as-is" |
| "No mobile" | "We will NOT build native iOS/Android in this project; the web app must work on mobile browsers" |
| "Skipping i18n" | "This release ships en-US only; non-English locales come in v2 (Q3 2027)" |
Common Non-Goal Categories
- Platforms — what platforms / browsers / devices we won't support.
- Performance — explicit "we won't optimize below X" budget.
- Edge cases — which low-frequency user paths we'll defer.
- Accessibility — what level (AA but not AAA, e.g.).
- Internationalization — locales not supported in v1.
- Integrations — third parties we won't connect to.
- Migration — what we'll leave on the old system.
- Backwards compatibility — what we'll break.
Defining Success — Metrics, OKRs, North Stars
Inception without a measurable definition of done is inception by vibes. A Lead nails this before a line of code.
The Metrics Pyramid
| Level | What | Example (e-commerce) |
|---|---|---|
| North Star Metric (NSM) | One number that reflects product value delivered | "Repeat-purchase revenue per active customer" |
| L1 / Driver metrics | 2–4 metrics that move the NSM | Conversion rate, AOV, retention, frequency |
| L2 / Feature metrics | Metrics tied to a specific feature | Cart-abandonment-rate, checkout completion time |
| Health / Counter metrics | What you'll watch for unintended damage | Refund rate, support ticket volume |
Leading vs Lagging Indicators
- Leading — predicts future state. Page-view time, scroll depth, button clicks. Move fast — useful for in-quarter steering.
- Lagging — confirms what already happened. Revenue, retention, NPS. Move slow — useful for definitive proof.
A Lead aligns the team on leading metrics weekly, lagging metrics quarterly. Reporting only lagging metrics is steering by looking in the rear-view mirror.
Writing Good OKRs
Objective + 3–5 Key Results. Objective is qualitative ("Delight power users"); Key Results are specific, quantitative, time-bound.
| Bad | Good |
|---|---|
| "Improve performance" | "p75 LCP for the catalog page drops from 3.4s → 2.0s by end of Q3" |
| "Increase engagement" | "Weekly active users with ≥3 sessions grows from 22% → 30% by end of Q3" |
| "Ship the redesign" | "95% of organic traffic served by the new design system by end of Q3 with no regression in conversion" |
The Goodhart Trap
Pre-Mortems — Imagining Failure Before You Start
A pre-mortem (Gary Klein, 2007 HBR) is the inverse of a post-mortem: you imagine the project has failed catastrophically, then work backwards to figure out why. Surfaces risks that optimistic planning hides.
How to Run One
- Gather the team (engineering + product + design) for 60 minutes.
- State the prompt: "It is 12 months from now. This project has failed catastrophically. The team is being disbanded. Why?"
- Silently — for 10 minutes, each person writes their top 5 reasons. (Silence first prevents groupthink.)
- Round-robin: each person shares one reason. Cluster on a whiteboard.
- Vote: each person gets 3 dots; place on the most-worrying clusters.
- For top 3 risks, draft mitigation plans with owners.
- Capture in the brief's risk register.
Common Pre-Mortem Findings (FE-flavored)
- "We over-invested in the design system and shipped no user-facing features."
- "The backend team's API was 8 weeks late; we couldn't ship without it."
- "Performance regressed silently because we didn't set budgets."
- "We picked Module Federation but only one engineer understood the failure modes."
- "We never validated the design with real users; the redesign tanked conversion."
- "Our hiring loop took 6 months; we shipped late by exactly that."
- "Stakeholder X never bought in; quietly blocked us for the whole project."
- "We migrated mid-flight to a new framework; doubled scope."
Estimation Under Uncertainty
Estimation in inception is the single most-faked skill in software. Junior leads quote a number; senior leads quote a distribution.
The Cone of Uncertainty (Boehm)
At project start, estimates are accurate within a factor of 4×. By design phase, 2×. By implementation, 1.25×. Estimates given at inception are inherently coarse — communicate that explicitly.
Three Estimation Modes
| Mode | Use when | Output |
|---|---|---|
| T-shirt sizing | Early inception, no design | S / M / L / XL — for relative ranking only |
| Story points (relative) | Team has shipped together, has velocity baseline | 1 / 2 / 3 / 5 / 8 / 13 — Fibonacci-style |
| Reference class forecasting | Comparing this to similar past projects | "This is like the X project we did, which took 4 months" |
| Bottom-up time estimates | Design is locked, scope is fixed | Specific hours/days — with a buffer factor |
Reference Class Forecasting (Kahneman / Flyvbjerg)
Rather than estimating from scratch ("how long will this take?"), find similar past projects and use their actual duration. This corrects for the "planning fallacy" — humans systematically underestimate by 30–80%. Bent Flyvbjerg's research on mega-projects (How Big Things Get Done) shows this is the single most accurate forecasting method available.
The "Steel Thread" Approach
Rather than estimating the whole project, build one minimal end-to-end slice ("steel thread") through every layer in 1–2 weeks. The act of building it tells you what the system actually looks like; estimates after are based on evidence, not imagination.
Communicating Estimates
- Always give a range, never a point. "4–6 weeks at 80% confidence" not "5 weeks."
- State the assumptions explicitly. "Assumes the API spec is locked by Monday; if it slips, add a week per week of slip."
- Distinguish forecast from commitment. A forecast can be wrong; a commitment cannot be without consequence.
- Track actuals. Compare your past estimates to actuals; this calibrates future estimates.
Drill: Calibrate Your Estimation
- Pull your last 10 tickets. Estimate each from scratch as if you hadn't shipped it.
- Compare to actual time. Calculate the average ratio.
- For the next sprint, multiply every estimate by that ratio.
- Re-measure at the end. Repeat until ratio is < 1.3 or > 0.8.
Risk Mapping & Mitigation
A senior Lead names risks before stakeholders ask. The risk register is a living document — first drafted in inception, updated weekly during execution.
Risk Categories (FE-flavored)
| Category | Examples |
|---|---|
| Technical | Untested architecture, library still pre-1.0, perf budget at risk |
| Dependency | Backend API not ready, design system not stable, vendor SLA risk |
| Resource / People | Critical engineer leaving, hiring slip, skill gap on team |
| Schedule | Hard external deadline, conflicting projects competing for same resource |
| Organizational | Sponsor change, reorg, conflicting priorities |
| Market / Competitive | Competitor ships first; user expectations shift |
| Compliance / Legal | GDPR/CCPA changes, accessibility lawsuits, security audit |
| Operational | Incident during launch, CDN outage, third-party SDK breaking |
Risk Score = Probability × Impact
For each risk, score on 1–5 scales for probability and impact. Multiply. Sort by score; focus on top 5.
The Four Risk Strategies
- Avoid — change the plan to remove the risk. ("Drop the experimental library.")
- Mitigate — reduce probability or impact. ("Spike the risky integration in week 1.")
- Transfer — make someone else's problem. ("Move auth to a vendor.")
- Accept — document the risk, do nothing. ("Acknowledged: vendor SLA could degrade. Owner: VP Eng.")
The Risk Register (Template)
| ID | Risk | Cat | P | I | Score | Strategy | Owner | Status | |-----|-----------------------------------|-----|---|---|-------|----------|-------|--------| | R01 | API not ready by week 6 | Dep | 4 | 5 | 20 | Mitigate | Sara | OPEN | | R02 | Design system v3 breaks v2 callers| Tec | 3 | 4 | 12 | Mitigate | Mark | DONE | | R03 | Single Bus Factor on TanStack mig | Peo | 3 | 5 | 15 | Mitigate | Lead | OPEN |
Reference: PMI — Risk Analysis · Will Larson — Mapping Risk
Conway's Law & Team Topology
Conway's Law (1968): "Organizations design systems that mirror their communication structure." If you have 3 teams, you'll build a 3-component system whether or not that's optimal. A Lead applies this intentionally — design the team structure to produce the architecture you want.
The Inverse Conway Maneuver
Coined by Jonny LeRoy + Matt Simons (ThoughtWorks): structure your teams the way you want your software to be structured. Want microfrontends with strong independence? Have small teams with full-stack ownership of their MFE. Want a unified UX? Have a single product team with embedded specialists.
Team Topologies (Skelton & Pais)
Four fundamental team types — the model used at Spotify, Microsoft, Capital One, Netflix:
| Type | Mission | Lifespan | FE example |
|---|---|---|---|
| Stream-aligned | Owns a slice of customer value end-to-end | Long-lived | "Checkout team" owns from cart to receipt |
| Platform | Internal product for stream-aligned teams | Long-lived | Design system team, dev-tools team, build platform |
| Enabling | Helps other teams adopt new tech/practice | Temporary — 3 months | "a11y enablement," "RSC migration squad" |
| Complicated-subsystem | Owns a domain requiring deep specialization | Long-lived | Video player team, payments team, real-time sync team |
Interaction Modes (only 3)
- Collaboration — high bandwidth, short term, for discovery; high cost, use sparingly.
- X-as-a-Service — one team provides a contract; consumers self-serve. Most relationships.
- Facilitating — enabling team helps a stream team for a fixed period.
Reference: teamtopologies.com · Skelton & Pais — Team Topologies (book)
Cognitive Load is the Currency
A team has a finite cognitive budget. Adding scope = adding cognitive load. Beyond a threshold, throughput drops. Team Topologies prescribes: size the team's responsibilities to fit its cognitive load, not the other way around.
Practical Implications for a Lead in Inception
- Sketch the team boundaries alongside the architecture sketch. They co-evolve.
- Avoid "spaghetti teams" where everyone touches everything — Conway's Law produces spaghetti software.
- Decide platform/stream split early. Will the design system live in a platform team or be co-owned across stream teams?
- Limit interaction modes — every additional collaboration relationship is overhead.
Building Shared Understanding — Event Storming & Story Mapping
Two techniques every senior Lead should be able to facilitate. They turn vague problem spaces into shared visual artifacts the whole team can reason about.
Event Storming (Alberto Brandolini)
A workshop technique for discovering domain events. Used heavily in Domain-Driven Design but invaluable for FE architecture too.
- Get everyone — eng, product, design, ops — into one room with a long wall and orange sticky notes.
- Each sticky represents a domain event, written in past tense ("Order Placed", "Payment Confirmed", "Shipment Notified").
- Place events left to right in rough timeline order.
- After 30 minutes, layer in: commands (blue, what triggered the event), actors (yellow, who issued the command), policies (purple, the business rules).
- Identify hot spots — questions, contradictions, gaps — with red stickies.
- The output is a domain map the whole team can refer to for the rest of the project.
Reference: eventstorming.com · Brandolini — Introducing EventStorming (free PDF)
User Story Mapping (Jeff Patton)
Map the user's journey horizontally; layer features vertically by release.
User Activities (horizontal — left→right in user time)
+-------+-------+-------+-------+
| Find | Try | Buy | Use |
+-------+-------+-------+-------+
Backbone| story | story | story | story | ← essential MVP slice
+-------+-------+-------+-------+
Walking | story | story | story | | ← release 2
Skeleton| story | story | | | ← release 3
+-------+-------+-------+-------+
The "backbone" is the minimum viable journey. Releases are horizontal slices — each delivers a complete user journey. Avoids the trap of shipping a partial app (e.g., a great search page with no checkout).
Reference: Jeff Patton — Story Mapping · Patton — User Story Mapping (book)
Choosing Between
- Event Storming — when domain complexity is high (financial, healthcare, multi-actor flows).
- Story Mapping — when user journey is the primary axis (consumer products, SaaS apps).
- Combine for complex consumer products.
The Tech Lead's Inception Toolkit
A checklist of tools / techniques to carry into every kickoff. Don't show up empty-handed.
The Documents Toolkit
- Engineering Brief template (Section 1.6).
- RACI matrix for decision ownership.
- Risk register.
- Open Questions log with named owners.
- Stakeholder map (Power × Interest grid).
- ADR template for individual decisions as they're made.
- 30/60/90 plan template.
The Workshop Toolkit
- Silent brainstorming → cluster → vote (avoid groupthink).
- Lightning talks (5-min framings, one per stakeholder).
- Affinity mapping (group stickies by similarity).
- Dot voting (each person 3 dots).
- Fist of five (1–5 fingers for agreement; explicit consensus check).
- Round-robin readouts (forces every voice in the room).
- Parking lot (capture off-topic thoughts; revisit at end).
The Mental Toolkit
- Chesterton's Fence — don't tear down something until you understand why it was built.
- Hill chart (Basecamp) — visualize uncertainty: tasks are "uphill" (figuring out) before "downhill" (executing).
- 5 Whys — for digging past surface symptoms.
- Wardley Maps — for strategic positioning of components (commodity vs custom).
- Cynefin framework — classify problems: simple / complicated / complex / chaotic. Each needs a different response.
Reference: learnwardleymapping.com · Cynefin framework · Basecamp — Hill Charts
The Facilitation Toolkit
- Reading a room — who's quiet? Who dominates?
- Calling on people gently when silent expertise is in the room.
- Timeboxing aggressively — set a timer; honor it.
- Naming the discomfort ("I notice we're avoiding the budget conversation").
- Closing every workshop with: decisions made, decisions deferred, owners, dates.
30/60/90 Day Plans
The 30/60/90 plan is the inception artifact for execution. Every project needs one; every new hire needs their own.
Standard Shape
| Phase | Theme | Outcomes |
|---|---|---|
| Days 0–30 | Listen & Learn | Map systems, build relationships, ship a small visible win |
| Days 31–60 | Diagnose & Plan | Identify 2–3 strategic levers; propose plan; align stakeholders |
| Days 61–90 | Execute & Demonstrate | Ship first major milestone; demonstrate trajectory |
For a New Project (the Lead's plan)
Inception, hiring, foundation
Complete inception workshop. Draft Engineering Brief. Initial RFC for architecture. Set up CI/CD scaffolding. Hire / onboard first engineers.
End-to-end thin slice
Ship the steel thread — one user flow through every layer (auth → fetch → render → submit → persist). Validates architecture; produces real estimates.
Expand from the thread
Layer in features around the steel thread. Internal alpha by day 75. External beta by day 90. Reviewed against the success metrics.
For a New Hire
- Days 0–30: Ship one small PR by end of week 1. Complete onboarding doc with feedback. Map the codebase. 1:1 with 8–10 cross-functional partners.
- Days 31–60: Own a small feature end-to-end. Run a code review for a peer. Propose one improvement to a process.
- Days 61–90: Lead a medium feature. Mentor an earlier-career engineer. Demonstrate independent technical judgment in design discussions.
Reference: Michael Watkins — The First 90 Days
Influence Without Authority
A Lead has positional authority over zero people they need to influence — designers, PMs, backend leads, infra. You influence via reputation, evidence, and well-told stories.
The Six Sources of Influence
From Influencer (Patterson et al.). Influence comes from:
- Personal — motivation: connect what they need to what you want.
- Personal — ability: teach them to do what you need (don't assume they can).
- Social — motivation: peer norms, public commitments.
- Social — ability: coalitions, allies, sponsors.
- Structural — motivation: incentives, recognition.
- Structural — ability: remove obstacles; design the path.
Tactics That Work
- Write the doc first. A clear written proposal is harder to argue against than a verbal pitch.
- Bring data, not opinion. "Our p95 LCP is 4.2s" beats "I think we're slow."
- Pre-wire decisions. Have 1:1 conversations with key stakeholders before the meeting where the decision is made. Surface objections privately.
- Frame in their language. Talk to PM in business outcomes. Talk to security in threat models. Talk to design in UX impact.
- Trade favors. Help others on their roadmap items; ask for help when you need it.
- Make their job easier. If you can hand a stakeholder a ready-to-approve doc instead of a question, they'll say yes.
- Make the path of least resistance the path you want. Defaults matter — make the right thing easy.
Tactics That Backfire
- Escalating to a manager before trying peer dialogue.
- Being right but condescending.
- Refusing to compromise on small things — burns credit for the big ones.
- Treating disagreement as personal opposition.
- Ignoring people you think are wrong instead of engaging them.
The "Disagree and Commit" Pattern
Used at Amazon, Anthropic, Stripe. When a decision is made you don't agree with: voice the disagreement clearly once; if you lose the argument, commit fully to execution. Don't undermine the decision behind closed doors. Reference: Amazon Leadership Principles — Have Backbone; Disagree and Commit
The Art of the First Week
Whether you're a new Lead joining a team or a returning Lead on a new project, week one is disproportionately important. People form lasting impressions in the first 7–10 days.
The First-Week Playbook
- Listen 80%, talk 20%. Resist the urge to demonstrate competence.
- Book 1:1s with every engineer on the team. 30 minutes each; ask: what's working, what's broken, what would you change?
- 1:1 with each cross-functional partner. Same questions, different lens.
- Ship something small. Even a documentation fix or a CI improvement. Signals you're a builder, not just a talker.
- Read everything. Engineering briefs, ADRs, runbooks, RFCs, recent postmortems. Three days of reading saves three months of confusion.
- Resist the rewrite urge. Whatever feels wrong, write it down — but don't act on it for 90 days.
- Set explicit expectations. Tell your team how you work, your office hours, how to escalate, what kinds of decisions you'll defer to them.
- Find your sponsor + your skip-level mentor. Build the relationships you'll need before you need them.
What NOT to Do in Week One
- Propose a major reorg / migration / tool change.
- Dismiss the existing architecture publicly.
- Promise outcomes you don't yet understand the cost of.
- Skip 1:1s "because you're busy onboarding."
- Take credit for any pre-existing work in flight.
The "Listening Tour" Questions
- What does success look like for you in this role / project?
- What's the smartest thing the team did in the last year?
- What's the dumbest thing the team did in the last year?
- If you could change one process, what would it be?
- Who on the team is underutilized / under-recognized?
- Who's a flight risk?
- What should I read first?
- What's the elephant in the room nobody talks about?
- How do you like to receive feedback?
- What's the best thing I could do for you in my first 90 days?
Reference: Will Larson — Onboarding Engineering Leadership · Pragmatic Engineer — First 90 Days
Common Inception Anti-Patterns
Patterns to recognize — in yourself and others — before they bite.
| Anti-pattern | What it looks like | Fix |
|---|---|---|
| Solutioning before problem | Team is debating React Server Components in week 1; no one has met a user. | Hard rule: no architecture before the brief is approved. |
| Boil the ocean | Scope keeps expanding; "while we're at it…" added 5 times. | Re-read the non-goals section weekly. Add any new ask to non-goals or kill it. |
| Phantom consensus | Nobody disagrees in the meeting; everyone has reservations privately. | 1:1 pre-wiring. Explicit "fist of five" voting. Designate a devil's advocate. |
| HiPPO (Highest Paid Person's Opinion) | VP weighs in; team caves immediately. | Bring data. Frame counter-arguments as "let me understand the constraint" not "you're wrong." |
| Magical estimates | "It'll take 6 weeks." How? Why 6? Nobody knows. | Insist on range + assumptions. Reference-class forecast. |
| Stakeholder absenteeism | Security / Legal / Data not in the room until pre-launch; they block everything. | Invite them in week 1. Even if they only listen, they're not surprised later. |
| Sequential discovery + delivery | "We'll finish discovery, then build" — discovery has no end date. | Time-box discovery. Continuous discovery throughout build. |
| Skipping the brief | "We're agile, we don't need docs." Three months later, nobody remembers the original goal. | Even a 1-page brief is better than zero. Make it lightweight, not bureaucratic. |
| Optimism cascade | Each team padded their estimate, but together they still overshoot. | Pre-mortem. Steel-thread first. Track velocity. |
| Solution dogmatism | "We always do X" — without checking if X fits this problem. | Force a "why not the alternative?" section in the brief. |
| The hero PM/Lead | One person holds all context; team is rudderless without them. | Document everything. Force decisions to be written, not verbal. |
| "Plan once, ship once" | The brief is treated as gospel after week 4; reality has shifted but nobody updates it. | Weekly brief check: any non-goal moved? Any assumption broken? Any risk activated? |
Hard Questions Bank — Inception-Specific
Practice Exercises — Run Your Own Inception
Reading about inception teaches the patterns; running one builds the muscle. Pick three exercises and complete them before declaring yourself fluent.
Exercise A · The 90-Minute Solo Inception
- Pick a real or imagined product (e.g., "an offline-first notes app for journalists in conflict zones").
- Set a 90-minute timer. Use this structure:
- 15 min: elevator pitch, 3 personas, top 5 jobs-to-be-done
- 15 min: NSM + 3 driver metrics
- 20 min: top 10 features brainstormed; RICE-scored
- 15 min: 5 non-goals
- 15 min: top 5 risks with mitigations
- 10 min: write the 1-page Engineering Brief
- Put it aside for 48 hours. Re-read and revise.
- Show a peer; ask for the 3 most-questioned assumptions.
Exercise B · The 5-Whys Drill
- List the last 5 feature requests you received from PM/stakeholders.
- For each, do the 5 Whys to dig past the surface ask.
- Reframe each request as the underlying problem statement.
- Identify which of your reframings the original requester would agree with — and which would surprise them.
Exercise C · The Pre-Mortem on a Real Project
- Pick your current biggest project.
- Write 10 reasons it could fail catastrophically.
- Score each by probability × impact.
- For the top 3, write a mitigation plan.
- Discuss with your manager / PM. Did they have any in mind that you missed?
Exercise D · Stakeholder Map for a Real Project
- List every person who can affect or is affected by your current project.
- Plot each on the Power × Interest grid.
- For each high-power person, audit: when did you last 1:1 with them? What's your shared context?
- Schedule the missing conversations this week.
Exercise E · Write an ADR Retroactively
- Pick a technical decision your team made in the last 12 months (framework choice, library swap, architecture pattern).
- Write the ADR retroactively: context, decision, alternatives considered, consequences.
- Share with the team. Often surprises emerge: people remember the rationale differently.
- If the ADR feels weak — the original decision lacked rigor. Make new decisions to a higher standard.
Exercise F · Run an Event Storming Mini-Session
- Pick a single user flow in your product (e.g., "user signs up and completes onboarding").
- Get a virtual whiteboard (Miro / FigJam) or sticky notes on a wall.
- Solo, write every domain event (past tense) on orange stickies — 15 minutes.
- Add actors (yellow), commands (blue), policies (purple).
- Mark hot spots (questions, contradictions) in red.
- You'll find at least 3 things you didn't realize you didn't know.
Exercise G · Build a Personal "Inception Kit"
- Create a folder of templates: Engineering Brief, ADR, RACI, Risk Register, Pre-Mortem agenda, 30/60/90 plan.
- Each template should be 1 file, <1 page, ready to copy-paste.
- Store in your dotfiles / personal Notion / GitHub repo.
- Pull from this kit on day 1 of every project. Refine after each use.
Full Resource Library — Books, Courses, Talks, Articles
The exceptional Lead reads constantly. Below is the curated curriculum — pick one item from each category per quarter for sustained growth.
Frontend Masters Courses (most-relevant for Lead/Tech Lead)
Engineering Management 101
Enterprise Engineering Management
Complete Intro to Product Management
Product Design for Web Applications
Enterprise & Leadership Learning Path
Expert Learning Path — Lead/Staff Developer
Other Online Courses
The Principal Dev — Certification Masterclass
LeadDev Learning
StaffEng Guides
Digital Product Management Specialization
Essential Books
Inspired
Empowered
Continuous Discovery Habits
The Mom Test
Shape Up
Staff Engineer
The Manager's Path
An Elegant Puzzle
Team Topologies
Accelerate
How Big Things Get Done
Thinking, Fast and Slow
The First 90 Days
Measure What Matters
Influencer
Crucial Conversations
Foundational Articles & Essays
Inception — The Key to Starting a Project Right
Strategies, Stories & Design Docs
Design Docs at Google
Scaling Engineering Teams via Writing Things Down (RFCs)
Lead Development Team
Things You Should Never Do — Part I
Strangler Fig Application
Performing a Project Pre-Mortem (HBR)
The Agile Fluency Model
Mapping Risk & Impact
The Pragmatic Engineer — Project Kickoff
Onboarding Engineering Leadership
Conference Talks & Videos
How to Speak
StaffPlus Conference Talks
LeadDev Conferences
Conway's Law in Action
QCon Conference Archive
GOTO Conferences
Death by Powerpoint (and how to fix it)
The Art of Pragmatic Engineering Leadership
Podcasts
LeadDev Podcast
The Pragmatic Engineer Podcast
Soft Skills Engineering
Lenny's Podcast
The Changelog
The Stack Overflow Podcast
Newsletters Worth Subscribing
The Pragmatic Engineer
Refactoring
Engineering Leadership
The Deployed Team
Lenny's Newsletter
Working in Content
Communities
- Rands Leadership Slack — invitation-based; thousands of engineering managers and leaders. Most active community for the topic.
- LeadDev Community — conference-affiliated; tracks for Staff/Lead/EM topics.
- StaffEng community — Will Larson's resource hub; comments and discussion on staff-track topics.
- r/ExperiencedDevs — anonymous candor on the harder parts of engineering leadership.
- Local LeadDev / Meetup communities — meeting in-person remains the highest-bandwidth way to learn.
The 90-Day Inception Curriculum
- Days 1–14: Read Inspired + The Mom Test + Shape Up. Watch Patrick Winston's "How to Speak."
- Days 15–28: Take Engineering Management 101 on Frontend Masters. Run Exercise A (the 90-Minute Solo Inception).
- Days 29–45: Read Team Topologies + How Big Things Get Done. Run Exercise D (Stakeholder Map) on your current project.
- Days 46–60: Read Continuous Discovery Habits. Take Complete Intro to Product Management on Frontend Masters.
- Days 61–75: Read Staff Engineer. Subscribe to Pragmatic Engineer + LeadDev + Refactoring.
- Days 76–90: Co-facilitate an inception workshop with a peer or mentor. Apply Exercises B, C, E, F to a real project.
02Tech Stack Selection
Tech stack is a 5-year decision dressed as a 2-week task. The Lead's job is to make this decision visible, justified, and reversible where possible.
2.1 The Decision Axes
| Axis | What you're optimizing for | Common answers (2026) |
|---|---|---|
| Rendering strategy | SEO, TTFB, time-to-interactive, server cost | RSC + streaming SSR (Next.js App Router, Remix/RR7), SSG (Astro), pure SPA (CRA-style with Vite — only for auth-walled apps) |
| Framework | Hireability, ecosystem, perf characteristics | React still dominant; Vue 3 strong in EU/Asia; Svelte 5 ascending; SolidJS for perf-critical; Qwik for resumability |
| Meta-framework | Routing, data, deploy story bundled | Next.js (default), Remix→React Router 7, TanStack Start, Astro (content), SvelteKit, Nuxt (Vue) |
| Language | Type safety, refactor confidence | TypeScript — non-negotiable at lead level |
| Styling | Bundle, DX, RSC compatibility | Tailwind v4, CSS Modules, vanilla-extract, Panda CSS; CSS-in-JS legacy = styled-components/emotion |
| UI primitives | Accessibility, customizability | Radix UI, React Aria (Adobe), shadcn/ui, Headless UI, Ark UI |
| State (client) | Subscriber granularity, DX | Zustand, Jotai, Redux Toolkit, XState (machines) |
| State (server) | Cache, dedup, invalidation | TanStack Query, RTK Query, Apollo (GraphQL), SWR, Relay (large scale) |
| Forms | Perf, validation, schema reuse | react-hook-form + Zod; TanStack Form; Conform (RSC-friendly) |
| Build / bundle | Cold start, HMR, prod size | Vite, Turbopack, Rspack, esbuild, Rollup (libs) |
| Test runner | Speed, ESM, watch DX | Vitest (modern), Jest (legacy stronghold), Playwright (E2E), Storybook test-runner |
| Lint / format | CI speed, rule depth | Biome (modern), ESLint flat config + Prettier (legacy), oxlint (emerging) |
| Monorepo | Code sharing, CI graph | Turborepo, Nx, pnpm workspaces + changesets, Moon, Bazel (mega-scale) |
| Deployment | Edge vs node vs static | Vercel, Cloudflare Pages/Workers, Netlify, AWS (CF+S3+Lambda@Edge), self-host (Kubernetes) |
2.2 The 9-Question Decision Framework
Borrowed from Spotify's tech-radar process and adapted for FE:
- Does it solve our actual problem? Not "is it cool" — "does the constraint exist?"
- What is the total cost of ownership over 3 years? Licensing, hosting, hiring, switching costs.
- How big is the community? Stack Overflow tag count, npm weekly downloads, GitHub contributors, conference talks last 12 months.
- What is the bus factor? One maintainer = high risk. Foundation-backed (Linux Foundation, OpenJS) = safer.
- What does the next version look like? Roadmap public? Breaking changes telegraphed?
- How does it interop with the rest of the stack? Does it force decisions in adjacent layers (Next.js forces Vercel-friendly choices)?
- What does the exit look like? Can we migrate off in 6 months if needed?
- How does it perform on our hot path? Build a tracer-bullet prototype and measure.
- Who already knows it on the team? Internal capability is a free advantage.
2.3 Anti-patterns Lead Candidates Should Articulate
- Resume-driven development: picking the technology because it's hot, not because it fits.
- Sunk-cost decisions: "we already started with X, so we must continue" — even when X is failing.
- Lowest-common-denominator: picking only what the most junior engineer already knows — caps ambition.
- "Just use whatever": the inverse of analysis paralysis. Lead candidates have opinions backed by evidence.
2.4 Hard Questions
2.5 References
03Architecture & ADRs
Architecture is the set of decisions that are expensive to reverse. A Lead documents them so the next Lead doesn't have to re-derive them.
3.1 Architecture Decision Records (ADRs)
Introduced by Michael Nygard in 2011 (canonical post). Every significant decision gets a numbered Markdown file in docs/adr/:
# ADR-0023: Adopt Module Federation for Cross-Team UI Sharing ## Status Accepted — 2026-04-10 ## Context We have 6 product squads each shipping their own React app. Shared components are copy-pasted across repos and drift. Build-time npm packages cause coordinated deploys and a 30-minute release cycle. ## Decision Adopt Module Federation (Webpack 5 / Rspack) to load shared remotes at runtime. Host the design system as a federated remote consumed by all six apps. ## Consequences + Independent deploys of design system without consumer rebuild. + Sub-second hot-swap when a fix ships. - Runtime coupling: a broken remote breaks consumers. - Shared deps (React, Router) require strict version negotiation. - New observability requirement: track remote load failures per consumer. ## Alternatives Considered - Build-time npm packages with changesets (current state): rejected — release coupling. - Web Components: rejected — interop friction with React state. - Single-spa: rejected — heavier than Module Federation for our use case. ## References - Module Federation docs: https://module-federation.io/ - Zack Jackson talks on YouTube (creator) - Our PoC results: docs/poc/module-federation-2026-Q1.md
3.2 The Frontend Architecture Layers
Modeled after the C4 model adapted for FE:
| Layer | What lives here | Key questions |
|---|---|---|
| Delivery | CDN, edge functions, DNS, TLS termination | Where does first byte come from? How is HTML cached? |
| Runtime shell | App shell, routing, layout, error boundaries | What loads before any feature code? Critical path? |
| Feature modules | Page/feature folders, route bundles | How are features isolated? Lazy loaded? Owned? |
| State & data | Server state, client state, derived state | What's cached where? Invalidation strategy? |
| Design system | Tokens, primitives, components, patterns | How are components versioned? Migrated? |
| Cross-cutting | Auth, i18n, feature flags, analytics, error tracking | How does a feature opt in/out? How is consent honored? |
| Platform & tooling | Bundler, lint, test, CI, deploy | Reproducible builds? Cache hits? Test parallelism? |
3.3 Composition Patterns at Scale
Monolith SPA
Single repo, single bundle, single deploy. Best for teams < 15 engineers. Communication is implicit (function calls). Breaks down when independent release cadence becomes necessary.
Monorepo + Modular App
One repo, many packages (Turborepo / Nx). Apps share design system and utilities at build time via workspace deps. Single deploy artifact, but contributors are isolated. Current default at most companies.
Reference: monorepo.tools · Turborepo docs · Nx mental model
Micro-Frontends — Build-Time
Each MFE published as npm package; integrating app composes them at build. Versioned via SemVer. Pros: type-safe, performant. Cons: coordinated deploys, slow release.
Micro-Frontends — Run-Time (Module Federation / Native Federation)
Remotes loaded at runtime via Webpack/Rspack Module Federation or Native Federation (Angular). Independent deploys. Shared dependency negotiation is the hard problem.
Reference: Module Federation · Cam Jackson on Micro-Frontends (Martin Fowler) · micro-frontends.org
Micro-Frontends — Edge-Side Composition (ESI / Edge-Side Includes)
HTML fragments composed at the CDN edge. Used by Spotify, Zalando. Powerful for SSR-heavy properties; complex to operate.
Reference: Zalando — Tailor architecture · ESI W3C spec
Islands Architecture
Static-first HTML with interactive "islands" hydrated independently. Astro, Fresh, Marko. Excellent for content sites where most HTML is static.
Reference: Jason Miller — Islands · Astro Islands docs
Resumability (Qwik)
Skip hydration entirely — serialize the framework state into HTML. Client picks up where server left off. Theoretical O(1) startup regardless of app size.
Reference: Qwik resumability
3.4 The Hard Architectural Trade-offs
| Trade-off | One side | Other side |
|---|---|---|
| Independence vs Coherence | MFEs let teams ship independently | Users see inconsistent UX; shared deps fragment |
| Edge vs Origin | Edge = low latency, cheap, geo-local | Origin = full Node runtime, easier debugging |
| RSC vs SSR vs CSR | RSC = smaller JS, server data fetch | RSC = harder to reason about, ecosystem still maturing |
| Monorepo vs Polyrepo | Mono = atomic refactor, shared tooling | Poly = isolated CI, smaller blast radius |
| Run-time MFE vs Build-time | Run-time = independent deploy | Build-time = type safety, smaller risk |
| Custom design system vs adopt | Custom = brand control | Adopt (Radix/Aria) = cheaper, better a11y |
3.5 Hard Questions
/checkout, /dashboard). (3) Shell layer: a thin orchestrator owning navigation, global notifications, and cross-squad communication via a typed event bus. Discuss: how do you enforce visual consistency? (visual-regression tests on shared components, Chromatic baseline shared across squads, design-token contract tests). How do you handle independent React versions? (React 19 forward-compatible singletons via Module Federation shared scope OR each MFE owns its React via Web Components — discuss trade-offs). Cite Spotify Backstage as a precedent for the platform pattern.@module-federation/typescript-plugin or contracts via OpenAPI-like schema. (3) Independent versioning paradox — if Remote A and Remote B both depend on a shared lib at different majors, the host has to pick one. (4) Observability — when a remote fails, the host needs a fallback boundary per remote. (5) Performance — every remote is an extra HTTP request; prefetch on idle, share the React chunk via the host. (6) Security — remotes execute JS in your origin; subresource integrity is impossible because you don't know the hash until runtime. Often you add a remote allowlist.3.6 References
04Foundation Setup — Day 1 to Week 4
The platform decisions made before any feature ships will be inherited by 100 future engineers. A Lead invests in foundation as if onboarding the team they don't have yet.
4.1 The Day-One Checklist
- Repo created; default branch protection on; required reviewers configured.
- Conventional commits enforced via
commitlint. - Node version pinned (
.nvmrc+enginesfield) and reproduced in CI. - Package manager pinned (
packageManagerfield inpackage.json— Node 16.9+). - TypeScript with
strict: true;noUncheckedIndexedAccess,exactOptionalPropertyTypeson. - Linter + formatter: Biome OR ESLint flat config + Prettier; rules committed.
- Pre-commit hooks: Husky + lint-staged (or simple-git-hooks).
- CI pipeline running on PRs from minute one — even if it just lints.
- Renovate or Dependabot configured for dependency PRs.
- License file, README, CODEOWNERS, CONTRIBUTING.md.
- Security:
npm auditin CI, Snyk/Socket integration, SBOM generation. - Editor config:
.editorconfig, recommended VS Code extensions in.vscode/extensions.json.
4.2 TypeScript Configuration (Production-Grade)
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2023", "DOM", "DOM.Iterable"],
"module": "ESNext",
"moduleResolution": "Bundler",
"jsx": "react-jsx",
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"noImplicitOverride": true,
"noFallthroughCasesInSwitch": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"isolatedModules": true,
"verbatimModuleSyntax": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true,
"incremental": true,
"paths": {
"@app/*": ["./src/app/*"],
"@ui/*": ["./src/ui/*"]
}
}
}
4.3 CI Pipeline Anatomy
| Stage | Tools | Target time |
|---|---|---|
| Install | pnpm + frozen lockfile + actions/cache | < 30s |
| Lint & Type-check | Biome / ESLint + tsc --noEmit | < 45s |
| Unit tests | Vitest with sharding | < 90s |
| Build | Vite / Turbopack with cache | < 2min |
| E2E (smoke) | Playwright against built artifact | < 3min |
| Visual regression | Chromatic / Playwright snapshots | parallel to E2E |
| Bundle analysis | statoscope / size-limit / bundlewatch | < 30s |
| Security | npm audit + Snyk + SAST (Semgrep) | < 60s |
| Deploy preview | Vercel / Netlify / custom S3+CF | < 90s |
Target: PR-to-feedback < 5 minutes. Anything slower kills iteration velocity.
4.4 Hard Questions
~/.pnpm-store keyed by lockfile hash. (2) Test parallelism — Vitest --shard across 4–8 runners; Playwright workers + sharding. (3) Affected-only — Turborepo/Nx affected commands; only test what changed. (4) Build cache — Turborepo remote cache to S3 or Vercel; cache hit rate > 80% target. (5) Drop unnecessary steps from PR runs — visual regression only on main, security scan nightly. (6) Container reuse — buildx / Docker layer cache. (7) Hardware — bigger runners cost less than engineer wait time. Set a budget (5 min PR), instrument adherence, alert on regression.4.5 References
05Design System & UI Foundation
A design system is product infrastructure — not "a folder of components." A Lead treats it with the same rigor as an API.
5.1 The Layered Token Architecture
The mature pattern adopted by Material 3, Adobe Spectrum, Carbon, and Polaris:
| Tier | Example | Owner |
|---|---|---|
| Reference / Primitive | color.blue.500 = #2563eb | Brand / Design |
| System / Semantic | color.action.primary = {color.blue.500} | Design System team |
| Component | button.primary.bg = {color.action.primary} | Design System team |
| Theme | Dark mode override of system tokens | Design System team |
Tools: Style Dictionary, Tokens Studio (Figma), Specify, W3C Design Tokens spec.
5.2 Component Architecture Patterns
Headless / Behavior + Presentation Split
Modern best-practice. Headless libraries (Radix UI, React Aria, Headless UI, Ark UI) own behavior, accessibility, keyboard, focus. Your team owns visuals. The split lets the design system evolve visually without re-implementing accessibility every time.
// Headless + styled (shadcn/ui style):
import * as Dialog from '@radix-ui/react-dialog';
export function ConfirmDialog({ children, ...props }) {
return (
<Dialog.Root {...props}>
<Dialog.Overlay className="overlay" />
<Dialog.Content className="content">
{children}
<Dialog.Close className="close" />
</Dialog.Content>
</Dialog.Root>
);
}
Compound Components
Parent component coordinates child state via Context. Used by Reach UI, Radix, Headless UI, and any modern Tabs/Accordion/Select.
Polymorphic Components (“as” prop)
Allow consumer to render the component as any HTML element. Hard to type correctly — see Ben Ilegbodu — polymorphic components in TS. React Aria uses a different pattern (slots).
Slot Pattern
Allow the parent to pass an element rather than children, useful for swapping the underlying element while keeping props/behavior. Implemented in Radix via asChild.
5.3 Storybook in Production
- Every component has stories that double as documentation and as tests via interaction testing.
- Visual regression via Chromatic, Percy, or Playwright snapshots gated on PR.
- a11y addon running axe-core on every story.
- Component testing mode for running stories as test fixtures.
- Story-driven design reviews — designers approve in Chromatic UI before merge.
5.4 Hard Questions
asChild, slot pattern), not a fork. (3) Genuinely different component: introduce a sibling primitive with shared tokens; don't pretend it's the same. Never silently fork — it dilutes the system. Document the decision in an ADR.5.5 References
06State Strategy
"What state library should we use?" is the wrong question. "What kinds of state exist in our app, and where does each live?" is the right one.
6.1 The Four Kinds of State
| Kind | Lives in | Tools |
|---|---|---|
| Server state | Cache reflecting a remote source of truth | TanStack Query, RTK Query, Apollo, SWR, Relay |
| URL state | The URL (query params, path, hash) | Native router, TanStack Router (type-safe), nuqs |
| Form state | Local to a form's lifecycle | react-hook-form, TanStack Form, Conform |
| Client UI state | App-local ephemeral data | useState, useReducer, Zustand, Jotai, Redux Toolkit, XState |
6.2 Client-State Library Comparison
| Library | Model | Strengths | Weakness |
|---|---|---|---|
| useState / useReducer | Local | Built-in, zero deps | No sharing across distant components |
| Context | Tree-scoped | Built-in, simple | Re-renders all consumers; no slice selection |
| Zustand | External store + hook | Tiny, fast, selectors, devtools | Hands-off — discipline required |
| Jotai | Atomic primitives | Granular subscriptions, Suspense-native | Many atoms = many references to track |
| Redux Toolkit | Flux + slices + RTK Query | Mature, devtools, time-travel, ecosystem | Verbose; cognitive overhead for small apps |
| XState | Statecharts | Explicit state, impossible-state-prevention, visualizer | Learning curve; verbose |
| Valtio / MobX | Proxy/observable | Mutation-style ergonomics | Magic; reactivity tracking is implicit |
| Signals (proposal / Solid / Preact) | Reactive primitive | O(1) updates, no diffing | Not yet native in React |
6.3 The Cache-Invalidation Question
Phil Karlton: "There are only two hard things in Computer Science: cache invalidation and naming things." TanStack Query won the FE space because it answered this:
- Stale time — how long data is considered fresh; no refetch within this window.
- Cache time / gcTime — how long unused data stays before garbage collection.
- Refetch on window focus / reconnect / mount — automatic background refresh policies.
- Optimistic updates with rollback on failure.
- Query keys as cache keys — hierarchy enables targeted invalidation:
['user', userId, 'posts']. - Mutations + automatic invalidation — declarative dependencies.
6.4 Hard Questions
6.5 References
07Data Layer & Caching
The data layer determines perceived performance more than any single rendering optimization. Network latency is your dominant cost.
7.1 REST vs GraphQL vs tRPC vs RPC
| Pattern | Best when | Watch out for |
|---|---|---|
| REST + OpenAPI | Stable resource model; many consumers; CDN caching matters | Over-fetching; versioning sprawl |
| GraphQL | Many consumers with different shape needs; federated backends | Caching complexity; N+1; payload-size bloat from defaults |
| tRPC | Mono-repo TS full-stack with single FE/BE owner | Couples FE to BE TS types — no decoupled evolution |
| gRPC-Web / Connect | Polyglot backends with strict schemas | Browser proxy required (gRPC); tooling friction |
| Server Actions (RSC) | Single-app full-stack with Next.js / similar | Coupling; observability gap; harder to test outside framework |
7.2 The Cache Hierarchy
A modern FE has at least 4 caches on the path from server to user:
- Browser HTTP cache — governed by
Cache-Control,ETag,Last-Modified. - Service Worker cache — programmable via the Cache API and Workbox.
- In-memory client cache — TanStack Query / Apollo normalized cache.
- CDN cache — Cloudflare, Fastly, Akamai; tags, surrogate keys, soft-purge.
Lead-level understanding: each layer has different invalidation primitives. The challenge is consistent purge semantics across them. Stripe and Shopify use surrogate keys + tag-based purge to cascade invalidations.
7.3 HTTP Cache Headers — The Set That Matters
Cache-Control: public, max-age=31536000, immutable # versioned static assets Cache-Control: private, no-cache # HTML for authed pages Cache-Control: public, s-maxage=60, stale-while-revalidate=600 # SWR pattern at CDN ETag: "abc123" Vary: Accept-Encoding, Accept-Language, Cookie
Reference: MDN HTTP caching · RFC 9111 · web.dev — SWR.
7.4 The N+1 Anti-pattern (Client Side)
// ❌ N+1: fires N requests sequentially
const users = await fetch('/api/users').then(r => r.json());
for (const u of users) {
u.posts = await fetch(`/api/users/${u.id}/posts`).then(r => r.json());
}
// ✅ Batch + parallel
const users = await fetch('/api/users').then(r => r.json());
const postsByUser = await Promise.all(
users.map(u => fetch(`/api/users/${u.id}/posts`).then(r => r.json()))
);
users.forEach((u, i) => (u.posts = postsByUser[i]));
// ✅✅ Batch endpoint (best)
const users = await fetch('/api/users?include=posts').then(r => r.json());
7.5 Hard Questions
onMutate, cancel any in-flight refetch (queryClient.cancelQueries), snapshot the current cache value, then setQueryData with the optimistic value. Return the snapshot from onMutate as context. In onError, restore the snapshot via setQueryData. In onSettled, invalidate queries to re-sync with server truth. Edge cases: concurrent mutations (you may need a mutation queue), partial failure where the server applies some but not all changes (mutation idempotency / server-side compensating actions), stale snapshot if the user navigated away (cleanup in onMutate's cancelQueries). Reference: TanStack Query — optimistic updates.s-maxage=300, stale-while-revalidate=3600 — serve stale while fetching fresh; price-update job purges surrogate key product-{id} on price change. Service worker: stale-while-revalidate strategy keyed on path. In-memory (Query): staleTime: 5 minutes, refetch on focus. Manual sync: on price-change event (WebSocket / SSE), client invalidates the specific query key, which propagates to UI. Discuss tag-based purge (Fastly Surrogate-Keys, Cloudflare Cache Tags Enterprise) — essential at scale. Mention: Fastly Surrogate-Key.7.6 References
08Authentication & Identity
Auth is where security and UX collide. A Lead FE knows the protocols deeply enough to push back on bad backend designs.
8.1 Standards You Must Know
| Standard | What it is | When |
|---|---|---|
| OAuth 2.0 | Delegated authorization framework | Third-party app accesses user data on user's behalf |
| OIDC (OpenID Connect) | Identity layer on top of OAuth 2.0; adds ID tokens | Login / SSO |
| OAuth 2.1 | Consolidation of best practices; PKCE mandatory | Modern default |
| SAML | Older enterprise SSO via signed XML | Enterprise B2B |
| WebAuthn / Passkeys | Public-key crypto in the browser; phishing-proof | Modern auth without passwords |
| FedCM | Browser-native federated identity (Chrome+) | Replacing third-party cookies for SSO |
| SCIM | User provisioning across SaaS | Enterprise admin flows |
| OPA / Cedar / OpenFGA | Authorization decision engines | Fine-grained authz |
8.2 The OAuth 2.1 Flow (Authorization Code + PKCE)
- Client generates a random
code_verifier, derivescode_challenge = SHA256(verifier). - Redirect to
/authorize?response_type=code&client_id&redirect_uri&scope&state&code_challenge&code_challenge_method=S256. - User authenticates; provider redirects to
redirect_uri?code=xxx&state=yyy. - Client POSTs
code + code_verifierto/token; receivesaccess_token,id_token(OIDC), mayberefresh_token. - Client calls APIs with
Authorization: Bearer <access_token>.
8.3 Token Storage — The Hard Decisions
| Storage | Risk | Verdict |
|---|---|---|
| localStorage | XSS reads it instantly. Avoid for access tokens. | ❌ for sensitive tokens |
| sessionStorage | Same XSS risk; cleared per tab | ❌ for sensitive tokens |
| HttpOnly cookie | JS can't read it. CSRF risk — mitigate with SameSite=Lax + CSRF tokens for mutating requests | ✅ for session |
| In-memory only | Lost on reload; requires silent re-auth via refresh cookie | ✅ pattern: short-lived access in memory + long-lived refresh in HttpOnly cookie |
| Web Worker | JS can hold token in worker scope; harder for XSS to exfiltrate | ⚠️ defense in depth, not silver bullet |
8.4 WebAuthn / Passkeys — The Future
Passkeys are FIDO2 credentials synced via platform cloud (iCloud Keychain, Google Password Manager, 1Password). UX: tap fingerprint, in. Security: private key never leaves device, public key on server; phishing-proof because the key is bound to the origin.
// Register a passkey
const credential = await navigator.credentials.create({
publicKey: {
challenge: serverChallenge, // server-provided random
rp: { id: 'example.com', name: 'Example' },
user: { id: userId, name: email, displayName: name },
pubKeyCredParams: [{ alg: -7, type: 'public-key' }],
authenticatorSelection: { residentKey: 'required', userVerification: 'preferred' },
}
});
// Send credential.response to server for verification
8.5 Authorization (AuthZ) — Not Auth (AuthN)
Patterns:
- RBAC — Role-Based Access Control. Roles → permissions. Simple, scales poorly with edge cases.
- ABAC — Attribute-Based. Decisions on user/resource attributes. Flexible.
- ReBAC — Relationship-Based. Google Zanzibar paper; OpenFGA, SpiceDB, Permify. Best for "user can edit doc because they're in group that owns folder."
8.6 Hard Questions
state param protects against CSRF in the redirect, while nonce in OIDC protects against ID token replay.8.7 References
09Routing
Routing is the public API of your app. URLs are forever; design them like they will be.
9.1 URL Design Principles
- Resource-oriented nouns:
/users/:id/projects/:slug, not/getUserProject. - Hackable — users can guess parent routes by truncating segments.
- Stable — set up redirects for any breaking change. Search engines and bookmarks live forever.
- Sharable — state critical to reproducing the view is in the URL (filters, sort, page, tab).
- Localizable — locale either in subdomain (
en.example.com), path (/en/products), or via Accept-Language. Decide consciously. - Type-safe at the boundary — runtime validate params (Zod) at the loader.
9.2 Router Landscape
| Router | Best for |
|---|---|
| React Router v7 (merged with Remix) | Modern data-router; framework or library mode; loaders/actions; SSR or SPA |
| Next.js App Router | RSC-native; file-system routing; layouts; parallel + intercepting routes |
| TanStack Router | Full type-safety from path params to search params; framework-agnostic |
| Wouter | Tiny — for embed widgets, micro-FEs |
| Reach Router / Hash router | Legacy; avoid for new work |
9.3 Next.js App Router — The Patterns to Know
- Nested layouts — shared shell across child routes; preserved on navigation.
- Loading.js / Suspense — instant loading UI while data streams.
- Error.js — per-segment error boundary.
- Parallel routes — render multiple slots simultaneously (dashboard with sidebar + content).
- Intercepting routes — modal overlays that survive refresh (Instagram-style photo modal).
- Route groups — folder-as-segment escape:
(marketing)doesn't add a URL segment. - Dynamic segments + generateStaticParams — SSG for known paths, fallback for unknown.
9.4 Hard Questions
?status=open&assignee=alice&sort=-created&cursor=xyz. How do you keep this maintainable??tab=billing if a path segment is more semantic. (6) Bookmarkable + back-button correct: every state change updates history meaningfully. Reference: nuqs for ergonomic typed search params./photo/123 that overlays the feed. Refresh should still show the modal but with feed underneath. How?@modal slot in the layout; (.)photo/[id] intercepting route renders the modal when navigating from the feed (client-side); when the URL is loaded fresh, the regular /photo/[id] route renders a full page. Same URL, two render trees depending on entry. Reference: Next.js intercepting routes.9.5 References
10Forms & Validation
Forms are where 80% of conversion lives. Lead candidates know forms cold.
10.1 Library Picks (2026)
| Library | Use |
|---|---|
| react-hook-form + Zod (resolver) | The de-facto default. Uncontrolled-by-default, minimal re-renders, schema validation. |
| TanStack Form | Framework-agnostic, type-safe end-to-end; rising. |
| Conform | Progressive enhancement; works with native forms + RSC server actions; Remix/Next compatible. |
| Formik | Legacy; superseded for new work. |
10.2 Validation Schemas
- Zod — most popular; great DX; chained API.
- Valibot — tree-shakable, smaller bundle (a fraction of Zod).
- ArkType — fastest at runtime; TS-syntax inspired DSL.
- Standard Schema — emerging interop spec so libraries can target multiple validators.
10.3 The Hard Form Problems
- Async validation — username availability, debounced calls, race condition handling (latest-only wins).
- Cross-field rules — confirm password matches, end date after start date.
- Conditional fields — schema that changes based on prior selections;
z.discriminatedUnion. - Multi-step wizards — partial submit + draft persistence; URL state per step.
- Server-returned validation errors — surface per field with translated messages; 422 with field map.
- Optimistic + offline submission — local-first persist; sync queue; conflict resolution.
- Accessible errors —
aria-describedby,aria-invalid, error list with focus management, screen reader announcement.
10.4 Hard Questions
/checkout/shipping, /checkout/payment, /checkout/review). Each step owns its schema; previous-step state persisted server-side (cart record). Progressive enhancement: each step is a native <form action> with server action; JS-on adds inline validation + optimistic UX. Conform or Remix-style data router fits. Validation runs both client-side (DX) and server-side (security — never trust client). Analytics: per-step funnel events, error events with field name, abandonment events on unmount. Accessibility: focus to first error on validation fail; announce errors via aria-live. PCI: tokenize card via iframe (Stripe Elements) so card data never touches your server. Recovery: pre-fill from session on return; clear on success.onBlur validation mode. (5) Inline functions in child props defeating React.memo. (6) Consider field-level Suspense for async validation. After fix, set perf budget: typing latency < 16ms p95.11Internationalization (i18n & l10n)
i18n done badly is impossible to fix later. Done well, it's invisible.
11.1 The Vocabulary
| Term | Meaning |
|---|---|
| i18n (Internationalization) | Making the app capable of supporting multiple locales |
| l10n (Localization) | Actual translation/adaptation for a specific locale |
| g11n (Globalization) | i18n + l10n + cultural adaptation |
| ICU MessageFormat | Standard for plurals, gender, select, nested arguments |
| BCP 47 | Language tag spec (en-US, zh-Hant-HK) |
| CLDR | Unicode Common Locale Data Repository — formats, plurals, calendars |
| RTL | Right-to-left scripts: Arabic, Hebrew, Persian, Urdu |
11.2 The Common Mistakes
- String concatenation —
"You have " + n + " items"breaks for word order in other languages. Use ICU MessageFormat. - Hard-coded plural rules — many languages have more than 2 plural forms (Arabic has 6, Russian 4). Use CLDR plural rules.
- Date / number formatting with manual code — use
Intl.DateTimeFormat,Intl.NumberFormat,Intl.RelativeTimeFormat,Intl.ListFormat. - Pixel-based layouts — Japanese text is shorter, German much longer; layouts must flex.
- Forgetting RTL — use logical CSS properties (
margin-inline-start,padding-block-end). - Sortable strings — use
Intl.Collator, neverString.prototype.localeComparewithout options. - String IDs as English — use stable hashes/IDs so source English can change without breaking IDs in translation memory.
11.3 Modern Tools
- Lingui — extracts strings via Babel/SWC plugin; ICU MessageFormat support.
- FormatJS / react-intl — long-time standard.
- i18next — popular, framework-agnostic.
- next-intl — Next.js-native.
- Crowdin / Lokalise / Phrase — TMS for translator collaboration.
11.4 Hard Questions
no-literal-strings); audit every date/number/currency format (manual code is the killer); audit every layout that won't flex; identify RTL deltas. Set up TMS pipeline: extract → upload to Crowdin → translate → download → bundle. Pick library (Lingui or react-intl). Implement RTL via dir="rtl" on html + logical CSS properties + a Tailwind plugin if applicable. Test process: pseudo-localize to expand strings to 130% (catch overflows); visual-regression per locale in Storybook. Critical path: get the foundation right in 2 weeks (extraction + library + RTL); translation in parallel; QA in the last 2 weeks. Reference: Smashing — i18n in React · RTL Styling 101.12Testing Pyramid & Quality Strategy
A Lead designs the test strategy — not just writes tests. The shape of the test portfolio is a leadership artifact.
12.1 The Modern Test Portfolio (post-Trophy / post-Pyramid)
Kent C. Dodds proposed the "Testing Trophy" — emphasizing integration over unit. Honeycomb / Spotify use a different shape. The truth: shape depends on product. Below is a sane default for a modern web product.
| Layer | Tools | What it covers | ~% |
|---|---|---|---|
| Static analysis | TypeScript, ESLint, Biome, Semgrep | Type errors, lint rules, security patterns | — |
| Unit | Vitest, Jest | Pure functions, hooks (with renderHook), reducers, utils | 30% |
| Component / Integration | React Testing Library + MSW | Component behaviour with realistic data fetching | 50% |
| Visual regression | Chromatic, Playwright snapshots, Percy | Pixel/structural changes per Storybook story | — |
| Contract tests | Pact, MSW handlers as contract | FE vs BE schema compatibility | — |
| E2E | Playwright, Cypress | Critical user flows on real browser | 15% |
| Accessibility | axe-core, Pa11y, manual SR testing | WCAG conformance | — |
| Performance | Lighthouse CI, WebPageTest API, Calibre | Perf budgets enforced on PR | — |
| Load / chaos | k6, Gatling, Toxiproxy (network chaos) | Behaviour under adverse conditions | 5% |
12.2 The Test-Strategy Question
Decisions a Lead makes explicitly:
- What flakiness rate is acceptable? Typical target: < 1% per E2E. Above that, automation becomes a tax.
- Who fixes flakes? "Last green pipeline" owner or a dedicated quality engineer.
- What's mocked vs real? Default: mock network at MSW boundary, run real timers, real fetch. Mock 3rd-party SDKs at module boundary.
- What's covered by E2E vs integration? Rule: E2E for cross-team contracts (auth → product → checkout); integration for within-team.
- How is test data managed? Test factories (e.g.,
fishery); avoid hand-rolling fixtures. - How are flaky tests quarantined? Auto-quarantine after N flakes; assign ticket to owner; remove from blocking after fix.
12.3 Hard Questions
Date globally. (2) Locale — number / date formatting differs; pin process.env.LANG. (3) Test isolation — module mocks leaking; resetMocks + restoreMocks per test. (4) Order dependency — Vitest's --shuffle catches; same with Jest. (5) CI slowness — race condition only manifests under load. (6) Snapshot diffs for environment-dependent output (file paths, port numbers). (7) Network — flake from real network calls; MSW everywhere. Investigate by capturing CI trace artifact; reproduce by running the same Docker image locally.12.4 References
13Performance Engineering
Lead-level perf is not "make Lighthouse green." It's "set budgets, instrument them, defend them, and explain the trade-offs."
13.1 Core Web Vitals (2026 state)
| Metric | What | Good (p75) | Poor |
|---|---|---|---|
| LCP | Largest contentful paint | < 2.5s | > 4.0s |
| INP | Interaction to Next Paint (replaces FID March 2024) | < 200ms | > 500ms |
| CLS | Cumulative layout shift | < 0.1 | > 0.25 |
| FCP | First contentful paint | < 1.8s | > 3.0s |
| TTFB | Time to first byte | < 0.8s | > 1.8s |
| TBT (lab only) | Total blocking time | < 200ms | > 600ms |
13.2 Performance Budgets
A Lead defines budgets per route, not per app:
# perf-budget.yaml
routes:
/:
js: 170kb
css: 30kb
lcp_p75: 2.0s
inp_p75: 150ms
/product/[id]:
js: 220kb
images: 600kb
lcp_p75: 2.5s
/admin/*:
js: 500kb # power user, larger budget acceptable
lcp_p75: 4.0s
Enforce via Lighthouse CI, size-limit, bundlewatch, or Calibre on every PR; block merge if violated.
13.3 The Perf Diagnostic Playbook
- Capture: WebPageTest from a representative location with throttled connection (Slow 4G, Moto G Power); record filmstrip + waterfall + Lighthouse trace.
- Classify: which CWV is failing? LCP → asset on critical path. INP → main-thread work. CLS → layout instability.
- Diagnose: open trace in DevTools Performance; look at long tasks, layout shift regions, LCP element selection.
- Hypothesize: one change, predict impact.
- Implement & measure: A/B in production via feature flag, or controlled lab measurement at minimum.
- Lock it in: add a budget assertion so regression breaks CI.
13.4 LCP Playbook
- Identify LCP element (DevTools surface; PerformanceObserver in code).
- If image:
fetchpriority="high", AVIF/WebP, responsivesrcset, preload hint, no lazy loading for above-fold. - If text:
font-display: swap; preload critical fonts; self-host (Google Fonts CDN adds DNS + TLS hops). - Reduce render-blocking CSS: inline critical, async load rest.
- Defer non-critical JS; code-split aggressively.
- Improve TTFB: edge SSR or static; cache HTML at CDN.
- 103 Early Hints for known critical resources.
13.5 INP Playbook
- Find long tasks > 50ms via Long Animation Frames API (replaces Long Tasks).
- Yield to the main thread:
scheduler.yield(),requestIdleCallback, React'suseTransition. - Virtualize long lists (TanStack Virtual, react-window).
- Memoize expensive recomputations; React Compiler does this automatically.
- Move heavy work to Web Workers (Comlink for ergonomic RPC).
- Avoid synchronous reflow in event handlers (read all then write all).
13.6 CLS Playbook
- Always set width/height on images and embeds OR
aspect-ratio. - Reserve space for ads, banners, dynamically inserted content.
- Animate
transform/opacityonly; never width/height/top/left for animations. - Font swap:
size-adjust,ascent-overrideon @font-face; or usefont-display: optional. - Avoid inserting DOM above existing content unless triggered by user interaction (which excludes from CLS).
13.7 Real User Monitoring (RUM)
- Use the web-vitals JS library to capture CWV in production.
- Send to a backend: SpeedCurve, Calibre, Datadog RUM, Sentry Performance, Vercel Speed Insights, your own.
- Slice by route, device, region, connection, build hash — find where regression lives.
- Alert on p75 regression of any CWV by > 10% over 24h.
13.8 Hard Questions
useMemo/useCallback are often missing where they'd help and present where they hurt (memoization itself has cost). React Compiler analyzes component code at build time and inserts memoization wherever it provably reduces re-renders without changing semantics. Result: fewer wasted renders → less main-thread work → better INP. It also enables more aggressive optimization in future React versions (selective hydration improvements, parallel rendering). Discuss: it's not a silver bullet for INP — heavy synchronous computations still need yielding, virtualization, workers. Reference: React Compiler docs.13.9 References
14Accessibility (a11y)
Accessibility is a competitive advantage hiding behind a compliance label. Lead candidates treat WCAG as a floor, not a ceiling.
14.1 The Standards Landscape (2025+)
| Standard | Scope |
|---|---|
| WCAG 2.2 (Oct 2023) | Current. 9 new criteria over 2.1 (focus appearance, dragging, target size 24×24, accessible authentication, etc.). |
| WCAG 3 (Silver) | Draft. Outcome-scored, broader scope (cognitive, mobile, AR/VR). |
| EAA (European Accessibility Act) | Enforced June 28, 2025. Applies to private-sector digital products sold in EU. |
| ADA Title III (US) | Court interpretation aligns with WCAG 2.1/2.2 AA. |
| Section 508 (US federal) | Procurement; aligns with WCAG 2.0 AA via Revised 508. |
| EN 301 549 | EU harmonized standard incorporating WCAG. |
| AODA (Ontario) | WCAG 2.0 AA mandated for large orgs. |
14.2 The Four Principles (POUR)
- Perceivable — text alternatives, captions, contrast ≥ 4.5:1 (normal text), structure conveyable in multiple ways.
- Operable — full keyboard, no time traps, no flashing > 3/s, skip links, focus visible.
- Understandable — readable language, predictable navigation, error identification and suggestion.
- Robust — works with current and future AT; valid HTML, ARIA used correctly.
14.3 ARIA — The Five Rules
- Don't use ARIA — use semantic HTML when it exists.
- Don't change native semantics — never put
role="button"on anh1. - All interactive ARIA must be keyboard-accessible.
- Don't use
role="presentation"oraria-hidden="true"on focusable elements. - Every interactive element needs an accessible name.
14.4 Focus Management — The Hard Part
- Route changes in SPAs — focus a heading or a skip-link target; announce via live region.
- Modals — trap focus inside; restore to triggering element on close; use
inertattribute on background. - Drag and drop — provide a keyboard alternative (arrow keys + space).
- Toasts / notifications —
role="status"for polite,role="alert"for assertive; don't steal focus. - Async content —
aria-live="polite"regions;aria-busy="true"while loading. - Focus visible — never
outline: nonewithout a replacement; use:focus-visiblefor keyboard-only rings.
14.5 Testing Approach
| Layer | Tool | Catches |
|---|---|---|
| Static / unit | jsx-a11y ESLint, axe-core in RTL tests | Missing alt, contrast (sometimes), misuse of ARIA |
| Story-level | @storybook/addon-a11y | Per-component automated audit |
| E2E | axe-playwright | Page-level axe scans in critical flows |
| Manual keyboard | Yourself, 5 minutes per critical flow | Focus traps, missing skip-links, broken Esc handling |
| Manual screen reader | NVDA (Windows free), VoiceOver (Mac built-in), JAWS (enterprise) | Reading order, announcement quality, ARIA misuse |
| User testing | Fable Tech Labs, Applause, internal a11y guild | Real-world friction |
14.6 Hard Questions
<select> if you can — describe the 47 platform-specific behaviors you'd otherwise re-implement (Android picker, iOS wheel, Windows dropdown). If you must custom: ARIA combobox pattern (per APG 1.2): role="combobox" on the input, aria-expanded, aria-controls="listbox-id", aria-activedescendant pointing to highlighted option. Listbox: role="listbox" + role="option" children with aria-selected. Keyboard: Up/Down navigates; Home/End jump; Type-ahead matches; Enter selects; Esc closes restoring focus. Touch: full-screen drawer on mobile is acceptable. Better: adopt Radix Select or React Aria Select — they have shipped these 47 behaviors. Reference: APG Combobox pattern.aria-label="Delete" AND a visible tooltip on hover/focus. Mention WCAG 2.5.5 (Target Size) — 24×24 minimum for WCAG 2.2, 44×44 for AAA. (3) Destructive action — confirmation pattern (dialog or undo toast); never a single click for irreversible. (4) Discuss the color choice — is delete signaled only by red? Add a label too (color-only conveying is a WCAG fail). Frame as collaboration, not policing; offer alternatives.14.7 References
15Security
A Lead FE thinks like an attacker. Every input is hostile until proven otherwise.
15.1 OWASP Top 10 (2021) — Frontend Lens
| Risk | Frontend exposure | Mitigation |
|---|---|---|
| A01 Broken Access Control | UI hides admin nav but no server enforcement | Server always re-validates; treat client as untrusted |
| A02 Cryptographic Failures | JWT in localStorage, weak hashing in client | HttpOnly cookies, no client-side crypto for secrets |
| A03 Injection (incl. XSS) | Untrusted HTML, href={input}, eval, innerHTML | Default React escape, DOMPurify, Trusted Types, CSP |
| A04 Insecure Design | Missing threat modeling on new features | STRIDE review per design doc |
| A05 Security Misconfiguration | Missing CSP, source maps in prod, exposed env | Headers audit, env hygiene, source map upload not serve |
| A06 Vulnerable Components | Stale npm deps | Snyk/Socket/Dependabot, lockfile review, SBOM |
| A07 ID & Auth Failures | Token storage, session management | BFF pattern, short-lived access tokens, MFA |
| A08 SW & Data Integrity Failures | CDN script tampering, supply-chain attacks | SRI hashes, pinned versions, Socket.dev |
| A09 Logging & Monitoring Failures | No FE error tracking, no audit log | Sentry / Datadog, redact PII |
| A10 SSRF | Mostly server; relevant if FE proxies arbitrary URLs | URL allowlist |
15.2 XSS — The Three Types
- Stored — payload saved server-side, served to others. Most dangerous.
- Reflected — payload in URL/query, executed on render.
- DOM-based — client JS writes attacker input to DOM unsanitized.
React escapes string interpolation by default. The remaining holes:
dangerouslySetInnerHTML— use DOMPurify or html-react-parser with allowlist.href={userInput}—javascript:URI is XSS. Allowlist protocols (https,http,mailto,tel).style={userInput}— CSS injection (data exfiltration viabackground-image: url(...)).- Third-party libraries that
document.writeor set innerHTML internally.
15.3 Content Security Policy (CSP)
Content-Security-Policy:
default-src 'self';
script-src 'self' 'nonce-{random}' https://www.googletagmanager.com;
style-src 'self' 'unsafe-inline';
img-src 'self' data: blob: https:;
font-src 'self' data:;
connect-src 'self' https://api.example.com https://*.sentry.io;
frame-ancestors 'none';
base-uri 'self';
form-action 'self';
upgrade-insecure-requests;
report-uri /csp-report;
report-to default;
Nonce-based CSP (random nonce per request, applied to legitimate inline scripts) is the modern default. 'unsafe-inline' for scripts is a deal-breaker — use nonces or hashes.
15.4 Trusted Types (the modern XSS firewall)
A browser API that prevents passing strings to DOM XSS sinks (innerHTML, document.write) unless wrapped in a policy-approved type. Google deployed it to reduce XSS to near-zero on their consumer products.
Content-Security-Policy: require-trusted-types-for 'script'; trusted-types my-policy
15.5 Security Headers (the full set)
| Header | What |
|---|---|
| Content-Security-Policy | Allowlist of sources for each resource type |
| Strict-Transport-Security | Force HTTPS; max-age=31536000; includeSubDomains; preload |
| X-Content-Type-Options: nosniff | Prevent MIME confusion attacks |
| X-Frame-Options: DENY | Clickjacking defense (deprecated in favor of CSP frame-ancestors) |
| Referrer-Policy: strict-origin-when-cross-origin | Limit referer leakage |
| Permissions-Policy | Restrict camera, mic, geolocation, payment, etc. |
| Cross-Origin-Opener-Policy / COEP | Required for SharedArrayBuffer; isolates browsing context |
| Cross-Origin-Resource-Policy | Restrict who can load your resources cross-origin |
15.6 Supply Chain Security
- Lockfile hygiene — never auto-merge dependency PRs without review.
- Snyk / Socket.dev / GitHub Dependabot — scan for known CVEs and malicious packages.
- SBOM (Software Bill of Materials) — CycloneDX or SPDX format; CISA mandates for federal contracts.
- Pinned versions — no
^or~for production deps in lockfile. - Subresource Integrity (SRI) for any CDN-loaded script.
- npm install discipline — review postinstall scripts; consider
--ignore-scripts.
node_modules as untrusted code.15.7 Hard Questions
15.8 References
16Observability
If it's not measured, it doesn't exist. Frontend observability is harder than backend because you can't put a debugger on the user's browser.
16.1 The Three Pillars (+ Two)
| Pillar | What | Tools |
|---|---|---|
| Logs | Discrete events; "user clicked checkout" | console (dev), telemetry SDK in prod |
| Metrics | Aggregate numbers; "p95 LCP this hour" | web-vitals, Datadog, Prometheus exporters |
| Traces | Cross-service request path; "this click took 800ms — which service?" | OpenTelemetry JS, W3C Trace Context |
| Errors | Exceptions + breadcrumbs | Sentry, Bugsnag, Rollbar, Datadog |
| Session replay | Reconstructed user sessions | LogRocket, Sentry Replay, FullStory, Hotjar |
16.2 Error Tracking — Production-Grade
- Source map upload on every deploy; never serve source maps publicly.
- Release tagging — every error tagged with build hash + version; regression detection automated.
- User context — anonymized user id, plan, locale, but redact PII.
- Breadcrumbs — last N navigations, network calls, console messages.
- Error boundaries in React at route + feature granularity with fallback UI + automatic report.
- Unhandled rejection +
window.onerrorcapture for what bypasses boundaries. - Sample rate — for high-traffic apps; bias toward keeping rare errors.
- Alerting — new error type within 24h → on-call ping; spike of existing error > threshold → ping.
16.3 Distributed Tracing on the Client
OpenTelemetry JS lets you create spans on the client and propagate W3C traceparent headers to your backend. Result: a single trace from user click to database query.
// Client-side span
const tracer = trace.getTracer('frontend');
const span = tracer.startSpan('checkout-submit');
try {
await fetch('/api/checkout', {
method: 'POST',
headers: { /* OpenTelemetry auto-injects traceparent */ },
body: JSON.stringify(data),
});
} finally {
span.end();
}
16.4 Analytics & Product Telemetry
- Schema-first events — typed event schema (Avro / JSON Schema); contract enforced in code.
- Server-side or client-side? Client = user behaviour, latency, errors. Server = revenue, authoritative state. Both for accuracy.
- Consent & privacy — IAB TCF v2.2, OneTrust, native consent banner; honor consent flags before any tracking.
- Avoid third-party trackers on critical path — load async, after LCP; ideally proxy server-side.
16.5 Hard Questions
16.6 References
17CI/CD & Release Engineering
"How often can you ship safely?" is a leadership metric. The answer should be "any time we want, and we have."
17.1 Release Strategies
| Strategy | How | When |
|---|---|---|
| Blue-Green | Two identical envs; swap traffic; instant rollback | Database-schema-stable releases |
| Canary | Route N% of users to new version; ramp up | Risky changes; gradual confidence |
| Rolling | Replace instances one at a time | Stateless services; common for k8s |
| Feature Flags | Code in prod, off by default; toggle per user | Trunk-based dev; A/B testing |
| Branch-by-Abstraction | Toggle between old and new implementation behind an interface | Large refactors |
| Dark Launch | Send traffic to new code path, discard response, measure | Validating new backend without UX change |
17.2 Feature Flags — Done Right
- Use a real flag platform: LaunchDarkly, Split, Unleash, ConfigCat, GrowthBook (OSS), Statsig.
- Three flag types: release (short-lived, deleted after rollout), experiment (A/B with metrics), permission (long-lived; access control).
- Maintain a flag inventory with TTL; auto-create cleanup tickets when a release flag passes 30 days.
- Default state should be safe (off).
- Server-side resolution prevents flicker; client-side allows fast UI swap.
- Test both branches in CI.
17.3 The Deployment Pipeline (Lead-quality)
PR opened
Lint, type-check, unit tests, build, bundle-size budget, security scan. Preview deploy to ephemeral URL.
Merge to main
Full E2E suite on built artifact. Visual regression. Tag artifact with commit SHA.
Auto-deploy to staging
Smoke tests; perf budget check against staging baseline; accessibility scan.
Canary to production (1–5%)
Watch error rate, CWV, business metrics for 15–30 minutes.
Ramp to 100%
Or rollback automatically on alert. Tag release; post in #releases.
Post-deploy
Source maps uploaded; SBOM published; release notes auto-generated from conventional commits.
17.4 Hard Questions
17.5 References
18Deployment, CDN & Edge
Where your code runs is as much a decision as what it does. The edge is no longer optional.
18.1 The Edge Landscape
| Provider | Runtime | Strength |
|---|---|---|
| Cloudflare Workers | V8 isolates (not Node); WinterCG runtime | ~0ms cold start, 300+ POPs, KV/D1/R2 ecosystem |
| Vercel Edge Functions | V8 isolates | Tight Next.js integration; ISR; image opt |
| AWS Lambda@Edge / CloudFront Functions | Node / lightweight JS | AWS-native; less ergonomic |
| Fastly Compute | WASM | Polyglot via WASM; deep CDN integration |
| Deno Deploy | Deno runtime | TS-native, fresh-built |
| Netlify Edge Functions | Deno runtime | Simple Netlify integration |
18.2 What to Run at the Edge
- Auth checks (validate session cookie at the edge, redirect or return 401 instantly).
- A/B test bucketing (consistent hashing on user id; pick variant; pass via header to origin).
- Geo-based redirects / personalization.
- Bot detection / WAF rules.
- HTML rewriting (HTMLRewriter API in CF Workers).
- Cache key normalization.
- Image optimization.
18.3 CDN Patterns
- Surrogate keys / Cache Tags for tag-based purge (Fastly, Cloudflare Enterprise).
- SWR (stale-while-revalidate) headers to serve stale instantly while refreshing background.
- ISR (Incremental Static Regeneration) for content that changes per minute, not per request.
- Tiered caching — Cloudflare Argo / Fastly origin shielding.
- Cache key normalization — strip non-meaningful query params; canonicalize trailing slash.
18.4 Hard Questions
18.5 References
19Documentation & Knowledge
Engineering culture is what survives the engineers leaving. Documentation is its substrate.
19.1 The Four Document Types
| Type | Purpose | Examples |
|---|---|---|
| ADR / RFC | Decisions and rationale | "Why we picked Module Federation" |
| Runbook | Step-by-step for incidents | "What to do if Lighthouse CI fails on main" |
| Reference | Surface description of API/system | Storybook stories, OpenAPI, TSDoc |
| Tutorial / How-to | Onboarding, paved paths | "How to add a new feature in our codebase" |
19.2 What "Good" Looks Like
- Onboarding doc — new engineer can ship a PR on day 2, not day 12.
- Architecture overview — a single page diagram + 200 words; not a 40-page wiki nobody reads.
- Runbook per page for every alert that pages someone.
- Code lives next to docs — Storybook stories are docs; TSDoc is docs.
- Docs in the repo, reviewed in PR, not in a separate Confluence.
19.3 Hard Questions
20Code Review Culture
Code review is the highest-leverage activity in any engineering org. A Lead designs the system as deliberately as any other.
20.1 Principles (Google's eng practices, adapted)
- Review for the change as it stands, not for what you would have written.
- Approve when the change improves the codebase, not when it's perfect.
- Comments are categorized: blocker (must fix), suggestion (consider), nit (style preference), question, praise.
- Code review SLA: first response within 4 working hours; full review within 24h.
- Small PRs (< 400 LoC) get reviewed; large PRs get rubber-stamped or postponed.
- Author responds to every comment (even "noted" or "wontfix because X"). No silent ignore.
20.2 The Tooling Matters
- CODEOWNERS for automatic reviewer assignment.
- Required CI green before merge.
- Stacked PRs for large changes (Graphite, Sapling, git-branchless).
- AI review (CodeRabbit, Greptile, Diamond) as first-pass — humans focus on architecture.
- Merge queue (GitHub, Aviator, Mergify) to test mainline state.
20.3 Hard Questions
20.4 References
21Browser Internals
A Lead reasons about performance from how the browser actually works — not from React's abstractions.
21.1 The Rendering Pipeline
- Parse HTML → DOM tree. Streaming parse; can be paused by script tags (unless
async/defer). - Parse CSS → CSSOM. Render-blocking.
- JavaScript execution — can read/write DOM and CSSOM; blocks parser unless deferred.
- Render tree — DOM × CSSOM, omitting
display:nonenodes. - Layout (reflow) — compute geometry for every render-tree node.
- Paint — fill pixels into layers (a layer per "compositing trigger": transform, opacity, will-change, video, canvas).
- Composite — GPU stitches layers together for the final frame.
The fast path bypasses layout and paint — only composite. That's why transform and opacity animations are 60fps-cheap while top/width are expensive.
21.2 The Event Loop
┌─────────────────┐ │ Macrotask │ ← one per loop turn (setTimeout, setInterval, I/O, UI events) ├─────────────────┤ │ Microtasks │ ← all drained before next macrotask (Promise.then, queueMicrotask, MutationObserver) ├─────────────────┤ │ requestAnimationFrame callbacks │ ← before paint ├─────────────────┤ │ Style + Layout + Paint │ ├─────────────────┤ │ requestIdleCallback (if time) │ └─────────────────┘
Implications: a Promise chain runs before the next setTimeout(0) callback. queueMicrotask lets you piggyback work without yielding to the browser. requestAnimationFrame aligns work with the paint cycle (~16.67ms at 60Hz, 6.94ms at 144Hz).
21.3 Memory Management
- V8 uses generational garbage collection: young generation (Scavenger, fast), old generation (Mark-Sweep + Mark-Compact, slower).
- Common leaks: forgotten event listeners on detached DOM, large closures captured by long-lived callbacks, growing arrays in modules, third-party scripts.
- Diagnose with Chrome DevTools → Memory tab → Heap snapshot + Allocation timeline.
WeakRef/FinalizationRegistryfor advanced cache scenarios.- Profile memory across page navigations in SPAs — leaks compound.
21.4 The Critical Rendering Path
Sequence to first paint: HTML byte → DOM → render-blocking CSS → first layout → first paint. JS in <head> blocks DOM parse. JS without defer/async blocks parsing. CSS in <head> blocks render. Optimizing this path is the foundation of LCP optimization.
21.5 Hard Questions
top/height/width instead of transform? (4) Layer count — too many or too few compositing layers? will-change overuse pre-allocates GPU memory. (5) Paint flashing — does the entire viewport repaint on each frame? (6) JS — heavy synchronous work in event handlers or requestAnimationFrame callbacks. Solutions: switch animation to transform: translate3d; offload computation to Web Worker; use CSS animations or Web Animations API instead of JS; check for forced synchronous layout (reading offsetTop after a write).queueMicrotask and setTimeout(fn, 0)?queueMicrotask queues in the microtask queue, drained before the next macrotask. setTimeout(fn, 0) is a macrotask — even with 0ms, it waits at least until current microtasks drain + next loop turn (often clamped to 4ms minimum after 5 nested timeouts). Use microtasks for "right after this task" semantics (Promise behaviour); use setTimeout for "yield to the browser" (let it paint, handle input). Modern browsers have scheduler.postTask and scheduler.yield (Chrome 129+) — better than setTimeout for INP.translate3d, translateZ), will-change for transform/opacity, position: fixed/sticky in some cases, video, canvas (sometimes), iframe, opacity < 1 with descendants, certain filter values, overlapping with already-composited siblings. Implications: too many layers = GPU memory pressure (especially on mobile). Too few = expensive repaints on animations. Use DevTools → Layers panel to audit. Cite: Chrome internals — rendering.21.6 References
22JavaScript Mastery
Past the bootcamp basics. Closures, iterators, generators, proxies, decorators, the proposals pipeline.
22.1 Closures & Lexical Scope
A closure is a function bundled with its lexical environment. The hardest production bug is usually a stale closure — a callback captured an old version of state.
// Stale closure trap
function setupCounter() {
let count = 0;
setInterval(() => console.log(count), 1000); // forever logs 0
count++; // unreachable; the closure already captured count=0 at scheduling
}
// In React
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
const id = setInterval(() => setCount(count + 1), 1000); // stale; count is always 0
return () => clearInterval(id);
}, []); // ← empty deps array = closure baked at mount
// FIX: setCount(c => c + 1) — functional update reads latest
}
22.2 Iterators & Generators
// Custom iterable
class Range {
constructor(start, end) { this.start = start; this.end = end; }
*[Symbol.iterator]() {
for (let i = this.start; i <= this.end; i++) yield i;
}
}
for (const n of new Range(1, 5)) console.log(n);
// Async iterators for streams
async function* readLines(file) {
for await (const chunk of fs.createReadStream(file)) {
for (const line of chunk.toString().split('\n')) yield line;
}
}
22.3 Proxies — Use Sparingly
const observed = new Proxy(target, {
get(t, key, recv) { trackRead(t, key); return Reflect.get(t, key, recv); },
set(t, key, val, recv) { const r = Reflect.set(t, key, val, recv); trigger(t, key); return r; }
});
Proxies power MobX / Vue reactivity / Valtio. Cost: every access goes through a trap; not free. Use for tooling, not hot paths.
22.4 Patterns Worth Knowing
- AbortController — cancellation for fetch, listeners, custom async; chainable via signals.
- Structured Clone — built-in deep clone (
structuredClone(obj)). - Symbol — unique keys; well-known symbols (
Symbol.iterator,Symbol.asyncIterator,Symbol.toPrimitive). - WeakMap / WeakSet / WeakRef — for caches that shouldn't prevent GC.
- Optional chaining + nullish coalescing — but beware
a?.b()short-circuits the whole expression. - Tagged templates — secure-string DSLs (e.g., SQL via Drizzle).
- Pipeline operator (Stage 2 proposal) — functional chaining.
- Decorators (Stage 3) — class & field metadata.
- Records & Tuples (Stage 2) — value-type immutable structures.
- Iterator helpers (Stage 4 — shipping) —
.map().filter().take()on iterators. - Temporal API (Stage 3) — modern date/time replacing Date.
22.5 Hard Questions
this binding works in JavaScript. Cover arrows, methods, constructors, and explicit binding.this resolves dynamically at call site (except arrows, which capture lexically). Four rules in precedence order: (1) new — this is the newly constructed object. (2) Explicit binding — .call(thisArg), .apply, .bind. (3) Implicit — object method call obj.fn() sets this to obj. (4) Default — undefined in strict mode, global in sloppy. Arrows have no own this; they capture the enclosing scope's. Class methods are sloppy-equivalent to regular functions; passing as callback loses this unless bound. ES2022 class fields with arrow can give per-instance bound methods. Reference: You Don't Know JS — this & Object Prototypes.AbortController + signal threading. Wrap the callback to check signal.aborted; set up setTimeout to call controller.abort(). If the library accepts AbortSignal (most modern do, including fetch), pass it directly. If it doesn't: wrap in Promise.race against a timeout promise; the loser is discarded but the work continues until natural completion (so still cleanup the resource). Discuss: AbortSignal.timeout(ms) — built-in shortcut. AbortSignal.any([sig1, sig2]) — compose signals.22.6 References
23TypeScript Advanced
Beyond strict: true. The type system is a Turing-complete logic programming language — and a Lead uses it that way (judiciously).
23.1 Type-Level Tools
- Conditional types —
T extends U ? X : Y. - Mapped types —
{ [K in keyof T]: U }. - Infer keyword — extract types within conditionals:
type Awaited<T> = T extends Promise<infer U> ? U : T. - Template literal types — type-level string manipulation.
- Variadic tuple types — spread in tuples.
- Discriminated unions — narrow by literal tag.
- Branded types — nominal typing via intersection:
type UserId = string & { __brand: 'UserId' }. - const generics — preserve literal types via
const T extends .... - satisfies operator — assert shape without widening.
23.2 Practical Patterns
// Type-safe event emitter
type Events = {
login: { userId: string };
logout: { reason: 'manual' | 'timeout' };
};
class Emitter<E extends Record<string, unknown>> {
on<K extends keyof E>(event: K, handler: (payload: E[K]) => void) { /* ... */ }
emit<K extends keyof E>(event: K, payload: E[K]) { /* ... */ }
}
const bus = new Emitter<Events>();
bus.emit('login', { userId: 'abc' }); // ✅
bus.emit('login', { reason: 'manual' }); // ❌ TS error
// Builder pattern with type accumulation
class QueryBuilder<T = {}> {
select<K extends string>(key: K): QueryBuilder<T & Record<K, unknown>> { /* ... */ }
where(...): this { /* ... */ }
execute(): T { /* ... */ }
}
const result = new QueryBuilder().select('id').select('name').execute();
// result is { id: unknown; name: unknown }
23.3 The TypeScript Anti-Patterns
any— opt-out of typing. Useunknowninstead and narrow.as Typecasts without runtime checks — bypass the type system at trust boundaries.- Overly-clever types that take 5 minutes to understand. Aim for "ergonomic for the consumer, simple-ish in implementation."
- Re-exporting types from
node_modulescreating circular type dependencies. - Massive single
index.d.ts— type errors become slow.
23.4 Performance of the Type System
At Lead scale (50k+ TS files), type-check time matters. Tactics:
tsc --diagnosticsto see hot paths.- Avoid deep recursion in conditional types.
- Prefer interfaces over type intersections for object shapes (faster to merge).
incremental: truefor build cache.- Project references for monorepo.
- Migrate to TypeScript native port (Go-based, 10× faster — coming).
23.5 Hard Questions
const schema = z.object({ email: z.string().email(), age: z.number() }). Infer the values type: type Values = z.infer<typeof schema>. The hook returns a typed register that constrains field names to keyof Values and infers value type per field. handleSubmit receives the parsed and validated values type. Errors map is Partial<Record<keyof Values, string>>. Discuss field arrays (nested keys), conditional fields (discriminated union on a tag field), async validation (returns Promise of ValidationResult). Refer to react-hook-form / TanStack Form for inspiration. Mention the Standard Schema spec emerging for cross-validator interop.23.6 References
24Modern CSS
CSS in 2026 is no longer the language CSS was in 2016. Container queries, layers, scope, view transitions, has(), and color spaces are production-ready.
24.1 Container Queries
.card {
container-type: inline-size;
container-name: card;
}
@container card (min-width: 400px) {
.title { font-size: 1.5rem; }
}
Queries the component's own width, not the viewport. Game-changer for design systems.
24.2 Cascade Layers
@layer reset, base, components, utilities;
@layer reset { /* normalize.css */ }
@layer base { body { font-family: sans-serif; } }
@layer components { .btn { padding: 0.5rem 1rem; } }
@layer utilities { .text-sm { font-size: 0.875rem; } }
Layered cascade beats specificity wars. Later layers always win over earlier (unlayered styles beat layered).
24.3 CSS :has() — The Parent Selector
/* Card with an image gets extra padding */
.card:has(img) { padding-bottom: 2rem; }
/* Form with invalid input shows error styling on the wrapper */
.form-row:has(input:invalid) { border-color: red; }
/* Hide siblings of focused element */
.menu li:not(:has(a:focus)) { opacity: 0.5; }
24.4 View Transitions API
// SPA route change with cross-fade
document.startViewTransition(() => {
updateDOMForNewRoute();
});
// CSS to customize
::view-transition-old(root) { animation: fade-out 0.3s; }
::view-transition-new(root) { animation: fade-in 0.3s; }
Cross-document view transitions (Chrome 126+) enable transitions across full page loads — previously only possible in SPAs.
24.5 Modern Color & Typography
- color-mix(in oklch, ...) — programmatic color mixing in perceptual color spaces.
- oklch() / oklab() — perceptually uniform color; better for design tokens than HSL.
- color() with display-p3 — wide-gamut for compatible screens.
- relative color syntax — derive variants:
oklch(from var(--primary) calc(l - 0.1) c h). - text-wrap: balance — heading line-balancing.
- text-wrap: pretty — better line-breaking in paragraphs.
- variable fonts — single file, axis-controlled (weight, width, slant); often smaller than 4 static files.
24.6 Scroll-Driven Animations
@keyframes reveal { from { opacity: 0; } to { opacity: 1; } }
.card {
animation: reveal linear;
animation-timeline: view();
animation-range: entry 0% cover 30%;
}
Native CSS scroll-linked animation. No JS, no IntersectionObserver. Chrome 115+, Firefox preview, Safari coming.
24.7 Logical Properties (RTL-Ready)
| Physical | Logical |
|---|---|
| margin-left, margin-right | margin-inline-start, margin-inline-end |
| padding-top, padding-bottom | padding-block-start, padding-block-end |
| top, left | inset-block-start, inset-inline-start |
| width, height | inline-size, block-size |
| text-align: left | text-align: start |
24.8 Hard Questions
24.9 References
25React Internals
A Lead understands what React does to memory and to the main thread — not just what hooks do.
25.1 The Reconciliation Model
React maintains two trees: current (committed) and work-in-progress (rendering). On a state change, React builds the WIP tree by re-rendering components, diffs against current, and commits changes to the DOM in a single batched flush. Since React 18, this is interruptible — concurrent rendering means the WIP tree can pause for higher-priority work (user input).
25.2 Fiber Architecture
Each component instance gets a "fiber" — a JS object holding component type, props, state, effects, and pointers to parent/child/sibling fibers. The reconciler walks fibers, not directly the DOM. Walking is cooperative — React can yield between fibers if the deadline expires.
25.3 Hooks — How They Actually Work
Each fiber has a linked list of hook instances. On render, React positionally matches calls — first call is the first hook in the list, second is the second, etc. That's why hooks must always be called in the same order (the "no conditional hooks" rule). The hook list is recreated on every render of the same fiber.
25.4 React 19 Highlights (deep)
use()— read a promise or context conditionally. Suspends the calling component until the promise resolves. Enables RSC's "await data inline."- React Compiler (Forget) — analyzes components at build, inserts memoization automatically. Removes 90%+ of manual
useMemo/useCallback. - Actions &
useActionState— async transitions; pending state, optimistic updates, form integration. useOptimistic— built-in optimistic UI primitive.- Refs as props — no more
forwardRefin most components. - Document Metadata —
<title>,<meta>inside components are hoisted to<head>. - Resources —
<link rel="stylesheet" precedence>deduped and reordered automatically. - preinit / preload / prefetchDNS — programmatic resource hints.
- Improved hydration errors — diffs reported clearly.
25.5 Server Components — The Mental Model
RSC are components that render on the server and ship a serialized tree (not HTML) to the client. The client merges them with client components ("islands"). RSC can:
- Use
async/awaitfor data fetching inline. - Access the server filesystem, environment, databases directly.
- Ship zero JS to the client (the RSC payload describes the tree, not the source).
RSC cannot:
- Use state hooks (
useState,useReducer) — they have no client lifecycle. - Use effect hooks.
- Attach event handlers (unless via client component child).
- Use browser APIs.
'use client' at the top of a file marks everything in that module as client. A server component can import and render a client component, but not vice versa.
25.6 Hard Questions
"use no memo" directive. Also: for libraries that ship to consumers, compiled output is less inspectable — consider shipping un-compiled. For very small components where overhead of memoization checks dominates, the compiler may add work for no win — but this is rare.25.7 References
26Networking
HTTP/3, WebTransport, WebSockets, Server-Sent Events, BroadcastChannel — picking the right transport is a Lead decision.
26.1 HTTP Evolution
| Version | Key Change | FE impact |
|---|---|---|
| HTTP/1.1 | Persistent connections, pipelining (rarely works) | Browsers cap at 6 connections per origin → bundle assets |
| HTTP/2 | Multiplexing on one connection, header compression, server push (deprecated) | Many small requests OK; bundling less critical |
| HTTP/3 (over QUIC) | UDP-based, eliminates head-of-line blocking at transport, faster handshake | Better on lossy networks; deployed at CF, Akamai, Fastly |
| 103 Early Hints | Server can send preload hints before final response | Improves LCP by ~100ms on slow origins |
26.2 Real-time Transports
| Tech | Direction | Best for |
|---|---|---|
| WebSocket | Full duplex | Chat, collaborative editing, real-time games |
| Server-Sent Events (SSE) | Server → Client | Notifications, live feeds, LLM token streaming |
| WebTransport | Multiple streams + datagrams over HTTP/3 | Future of low-latency apps (browser support emerging) |
| WebRTC | P2P + signaling server | Video, voice, low-latency data channels |
| Long polling | Client requests, server holds | Fallback when WS blocked by corporate proxies |
| BroadcastChannel | Same-origin tabs | Cross-tab UI sync without a server |
26.3 Picking Between WS and SSE
SSE wins for server-push-only data: simpler protocol (just HTTP), auto-reconnect with last-event-id resume, works with HTTP/2 multiplexing, no CORS gymnastics, easy to scale (CDN-friendly). LLM streaming is the classic 2024+ use case. WebSocket wins when client also pushes frequently (chat input, mouse cursors in collaborative editor).
26.4 Hard Questions
26.5 References
27Web Standards & Platform APIs
The platform shipped a lot in 2023-2025. Lead engineers should know what's possible without npm install.
27.1 APIs Worth Knowing
- IntersectionObserver — lazy-load, infinite scroll, ad viewability without scroll listeners.
- ResizeObserver — element-size-aware layouts.
- MutationObserver — react to DOM changes (third-party iframes, legacy code).
- PerformanceObserver — capture LCP, FID/INP, long tasks, layout shifts.
- Long Animation Frames (LoAF) — replaces Long Tasks; catches the things hurting INP.
- Navigation API — replaces History API + popstate; promise-based, intercept-able.
- View Transitions — animated state changes between DOM trees.
- Popover API — native popovers without JS (Chrome 114+, Safari 17+).
- Dialog element — native modal with backdrop, ESC handling, focus trap (partial).
- BroadcastChannel — cross-tab messaging.
- File System Access API — read/write user files (Chrome only).
- Web Share API — native share dialog on mobile.
- WebAuthn / Passkeys — phishing-proof auth.
- FedCM — federated identity replacing third-party cookies.
- Web Workers / Service Workers / Shared Workers — different scopes of off-main-thread.
- WebAssembly + WASI — near-native compute in browser.
- Web Bluetooth / USB / Serial / HID — hardware access (Chrome).
- Web Speech API — text-to-speech and speech-to-text.
- Web Animations API (WAAPI) — programmatic CSS animations.
- Web Locks API — coordinate across tabs (e.g., one tab leader for IndexedDB writes).
- Storage API — quota estimates, persistent storage requests.
- OffscreenCanvas — canvas rendering on a Web Worker.
27.2 Hard Questions
27.3 References
28PWA & Offline-First
Service workers are how the web shipped its strongest feature in the last decade. Most teams still don't use them well.
28.1 The Service Worker Lifecycle
- Register — JS calls
navigator.serviceWorker.register('/sw.js'). - Install — once per version; cache assets via
caches.open(...).addAll(...). - Activate — clean up old caches;
self.clients.claim()for instant control. - Fetch — intercept every navigation and asset; programmable caching.
- Update — browser checks
sw.jsfor byte changes; new SW installs in background, waits for tabs to close.
28.2 Cache Strategies
| Strategy | Behaviour | Best for |
|---|---|---|
| Cache-first | Cache → fallback to network | Hashed static assets (immutable) |
| Network-first | Network → fallback to cache | HTML pages — fresh wins, offline-safe |
| Stale-while-revalidate | Cache immediately + background refresh | Frequently-updated content where stale is OK briefly |
| Network-only | Always network | Mutations, auth, real-time |
| Cache-only | Never network | App shell after install |
Workbox abstracts these as one-liners. Reference: Workbox docs.
28.3 Hard Questions
self.skipWaiting() in install + self.clients.claim() in activate, but warn that this can break in-flight requests; safer is to show an "update available" toast and call skipWaiting on user click. (2) HTML caching too aggressive — never cache HTML at the SW with long TTL; use network-first. (3) Asset hash mismatch — ensure assets are content-hashed; old SW caches old hashed assets, new SW caches new ones; no overlap. (4) Cache versioning — bump cache name on every deploy; activate handler purges old caches. (5) HTTP cache on top of SW — ensure SW responses have correct Cache-Control. (6) Kill switch — ship an "unregister-all" SW as last resort. Cite Workbox patterns.28.4 References
29Frontend System Design — Framework
FE system design is the most distinctive part of a senior-to-staff interview. There's a structured way to approach every problem.
29.1 The RADIO Framework
Popularized by GreatFrontEnd; the most cited framework for FE system design.
- Requirements clarification
- Architecture / high-level design
- Data model
- Interface (API + component API)
- Optimizations (perf, a11y, security, offline, error handling, scaling)
Reference: GreatFrontEnd — RADIO framework
29.2 Requirements — The Right Questions
- Functional: what does the user do? Main flows? Edge cases?
- Audience: who, where (geo), what devices, what network?
- Scale: DAU/MAU, concurrent users, peak QPS?
- Non-functional: p95 latency, accessibility, SEO, offline support, localization?
- Constraints: existing backend, tech stack, team skills, deadline?
- Out of scope: what won't you discuss (auth, signup, billing)?
29.3 Architecture Diagrams
Draw three boxes minimum: client, server (or BFF/API gateway), backend (services + data store). Add CDN/edge layer. Identify the network hops. For each hop, label payload shape and frequency.
29.4 Data Model
List entities, their relationships, the shape returned to the client. Mention normalization (cache shape) vs denormalization (transport). Discuss pagination strategy (offset/cursor/keyset). Discuss freshness — what's cached for how long.
29.5 Interface
API endpoints (REST or GraphQL queries). Component API — what the consumer sees: props, callbacks, slots. Loading/error/empty states explicitly defined.
29.6 Optimizations Checklist
| Area | Tactics to mention |
|---|---|
| Performance | Code splitting, lazy load, virtualization, image opt, SSR/RSC, prefetch, Web Workers |
| Network | Batch, dedup, cache, optimistic update, retry with backoff, offline queue |
| Accessibility | Semantic HTML, ARIA, keyboard, screen reader, focus mgmt, color contrast |
| Security | XSS, CSRF, CSP, token handling, rate-limit-aware client |
| i18n | RTL, plural rules, date/number formatting |
| Reliability | Error boundaries, retry, graceful degradation, offline detection |
| Observability | Errors, RUM, custom telemetry, A/B test instrumentation |
| Testing | Unit, integration, E2E, visual regression, a11y |
29.7 References
30Design: News Feed
The canonical FE system-design question. Used at Meta, Twitter, LinkedIn, TikTok.
30.1 Requirements (clarify first)
- Vertical infinite scroll, posts with text/image/video, like/comment/share.
- Personalized ranking (server-side); client just renders.
- 10M DAU; reads >> writes.
- Web + mobile web; deep links; share-to-anywhere.
- Real-time new-post indicator ("3 new posts" pill at top).
30.2 Architecture
- SSR or RSC for initial page (SEO + fast LCP for the first 5–10 posts).
- Client-side hydration; subsequent pages fetched via cursor pagination.
- Edge cache for unauth feed (logged-out homepage); per-user cache for auth feed (short TTL).
- WebSocket or SSE for new-post notifications (push count, not the posts themselves).
- Image CDN with responsive variants (
srcset, AVIF), video as HLS/DASH.
30.3 Data & Pagination
// Cursor-based pagination (preferred over offset)
GET /feed?cursor=eyJ0cyI6MTcwOH0&limit=20
{
posts: [...],
nextCursor: "eyJ0cyI6MTcwOX0",
hasMore: true
}
Cursor pagination handles "new posts arriving while user scrolls" correctly (offset would skip or duplicate). Stable across sessions when cursors are opaque ts+id tuples.
30.4 Virtualization & Memory
- Use TanStack Virtual or react-window with measured heights. Naive infinite scroll renders 100s of DOM nodes — memory grows.
- Recycle DOM via virtualization OR unmount far-offscreen posts and remount on re-entry (LRU).
content-visibility: autoon each post — skips render for off-screen items.- Image lazy-load with IntersectionObserver;
loading="lazy"attribute as fallback.
30.5 Optimistic Interactions
- Like: increment count immediately, POST in background; rollback on error.
- Comment: append optimistic comment with grey state; replace with server response or retry.
- De-duplicate concurrent mutations.
30.6 Performance Targets
- LCP < 2.0s p75 (above-fold first post + image).
- INP < 100ms (like button must feel instant).
- Scroll FPS > 50 on mid-tier Android.
- Initial JS < 200KB compressed.
30.7 Edge Cases
- Post deleted while user viewing — fade-out with explanation.
- Network drops mid-scroll — show "tap to retry" within the empty space.
- Auto-play video on Wi-Fi only; respect
prefers-reduced-motion. - Same post viewed in multiple tabs — like state sync via BroadcastChannel.
30.8 References
31Design: Collaborative Editor (Google Docs / Figma / Linear)
The hardest problem in FE system design — concurrency, consistency, and offline.
31.1 The Core Question: OT vs CRDT
| Operational Transformation (OT) | CRDT | |
|---|---|---|
| Approach | Operations rebased against concurrent ops on a central server | Data structures designed to converge regardless of order |
| Server role | Required — applies transforms | Optional — can be P2P |
| Complexity | Hard transform functions; lots of edge cases | Complex data structures but composable |
| Examples | Google Docs, Etherpad, ShareJS | Yjs, Automerge, Liveblocks, Linear's Sync Engine |
| Trend (2025+) | Mature, used in large products | Rapidly mainstream — favored for new apps |
31.2 Architecture (CRDT-based, like Yjs)
- Client maintains a local Y.Doc instance — single source of truth for the user.
- Edits are local mutations; converted to binary "updates" by Yjs.
- Updates sync via WebSocket to a server (or directly to peers via WebRTC).
- Server is "dumb" — relays updates and persists snapshot+log.
- Conflict resolution is automatic by CRDT properties — concurrent edits merge deterministically.
- Presence (cursors, selections) on a separate ephemeral channel.
31.3 Hard Sub-problems
- Garbage collection — CRDT tombstones accumulate; periodic compaction needed.
- Initial load — load snapshot then replay since-snapshot updates. Latency budget matters.
- Permissions — server can't trust client; document-level ACL gate on the WS.
- Undo/redo — local undo stack vs collaborative undo (only undo your own changes).
- Large documents — chunking strategies; lazy-load offscreen pages.
- Offline edits — local IndexedDB persistence; reconcile on reconnect.
- Cursor presence — debounce broadcast; subscribe only to visible users.
31.4 Linear's Sync Engine — Worth Studying
Linear ships an in-process client database synchronized with the server; all UI reads from the local store; all writes go through optimistic mutation + reconciliation. Result: every interaction is instant. Reference: Linear engineering — scaling sync.
31.5 Hard Questions
31.6 References
32Design: Autocomplete / Typeahead
Looks simple. Has every interesting FE problem in 30 lines of code.
32.1 Requirements to Clarify
- Latency target — feels instant means < 100ms perceived.
- Trigger threshold (2 chars? 1 char?).
- Recent / popular suggestions even without typing.
- Keyboard navigation (Up/Down/Enter/Esc).
- Accessibility — ARIA combobox pattern.
- Result count, ranking, highlighting.
32.2 Architecture
- Client debounces input (~150-300ms).
- Request only if query changed;
AbortControllercancels in-flight on new input. - Cache key by query string; LRU eviction.
- Prefetch popular suggestions at idle.
- Server: dedicated search service (Elasticsearch / Algolia / Typesense / Meilisearch) — frontend hits this directly with auth token.
- Edge caching for popular queries; bypass for personalized.
32.3 The Race Condition Trap
// ❌ Race: user types "ne", "new", "news" — responses may arrive out of order
async function search(q) {
const res = await fetch(`/search?q=${q}`);
setResults(await res.json());
}
// ✅ AbortController cancels prior
let ctl;
async function search(q) {
ctl?.abort();
ctl = new AbortController();
try {
const res = await fetch(`/search?q=${q}`, { signal: ctl.signal });
setResults(await res.json());
} catch (e) { if (e.name !== 'AbortError') throw e; }
}
32.4 Hard Questions
role="combobox", aria-expanded reflecting popup open, aria-controls="listbox-id" pointing to the listbox, aria-autocomplete="list" or "both", aria-activedescendant pointing to the highlighted option id. Listbox has role="listbox"; each result role="option" with unique id and aria-selected. Live region announcing result count ("5 results, use arrow keys to navigate"). Keyboard: Down opens + highlights first; Up/Down navigate; Enter selects; Esc closes restoring focus to input; Tab closes and tabs away. Reference: APG Combobox.32.5 References
33Design: Video Player
Video is where FE meets media engineering. Adaptive bitrate, DRM, captions, low-latency.
33.1 Core Concepts
- HLS (HTTP Live Streaming) — Apple's protocol, m3u8 manifest + .ts/.mp4 segments. Default for web/iOS.
- DASH — Google/Netflix; xml manifest + MP4 segments. Common for Android/desktop.
- WebRTC — for <500ms latency (live shopping, interactive).
- LL-HLS — low-latency HLS (sub-3s).
- MSE (Media Source Extensions) — JS API for ABR streaming via append-buffer model.
- EME (Encrypted Media Extensions) — for DRM (Widevine, FairPlay, PlayReady).
- Players — Shaka (Google, supports DASH+HLS), Video.js, HLS.js, dash.js, Mux Player.
33.2 The ABR (Adaptive Bitrate) Loop
- Player downloads manifest with multiple quality levels.
- Measures bandwidth via segment download time.
- Chooses next segment quality based on bandwidth + buffer level + heuristics.
- Aims to keep buffer 10-30s, never empty.
- Throttles up on stability, throttles down on stall risk.
33.3 Hard Sub-problems
- Autoplay restrictions — muted required on most browsers; user gesture required for sound.
- Captions — WebVTT format; accessibility critical (FCC compliance for streaming services).
- Subtitle styling — render in DOM (more control) or via native track (better a11y).
- Picture-in-picture — PiP API.
- Background playback — Media Session API for lock-screen controls.
- Watch history / resume — debounced position save.
- DRM provisioning — license server, key rotation.
- Analytics — startup time, rebuffer ratio, average bitrate, quality switches, errors. QoE (Quality of Experience).
33.4 References
34Design: Chat / Realtime Messaging
Slack, WhatsApp Web, Discord — same problem, similar architecture.
34.1 Architecture Sketch
- WebSocket connection per user; sticky-routed to a "channel server."
- Server fan-out to all members of the channel (room).
- Message persisted to DB before fan-out (durability).
- Sequence number per channel for ordering; client uses this to detect missed messages on reconnect.
- Read receipts via separate lightweight events (debounced).
- Typing indicators via short-lived events (TTL 5s).
- Presence — heartbeat over WS; aggregated to "online/offline/idle" indicator.
34.2 Client-Side Data Model
- IndexedDB for offline persistence; messages keyed by (channel_id, sequence).
- Optimistic local-id for sent messages; reconcile to server-id on ack.
- Read-only normalized cache (Apollo-style) for users, channels, members.
- Virtualized message list (huge channels render only visible window).
34.3 Hard Sub-problems
- Reconnection without missing messages — on reconnect, client sends last_seq; server replays from durable log.
- Order across servers — sticky routing keeps per-channel order; cross-channel order is per-channel only.
- Mute / DND / per-channel notification settings — server-evaluated.
- End-to-end encryption — Signal Protocol; client-side encryption; server never sees plaintext.
- Edit and delete — append "edited" event; client rewrites local state.
- Rich content — markdown, mentions, attachments; lazy-load attachments.
- Notifications — push via FCM/APNs when web app closed.
34.4 References
35Design: A Company-Wide Design System
Not "a component library." A product with users, an API, a migration story.
35.1 Requirements
- 50 product teams; 5 product brands sharing a design language.
- Web + React Native (or Flutter); shared design tokens.
- Accessible by default (WCAG 2.2 AA minimum).
- Independent versioning; consumers upgrade at their pace.
35.2 Architecture
- Token layer (JSON, generated to CSS vars, iOS XCAssets, Android XML).
- Primitives layer (Box, Stack, Text, Button, Input — built on Radix / React Aria).
- Patterns layer (Card, Modal, Toast, Form — composed primitives).
- Templates layer (Dashboard shell, Marketing landing, Settings page).
- Per-brand theme overrides via tokens, not forks.
35.3 Operating Model
- Central DS team owns the platform; product teams contribute via federated model (RFC + PR).
- Office hours, Slack channel, monthly demo.
- Metrics: adoption rate (% PRs using DS components), versions in use, time-to-upgrade.
- Quarterly migration goals; codemods for every breaking change.
35.4 Hard Questions
asChild / slot), fundamentally different component (introduce a sibling primitive). Make contribution easy — clear PR template, 1-week review SLA. Measure forks; share the metric in the design system steering committee. Provide a "design system upgrade quarter" so teams can pay back the debt. Make forks visible — automated PR comment when a custom component is detected duplicating a DS one. Carrot, not stick: highlight teams who contribute back, ship DS releases with their names.35.5 References
36AI in the Frontend
In 2026, a Lead FE is judged on two AI dimensions: how they ship AI features, and how they use AI in their own workflow.
36.1 Building User-Facing AI Features
- Vercel AI SDK — high-level wrapper for streaming, tool calling, RAG, multi-model.
- LangChain.js / LangGraph.js — orchestration of multi-step agent flows.
- LlamaIndex.ts — RAG-focused.
- Streaming UI patterns — Server Components + RSC streams, Edge functions piping SSE.
- Tool calling — model returns structured calls; FE renders custom UI per tool result.
- Inline citations + grounding — display sources next to claims.
- Cost / token budgeting — UI for premium users, fallback for free.
- Failure modes — what UX shows when the model is slow, wrong, or unavailable.
36.2 LLM-Native UX Patterns
- Streaming tokens — render progressively; never spinner-then-dump.
- Stop generation — user-cancellable; AbortController.
- Regenerate / try again — easy to retry.
- Edit and resubmit — revise prior message rather than starting over.
- Markdown / code rendering — react-markdown with safe whitelist; Prism/Shiki for syntax highlighting.
- Generative UI — RSC + tool calls producing typed React components rather than text.
- Tool result UI — chart for chart-tool, table for query-tool, map for places-tool.
- Source citations — clickable, with provenance.
- Conversation persistence — server-side history; resume across devices.
- Multi-turn context windows — manage context length, summarize older turns.
36.3 AI in Developer Workflow
| Tool | Category | Used for |
|---|---|---|
| GitHub Copilot | Inline completion | Boilerplate, scaffolding |
| Cursor | IDE | Multi-file edits, agentic refactors |
| Claude Code / Claude Desktop | Agent / chat | Architecture, code review, doc generation |
| Windsurf | IDE | Cursor competitor |
| v0.dev | UI scaffolding | Prompt → React + Tailwind components |
| Bolt.new / Lovable | App scaffolding | Prototypes, MVPs |
| Aider / Cline / Continue | Agent | Pair programming from terminal/editor |
| CodeRabbit / Greptile / Diamond | AI PR review | Automated first-pass review |
| MCP servers | Integration protocol | Connect AI to data sources, APIs |
36.4 Hard Questions
data: {"type":"tool_call","name":"search","args":{...}}); server executes tool, returns results, model resumes with augmented context. Client maintains a state machine of message parts: text-token, tool-call, tool-result, citation. Each part rendered with its own React component. Token-level state update is too chatty — batch via requestAnimationFrame. Auto-scroll if user is at bottom; pause auto-scroll if user scrolls up. Stop button calls AbortController on the SSE stream. Reference: Vercel AI SDK..cursorrules, CLAUDE.md) encoding conventions. (2) Strong CI — types, lint, tests catch the things AI gets wrong. (3) Code review discipline — reviewers don't rubber-stamp because "the AI wrote it." (4) Banned patterns — no AI for security-sensitive code, no AI for crypto, no AI-generated regex without review. (5) Team culture — celebrate the engineer who pushed back on bad AI suggestion. (6) Measure: track bug rate by author; doesn't change much when AI use scales. (7) Training: regular team sessions on prompt patterns that work, anti-patterns that don't. Discuss: AI-velocity-without-AI-quality is a trap.36.5 References
37Edge & Server Components Deep-Dive
RSC + edge is the most significant architectural shift since the SPA. A Lead can argue for and against it.
37.1 The Mental Reset
- Components run on the server, ship serialized tree.
- Client receives "instructions" not HTML — a React-internal binary format.
- Server components can
awaitanything. - Client components are explicit (
'use client') — and become the islands of interactivity. - Server Actions are functions on the server callable from client; they replace many API routes.
37.2 Trade-offs
| Pro | Con |
|---|---|
| Smaller JS bundle (server-only code never ships) | Two execution models in one codebase; mental overhead |
| Data fetching inline, no client-side waterfall | Client state and server data tightly coupled in dev experience |
| Direct DB access in components | Easy to over-fetch or fan out N+1 if not careful |
| Suspense + streaming gives great LCP | Tooling immaturity — testing RSC is harder |
| Forces a layered architecture | Ecosystem fragmented — libraries declare client/server compat differently |
37.3 Anti-patterns
- Passing huge server-fetched objects to client components — they get serialized in the RSC payload.
- Using
'use client'on a leaf rather than the boundary — it cascades. - Calling Server Actions from useEffect — defeats the point; use them on form submit.
- Mixing server-only env vars with client components — leaks at build.
37.4 References
38Cross-Platform Considerations
38.1 The Choices
| Stack | Approach | Best for |
|---|---|---|
| React Native + Expo | Native UI via bridge | True-native feel; large user base |
| Flutter | Custom renderer (Skia) | Pixel-perfect cross-platform; non-React orgs |
| Capacitor / Ionic | Webview + native plugins | Code reuse across web + mobile; less native feel |
| Tauri | Web frontend + Rust backend | Lightweight desktop apps |
| Electron | Web frontend + Node backend | Mature; heavy memory; VS Code, Slack |
| PWA | Web installed | When app-store is not required |
| Lynx (ByteDance) | React-syntax cross-platform UI | Emerging |
38.2 Code Sharing Strategies
- Share types, models, business logic (TypeScript packages in monorepo).
- Share UI primitives where possible (Tamagui, Solito for RN+Web shared components).
- Platform-specific UI for high-touch surfaces (navigation, gestures).
- Share networking, validation, state libraries.
38.3 Hard Questions
38.4 References
39Tech Debt & Migration
A Lead is judged on their ability to make hard migrations land without melting the team or the product.
39.1 The Migration Playbook
- Define done — what state is target? Be specific.
- Strangler fig — incremental, not big-bang.
- Codemod first — automate every mechanical change.
- Branch by abstraction — toggle between old and new behind an interface.
- Owner per migration unit — accountability prevents drift.
- Dashboards — % migrated, ETA, blockers visible.
- Deprecation policy — old API works until date X; warn in logs.
- Removal phase — only after 100% migration metrics + 1 quarter buffer.
39.2 Common FE Migrations
- Webpack → Vite/Rspack/Turbopack
- Jest → Vitest
- ESLint legacy config → flat config (or → Biome)
- styled-components → vanilla-extract / Tailwind
- Class components → functional
- React Router v5 → v6 → v7
- Pages Router → App Router (Next.js)
- Moment.js → date-fns / Day.js / Temporal
- Redux → Zustand / RTK Query / TanStack Query
- npm/yarn → pnpm
39.3 Hard Questions
process.env vs import.meta.env). (3) Codemods — for common patterns. (4) Migration template repo — engineers copy config. (5) Office hours — DS/Platform team available. (6) Quarterly target — % apps migrated; dashboard. (7) Removal date — old Webpack config deleted from CI on date X. (8) Reward early adopters — public recognition. Reference: how Shopify migrated to esbuild — gradual, measured, communicated.39.4 References
40Hiring, Mentoring & Team Building
40.1 What Leads Are Judged On
- Velocity of the team (DORA metrics).
- Quality of output (defect rate, customer-impacting incidents).
- People you brought up (promotions, growth conversations).
- Hiring bar maintained (or raised).
- Cross-team influence (RFCs you drove, standards you proposed).
- Sustainability (no heroics, no burnout, on-call humane).
40.2 Hiring Loop You Should Design
- Recruiter screen (45 min) — alignment, scope.
- Hiring manager (45 min) — motivation, growth, fit.
- Coding round (60-90 min) — practical problem, no leetcode trick.
- FE system design (60 min) — RADIO problem.
- Behavioral / leadership (60 min) — STAR stories.
- Bar raiser / cross-team (45 min) — Amazon-style independent assessment.
- Optional: take-home (timed, capped) for senior candidates uncomfortable with whiteboard.
40.3 Mentoring Engineers
- Weekly 1:1s — agenda owned by the report, not you.
- Growth plan — concrete, time-boxed, measurable.
- Stretch projects — assigned with safety net (pairing, rollback plan).
- Public feedback loop — code review is a teaching opportunity, not just a quality gate.
- Sponsorship over mentorship — talk about them when they're not in the room.
40.4 Hard Questions
40.5 References
41Incident & Postmortems
41.1 The Incident Cycle
- Detect — alerting; ideally before users notice.
- Triage — severity, ownership, comms channel.
- Mitigate — feature flag off, rollback, scale up.
- Communicate — internal + external updates on cadence.
- Resolve — full recovery.
- Postmortem — blameless, action items, follow-through.
41.2 The Blameless Postmortem
Inspired by Etsy and SRE: focus on systems and process, not individuals. Output: timeline, contributing factors, blast radius, what worked, what didn't, action items with owners and dates.
41.3 Hard Questions
41.4 References
42Behavioral & Storytelling
42.1 The STAR Structure
- Situation — concise context.
- Task — what you owned.
- Action — specific things you did (not "we").
- Result — quantified outcome + lesson.
42.2 Story Bank — Prepare 6-8 Stories Covering
- A time you led a difficult technical decision (push back on senior leadership).
- A time you disagreed with a peer and worked through it.
- A failure — what you learned.
- A migration or refactor you led.
- A time you mentored someone significantly.
- A production incident you owned.
- A scope cut you pushed for.
- A time you said no to a stakeholder.
42.3 Amazon Leadership Principles (relevant beyond Amazon)
- Customer Obsession · Ownership · Invent and Simplify · Are Right, A Lot · Learn and Be Curious · Hire and Develop the Best · Insist on the Highest Standards · Think Big · Bias for Action · Frugality · Earn Trust · Dive Deep · Have Backbone; Disagree and Commit · Deliver Results.
42.4 Hard Questions
43Hard Questions Bank — Rapid-Fire
A scrollable pool of 60+ hard questions across all areas. Sprinkle through the interview; never ask all of them.
43.1 Core Web
- Explain the rendering pipeline. Where is the bottleneck in a typical SPA?
- Walk through what happens when you type a URL and hit Enter.
- What's the difference between the DOM and the render tree?
- Why is animating
transformcheaper thantop? - How does the browser decide what's a compositing layer?
- What's a forced synchronous layout? How do you detect it?
- What does
requestAnimationFramedo thatsetTimeoutdoesn't? - Why are passive event listeners important for scroll performance?
43.2 JavaScript & TypeScript
- Implement
Promise.allfrom scratch. NowPromise.allSettled. - Implement a debounce. Now a leading-edge throttle.
- Write a curry function. Now a pipe function.
- Explain prototype chain vs class inheritance.
- What's the iteration protocol? Build a custom iterable.
- Implement deep clone without
structuredClone. - Write an LRU cache.
- Explain generators and how they enable async iteration.
- Type a generic
pickfunction with key inference. - Build a discriminated union for an API response.
43.3 React
- Why are hook calls order-sensitive?
- Implement
useDebouncedValue. - Implement
useEventCallback(stable identity, latest closure). - What does
useTransitiondo? Give a concrete example. - How does React decide a component should re-render?
- What's the difference between
useMemoanduseRef? - When is
useEffectthe wrong tool? What's right? - Explain selective hydration.
- What can a Server Component not do?
- Why is React Compiler important for INP?
43.4 Performance
- LCP regressed from 2.0s to 3.5s overnight. No deploys. Investigate.
- Bundle is 600 KB. Cut to 200 KB. How?
- INP is 600 ms on mobile. Plan.
- Explain Long Animation Frames vs Long Tasks.
- How do you set up a performance budget that actually blocks PRs?
- Why is preconnect different from preload?
- What does HTTP/2 give you that HTTP/1.1 didn't?
- Walk me through optimizing TTFB for a Next.js app.
43.5 Security
- Walk through OAuth 2.1 with PKCE end-to-end.
- Difference between XSS and CSRF — defenses for each?
- What's the danger of localStorage for tokens?
- How would you implement a strict CSP for a React app?
- Explain Trusted Types.
- What's Subresource Integrity, when does it fail?
- Walk through threat-modeling a "share via link" feature.
43.6 Architecture & System Design
- Design a news feed for 50M MAU.
- Design Google Docs-style collaborative editor.
- Design an autocomplete for a search engine.
- Design a video player with adaptive bitrate.
- Design Slack's chat client.
- Design a company-wide design system used by 50 teams.
- Design infinite scroll with 100k items.
- Walk through micro-frontends — when, why, and the gotchas.
- Module Federation in production: name three problems and the fixes.
- How do you cache-invalidate across CDN + SW + client cache?
43.7 Leadership
- Tell me about a technical decision you reversed.
- How do you raise the bar without breaking team velocity?
- Walk me through a migration you led.
- An engineer keeps shipping 1500-line PRs. What do you do?
- Your team is burned out. How do you address it?
- Two senior engineers disagree on architecture. How do you resolve?
- Tell me about a failed project. What did you learn?
- How do you decide what tech debt to pay down first?
- How do you mentor someone into senior?
- What's your hiring bar? Defend it.
44Reference Library
Curated authoritative sources. Bookmark these.
44.1 Specs & Standards
- MDN Web Docs — the canonical Web reference
- HTML Living Standard (WHATWG)
- W3C Technical Reports
- TC39 — JavaScript Process
- WCAG 2.2
- ARIA Authoring Practices
- IETF Datatracker (RFCs)
- W3C Design Tokens Spec
44.2 Engineering Blogs
- Meta Engineering
- Airbnb Engineering
- Uber Engineering
- Netflix Tech Blog
- Shopify Engineering
- Stripe Engineering
- Discord Engineering
- GitHub Engineering
- Slack Engineering
- Figma Engineering
- Linear blog
- Vercel Engineering
- Cloudflare blog
- Anthropic news & engineering
- ThoughtWorks Insights
44.3 People to Follow
- Dan Abramov — Overreacted
- Addy Osmani
- Josh Comeau
- Jake Archibald
- Kent C. Dodds
- Will Larson — Irrational Exuberance
- Martin Fowler
- Matt Pocock — Total TypeScript
- Harry Roberts — CSS Wizardry
- Smashing Magazine
- TkDodo — React Query internals
- Ben McCormick
44.4 Performance & Web Vitals
- web.dev (Google's web team)
- 3perf — Ivan Akulov
- Calibre — perf monitoring posts
- cssperf — Stoyan Stefanov
44.5 Architecture & System Design
44.6 Tools (canonical docs)
- React
- Next.js
- React Router
- TanStack (Query, Router, Table, Virtual, Form, Start)
- Vite
- Vitest
- Playwright
- Storybook
- Radix UI
- React Aria
- shadcn/ui
- Tailwind
- Zod
- react-hook-form
- Zustand
- Jotai
- Redux Toolkit
- XState (Stately)
- Module Federation
- Turborepo
- Nx
- Biome
- OpenTelemetry
- Cloudflare Workers
44.7 Books
- "High Performance Browser Networking" — Ilya Grigorik (free online)
- "Designing Data-Intensive Applications" — Martin Kleppmann
- "Refactoring" — Martin Fowler
- "You Don't Know JS" — Kyle Simpson (free on GitHub)
- "Inclusive Components" — Heydon Pickering
- "Atomic Design" — Brad Frost (free online)
- "Staff Engineer" — Will Larson
- "The Manager's Path" — Camille Fournier
- "Accelerate" — Forsgren, Humble, Kim (DORA)
- "An Elegant Puzzle" — Will Larson
44.8 Newsletters Worth Subscribing
- Bytes (Ui.dev)
- The Pragmatic Engineer
- This Week in React
- Frontend Focus
- Smashing Newsletter
- CSS Weekly
- JavaScript Weekly
- LeadDev
44.9 Closing Note
45Market Reality — What Top Companies Actually Hire For
Distilled from 2026 Senior/Lead Frontend Engineer job descriptions at Airbnb, Anthropic, Vercel, Netflix, Uber, Stripe, Meta. Use this to calibrate what really matters.
45.1 The Universal Bar (in every JD)
- 5+ years of professional experience; 2+ years on consumer-facing or production-scale apps.
- Deep React + TypeScript — table stakes, not differentiator. Advanced TS (generics, conditional types, discriminated unions) explicitly mentioned.
- Core web fundamentals — HTML semantics, CSS layout, browser internals, network protocols. Not assumed; tested.
- Performance ownership — Core Web Vitals literacy, real-user monitoring, perf budgets.
- Accessibility — WCAG 2.2 AA mentioned in every senior+ JD post-EAA (June 2025).
- Testing strategy — not just "writes tests" — owns testing philosophy across unit/integration/E2E.
- System design ability — verbal walkthrough of large frontend architectures.
- Collaboration evidence — cross-functional with design, product, backend, infra.
45.2 Company-Specific Emphasis Patterns
| Company | What they weight heaviest | Distinctive ask |
|---|---|---|
| Airbnb | System design & cross-team work; design system literacy | GraphQL + networking platform; design-language consistency across 50+ surfaces |
| Anthropic | AI/LLM product UX, streaming UIs, RSC mastery; deep React 19+ | Building agent interfaces; tool-call rendering; safety-aware UX |
| Vercel | Next.js App Router internals; Edge runtime; perf at scale | RSC, streaming SSR, framework contribution mindset |
| Netflix | System design (highest weight); behavioral fit; project deep-dive | Media/video streaming UX; A/B experimentation discipline; minimal coding-puzzle focus |
| Uber | Coding (CodeSignal OA), DSA fundamentals, then system design | Real-time / map-heavy UX; high-scale dispatch UI |
| Stripe | API ergonomics; developer experience; correctness | Forms, money, type-safe end-to-end; long PR review culture |
| Meta | Relay/GraphQL, custom infra, scale | Owns parts of React itself; expects RFC literacy |
| Figma | Canvas, WASM, CRDT, low-latency collab | Renders at 60fps under multiplayer load |
| Linear | Local-first architecture; sync engines; perceived instantness | Optimistic UI, IndexedDB, custom state engine |
| Notion | Document editing, schemas, collaborative state | Block-based editor architecture; performance at large doc sizes |
| Shopify | Storefront perf (Hydrogen), CSS-in-JS replacement, edge SSR | Multi-tenant theming; Remix/RR7 ecosystem |
45.3 The Hidden Bar — What Senior Means in 2026
From Noor Mohamad — Six FE Capabilities (May 2026) and MockExperts — FE Engineering 2026:
- Rendering pipeline literacy — explain LCP and CLS from the browser's perspective, not from Lighthouse output.
- Network & performance optimization — at the same depth a backend engineer understands DB indexing.
- Server vs client boundary for RSC — knowing what runs where, why, and the perf consequence.
- Architectural opinion — Module Federation vs single-spa vs iframe; defend a position.
- Testing as a system — pyramid shape, flake management, what to skip.
- Product judgment — pushing back on requirements that hurt users.
45.4 What "Lead" Adds on Top of Senior
- RFC / ADR authorship — written communication is the leverage point.
- Cross-team influence without authority.
- Mentoring 2–4 engineers with measurable growth.
- Migration leadership — bringing a team off a deprecated stack without melting velocity.
- Incident command experience — has run a production incident as IC.
- Hiring contributions — interview loop owner, candidate calibration sessions.
45.5 Decoded — How to Read Between the JD Lines
| JD phrase | What it actually means |
|---|---|
| "Own the technical roadmap" | Expect 30% time on RFCs and 1:1s, not coding. |
| "Work in ambiguity" | Product hands off vague problems; you scope, prioritize, ship. |
| "High leverage" | Building platforms others use, not features users see directly. |
| "Production-grade" | Observability + on-call + perf budgets baked in from day 1. |
| "Bias for action" | Ship a prototype this week, not a design doc this month. |
| "Raise the bar" | Your hiring decisions and code reviews carry weight beyond your own work. |
| "Customer obsession" | You read user research; you sit with the support inbox monthly. |
45.6 References
- Airbnb — Senior FE Engineer, Reliability Experience
- Airbnb — Senior FE, GraphQL & Networking Platform
- Anthropic Careers
- Anthropic comp data — Levels.fyi
- Prepfully — Uber FE interview process
- Exponent — Netflix SWE interview 2026
- Glassdoor — Vercel Senior SWE
- FrontendLead — Netflix FE questions
- FrontendLead — Uber FE questions
- interviewing.io — Netflix interview guide
46Staying Current — A Sustainable Learning System
The field shipped more in the last 3 years than the prior decade. The signal you can keep up — not that you already know it — is what gets you hired and keeps you employable.
46.1 The Layered Learning Routine
| Cadence | What to do | Time |
|---|---|---|
| Daily (15 min) | Skim a curated newsletter or RSS feed; star one item to read deeply later | ~15 min over coffee |
| Weekly (1–2 hr) | Read one deep technical article from a starred queue; try one new library/feature in a sandbox | Friday afternoon or weekend |
| Monthly (3–4 hr) | Build a small project with one new tech you've been curious about; write a 1-page brief on what you learned | One Saturday |
| Quarterly | Audit your toolkit — what to drop, what to add; attend or watch one conference | 2-day block |
| Yearly | Pick one "stretch" topic outside daily work (compilers, ML, systems, DBs) — depth over breadth | Dedicated 20% time |
46.2 Daily — Newsletters & RSS
Curate ruthlessly. Subscribing to 30 newsletters is the same as zero — you'll mark them read without reading.
- Bytes — short, funny, weekly. Best entry-point newsletter.
- The Pragmatic Engineer (paid) — Gergely Orosz; engineering culture at scale.
- This Week in React — Sébastien Lorber; comprehensive React + RN.
- Frontend Focus — Cooperpress; weekly link roundup.
- JavaScript Weekly — Cooperpress; language news.
- CSS Weekly — Zoran Jambor; CSS-only.
- TypeScript Weekly — language updates.
- LeadDev — engineering leadership; staff+ focus.
- System Design Newsletter — Neo Kim; weekly architecture explainer.
- Engineering Leadership — Gregor Ojstersek.
46.3 Weekly — Deep-Dive Sources
- Web platform releases — web.dev blog, Chrome for Developers, WebKit blog, Mozilla Hacks.
- React — react.dev/blog, React Working Groups discussions, overreacted.io.
- Frameworks — Next.js blog, Remix/RR blog, Vercel blog, Svelte blog.
- Engineering blogs — see Section 44.2.
- RFCs / proposals — TC39, WHATWG HTML, CSS WG drafts.
46.4 Communities Worth Joining
- Twitter/X — still where new releases break first. Curate aggressively; mute liberally.
- Bluesky — increasingly where web standards / React people are migrating.
- Reactiflux Discord — React-focused community.
- r/reactjs, r/javascript, r/typescript, r/webdev, r/ExperiencedDevs.
- Hacker News — discover; don't doom-scroll.
- Local meetups — Meetup.com, LeadDev events, framework-specific.
46.5 Conferences to Watch (recordings are free)
- React Conf (Meta)
- Reactathon / React Miami / React India regional
- Next.js Conf
- JSNation (Amsterdam)
- React Summit
- CSSConf EU
- SmashingConf
- LeadDev (leadership)
- Staff+ Summit
- Google I/O Web track
- Apple WWDC Web sessions
46.6 Podcasts (commute material)
- Syntax — broad, beginner-friendly.
- ShopTalk Show — CSS-heavy.
- JS Party — language, ecosystem.
- Full Stack Radio — Adam Wathan (Tailwind).
- PodRocket — LogRocket, modern stack.
- React Podcast.
- Stack Overflow Podcast.
46.7 Long-Form & Books (quarterly)
See Section 44.7 — Books. Build a 2-books-per-quarter habit; mix one technical (e.g., DDIA) with one leadership (e.g., Staff Engineer).
46.8 The "Read on Schedule" Stack
Set up an RSS reader (Feedly, Inoreader, Reeder). Subscribe to engineering blogs (Section 44.2), newsletters, GitHub release feeds for libraries you use. Read for 15 min daily; never let the queue build past 100.
46.9 Track What You Learn
Keep a personal "learning journal" — a markdown file, an Obsidian vault, a Notion page. One entry per learning, ~3 sentences: what, why it matters, link to source. After a year you'll have 200+ entries — interview gold, promotion packet evidence, blog-post seed material.
47Practice Platforms & Exercise Bank
Reading about interviews ≠ being ready. Practice with the same intensity and structure you'd practice a musical instrument.
47.1 The Top Practice Platforms (2026)
| Platform | Strengths | Best for |
|---|---|---|
| GreatFrontEnd | 500+ questions, in-browser code, prep plans, ex-FAANG authors | End-to-end FE interview prep; system design + coding combined |
| FrontendLead | 300+ practice questions; company-specific filters (Netflix, Uber, Stripe) | Targeting a specific company; system-design walkthroughs |
| BFE.dev | JS/React quizzes with auto-graded tests; daily challenges | Sharpening JS internals (implement Promise, debounce, deep clone) |
| FE Interview Handbook | Free, structured, comprehensive; now part of GreatFrontEnd | Starting point; foundational concepts |
| Pramp | Free peer-to-peer mock interviews | Live practice with another candidate — invaluable |
| interviewing.io | Anonymous mock interviews with FAANG engineers (paid) | High-stakes mock with detailed feedback |
| LeetCode | DSA + occasional frontend; Uber-style OAs | CodeSignal/HackerRank-style screens |
| CodeSignal | Used by Uber, Meta, others for OAs | Familiarize with the actual platform |
| HackerRank | Frontend skills tracks | Algorithmic warm-up |
| Frontend Masters | Video courses on advanced topics | Filling specific gaps — RSC, accessibility, perf |
| Epic React (Kent C. Dodds) | Workshop-style React deep-dive | Solidifying React fundamentals + advanced patterns |
| Total TypeScript (Matt Pocock) | Interactive TS exercises | Leveling up the type system |
47.2 Curated Practice Problems by Level
Warm-up (30 min each)
- Implement
debounce,throttle,memoize,curry. - Implement
Promise.all,Promise.allSettled,Promise.race,Promise.any. - Deep clone an object (without
structuredClone); flatten a nested array; group by. - Implement EventEmitter / pub-sub.
- LRU cache.
- String compare with version semantics (1.2.10 vs 1.2.2).
Component-level (45–60 min)
- Build an autocomplete with debounce, cancellation, keyboard nav, ARIA.
- Build a virtualized list (no library).
- Build a modal with focus trap, ESC, click-outside, restore focus.
- Build a multi-step form wizard with URL state per step.
- Build infinite scroll using IntersectionObserver.
- Build a star-rating component (controlled + uncontrolled).
- Build a sortable / draggable list (mouse + keyboard).
- Build a tabs component with the Compound pattern + ARIA.
- Build a tooltip that auto-positions (collision detection).
- Build a video player with custom controls + captions toggle.
Mini-app (90–120 min)
- Pokemon / Starwars API explorer (from your existing probe exercises).
- Tic-tac-toe → Connect 4 → Chess board (UI only).
- Real-time stock ticker (WebSocket / SSE).
- Kanban board with drag-drop and persistence.
- Markdown previewer with syntax highlighting.
- Pomodoro timer with persistence + notifications.
- Reddit-style nested comment thread.
System design (45–60 min verbal)
- Twitter / X feed.
- Slack / chat client.
- Google Docs / collaborative editor.
- Autocomplete (Google search bar).
- Photo sharing (Instagram-like).
- Video streaming UI (Netflix-like).
- E-commerce checkout flow.
- Email client.
- Stock trading dashboard.
- Multi-tenant admin dashboard.
47.3 The 6-Week Interview Sprint Plan
Audit + plan
Take 3 BFE.dev quizzes, 2 GreatFrontEnd questions, 1 system design problem. Identify weak areas. Write a learning plan with 2 weak areas per week.
Deep-dive on closures, async, hooks internals
5 BFE.dev/day implementing language primitives. Re-read React docs hook by hook. Build one component-level exercise.
Build 5 component exercises end-to-end
Build with full a11y, error states, loading. Record yourself explaining the build (record your screen).
3 verbal system designs with the RADIO framework
News feed, autocomplete, chat. Time-box 45 min each. Record audio; play back; cringe; iterate.
Schedule 2 Pramp + 1 paid interviewing.io
Get external feedback. Fix the top 2 issues each mock identifies before the next.
STAR-format 8 stories; review communication snippets
Record yourself answering "tell me about a time" prompts. Tighten openings, prune tangents, end with measurable outcomes.
47.4 Build a Visible Portfolio Project
One real project under your GitHub beats five toy exercises. Pick a real problem; ship to production; write a 2-page README that includes:
- Problem statement (one paragraph).
- Architecture diagram.
- Trade-offs you considered and the one you picked, with rationale.
- Performance budget + measured results (Lighthouse / RUM).
- Accessibility audit (axe / Lighthouse).
- What you'd do differently.
This becomes the "tell me about a project" anchor in every interview.
47.5 References
48Technical Communication Snippets — Sound Like a Lead
Memorize these. They are the verbal scaffolding that makes ordinary technical content sound like senior-engineer reasoning. Use the exact phrases; over time they become natural.
48.1 Opening a Coding Problem
The first 60 seconds set the tone. Never start typing. Always restate + clarify + plan.
48.2 Talking While Coding
Silent coding feels long to the interviewer. Narrate your thought process — but only the non-obvious parts.
useState here rather than useReducer because the state is simple — one boolean. If this grew to three or four interrelated fields, I'd probably switch."48.3 When You Don't Know Something
"I don't know" delivered confidently is one of the strongest signals. Faking knowledge is the fastest way to fail.
48.4 Explaining Trade-offs (the Lead Signal)
The single most under-used phrase in interviews. Use "trade-off" 5+ times per interview.
48.5 Handling Pushback or Disagreement
Lead candidates are tested on whether they can be challenged without crumbling — and without dying on the hill.
48.6 Wrapping Up an Answer
Bad answers trail off. Good answers land.
48.7 System Design Interview Phrases
48.8 Behavioral (STAR) Phrases
48.9 Questions to Ask the Interviewer (End of Loop)
Asking good questions is half the interview signal. Have 5–6 prepared; pick based on what you've heard.
48.10 Confidence-Building Verbal Hygiene
| Replace | With | Why |
|---|---|---|
| "I think maybe…" | "My initial take is…" or "I'd lean toward…" | Sounds tentative without sounding hedgy |
| "This is probably wrong, but…" | "Here's my best thinking…" | Don't pre-undermine yourself |
| "Does that make sense?" | "Did I answer your question?" or "Want me to go deeper anywhere?" | The first sounds insecure; the second invites engagement |
| "I'll try to…" | "I'll…" | Eliminate hedge verbs |
| "Sorry, just one more thing…" | "One more point worth adding…" | No apologies for adding value |
| "I'm not an expert but…" | (omit entirely) | The interviewer didn't ask for credentials |
| "Um", "like", "you know" | Silence | 2 seconds of silence sounds confident; "umm" sounds nervous |
| Uptalk (rising intonation on statements) | Declarative downward tone | Statements should sound like statements |
48.11 Quick Rehearsal Drills
- Mirror drill — answer 3 behavioral questions out loud to your mirror, twice a week. You'll instantly hear filler words.
- Recording drill — record yourself answering a system design question. Play back at 1.5× speed; the awkward moments compress into obvious patterns.
- 2-sentence drill — every technical concept you know, write a 2-sentence explanation. Forces compression. (Try: hydration, CSP, useMemo, RSC, INP.)
- Trade-off drill — every time you read about a tech, write down its trade-offs vs the alternative. After a month, this is reflexive in conversation.
- "Why" drill — when someone explains a decision to you, ask "why" 3 times. Then practice answering 3 levels deep on your own decisions.
48.12 References
49Mock Interview Drills — Self-Practice Routines
Solo practice beats no practice. Structured solo practice beats unstructured group practice.
49.1 The Daily 45-Minute Routine
| Block | Time | What |
|---|---|---|
| Warm-up | 5 min | One BFE.dev problem — implement a primitive |
| Coding | 20 min | One component-level exercise, talking out loud (no music, no silence) |
| System design | 15 min | Verbal walkthrough of one design problem, with timer; record audio |
| Reflection | 5 min | Watch/listen back to one moment; note one phrase to improve |
49.2 The Weekly Mock
Once a week, do a full 45–60 minute mock with someone else. Options:
- Pramp — free peer matches; reciprocal practice.
- interviewing.io — paid mocks with ex-FAANG engineers.
- A friend in the industry — trade mocks; honest feedback > polite feedback.
- An AI mock — use Claude / ChatGPT to role-play the interviewer; surprisingly effective for behavioral practice.
49.3 The Recording Loop (the highest-ROI drill)
- Pick a problem. Set a 45-minute timer.
- Talk it out loud as if interviewer is in the room. Record screen + audio.
- Stop at 45 min regardless of completion.
- Watch it back at 1.5× speed.
- Note 3 specific things — one verbal habit, one missed concept, one structural issue.
- Pick one to fix; redo the next day.
49.4 The Behavioral Story Workshop
- Make a list of 8 stories from your career (use Section 42.2 categories).
- For each, write a STAR outline (4 bullets, max 200 words).
- Practice each out loud — target 90 seconds for "tell me about a time" answers.
- Time yourself; if you exceed 2 minutes, you're rambling. Trim.
- Get a friend to ask follow-ups — "what specifically did you do?", "what was the metric?" — to stress-test your answer's specifics.
49.5 The AI Rubber-Duck Loop
Use Claude or ChatGPT as a relentless follow-up generator. Prompt template:
You are a senior frontend engineer interviewing me for a Lead role. Ask me [X — e.g., a system design question for "design Twitter feed"]. After my answer, ask 3-5 follow-up questions that probe weak spots. Be tough but constructive. Do not give answers — only ask.
The AI will probe corners you didn't anticipate. Better than a friend who doesn't know the domain; cheaper than a paid mock.
49.6 The "Explain to a Junior" Drill
For every concept you intend to discuss in an interview, prepare two versions:
- 30 seconds — what it is, why it matters, one example.
- 3 minutes — the same plus trade-offs and one war story.
If you can't compress to 30 seconds, you don't understand it yet. Compression is mastery.
49.7 The Failure-Mode Calendar
Track your interview attempts in a simple table:
| Date | Question | What I did well | What broke | Fix for next time |
|---|---|---|---|---|
| Apr 14 | Build autocomplete | Asked clarifying Qs | Forgot ARIA combobox role | Re-read APG combobox; do 1 more autocomplete |
| Apr 16 | Design news feed | RADIO structure | Glossed over caching; got cornered | Re-read CDN section; rehearse cache-invalidation answer |
This becomes your personalized weakness map.
49.8 Mock Interview Templates to Run Yourself
Template A — JS / TS warm-up (15 min)
- Implement a debounce with cancel.
- Type a generic
pickfunction with full key inference. - Explain a stale closure and how you'd fix it.
Template B — Component build (45 min)
- Build an accessible modal with focus trap.
- Discuss state management choice mid-build.
- Add keyboard handling under interviewer probe.
Template C — System design (45 min)
- Run RADIO end-to-end on a feed/chat/editor problem.
- Force yourself to draw (paper or whiteboard).
- Stop at 45 min — even mid-thought.
Template D — Behavioral (30 min)
- 5 rotating prompts: failure, conflict, leadership, mistake, scope-cut.
- Limit each answer to 90 seconds.
- Self-grade: did you say "I" or "we"? Specific or vague? Quantified outcome?
50Communication Anti-Patterns — What Kills Interviews
Even strong engineers tank interviews on these. Most are habits you can break in 2 weeks of deliberate practice.
50.1 The Top 10 Killers
- Silent coding. The interviewer can't read your mind. 5 minutes of silent typing reads as "doesn't know what they're doing."
- Diving in without clarifying. Skipping requirements is the #1 reason senior candidates get downleveled. Spend 3–5 minutes asking.
- Saying "we" instead of "I". Behavioral round killer. Interviewers explicitly listen for "I" — they want to know your contribution.
- Rambling. Hard cap your answers at 2 minutes; pause and ask "want me to keep going?"
- Pretending to know. Always fails. Interviewers ask exactly the question they know you don't know to test honesty.
- Defending a wrong answer to the death. Showing you can update is more important than being right.
- Not asking any questions back. Reads as low curiosity. Always have 5 prepared.
- Filler-word storms. "Um", "like", "kind of", "sort of", "basically" — each one chips at your authority.
- Pre-undermining. "This is probably wrong but…" — never. State your answer; let them judge.
- Tangents. Answering a different question than the one asked. Listen to the actual question; answer the actual question.
50.2 Body Language & Presence (Video Interview)
- Camera at eye level — not below, not above. Stack books under your laptop.
- Look at the camera when delivering a key point, not at the screen.
- Lighting in front of you, not behind — face a window, not back to one.
- Quiet background — no notifications, phone on silent in another room.
- Sit up, hands visible — slouching reads through camera.
- Smile in the first 10 seconds — it sets the room temperature.
- Don't read from notes mid-answer — eye drift is obvious. Notes for question prompts only.
50.3 The "Sound Senior" Vocabulary Substitutions
| Junior phrasing | Senior phrasing |
|---|---|
| "It's hard to say" | "It depends on the trade-off between X and Y" |
| "This is easy" | "There are a few subtle points worth being explicit about" |
| "I've never done that" | "I haven't worked with that directly, but the principle I'd apply is…" |
| "I would probably…" | "My default would be… unless [condition]" |
| "Just" | (remove) — "just" minimizes complexity and signals naïveté |
| "Obviously" | (remove) — if it were obvious, they wouldn't ask |
| "Quickly" | "Concisely" / "at a high level" |
| "I feel like" | "My read is" / "the evidence suggests" |
| "Sorry" | (reserve for actual mistakes; don't reflex-apologize) |
50.4 Specific Failure Modes to Train Away
50.5 What to Do If You Freeze
- Acknowledge it. "Give me 30 seconds — I want to think through this one." Then actually take 30 seconds. Don't talk through the silence.
- State the problem out loud. Restating often unsticks you. "So we need to [X], the constraint is [Y]…"
- Reach for first principles. "Let me reason from basics — what does the user need?"
- Reach for an analogous problem. "This reminds me of [other problem]. Is the same shape applicable here?"
- If still stuck, ask for a hint. "I'm not seeing the obvious path forward. Could you give me a nudge?" — interviewers expect this; using it once is fine.
50.6 Energy & Pacing
- Match interviewer energy. If they're warm, be warm. If they're terse, be precise.
- Slow down on important points. Rushing through a key trade-off signals you don't realize it's important.
- Take water breaks. Sipping water is a legitimate way to buy 3 seconds. Keep a glass in frame.
- Don't fill silence. 5 seconds feels long to you; sounds confident to them.
- End on a high note. The last 2 minutes are remembered most. If you stumbled mid-interview, finish strong with a thoughtful question and a clear closing.
50.7 The "Last 10 Minutes" Playbook
- If anything went unfinished, address it: "Earlier I said [X] — I want to come back and clarify."
- Ask your prepared questions (Section 48.9). Pick 2–3 based on what the conversation revealed.
- Show genuine interest in their answers — follow up on at least one.
- Express your specific interest: "What you said about [X] is exactly the kind of problem I'd want to work on. I'd love to hear more about that team."
- Thank them warmly and concretely — "Thanks for the conversation — I particularly enjoyed the [X] discussion."
50.8 After the Interview
- Write a thank-you note within 24 hours. 3–4 sentences. Reference something specific from the conversation.
- Journal what went well and what didn't — while it's fresh. This is your most valuable learning data.
- Don't replay endlessly. Two passes: one for lessons, one for closure. Then move on.
- Treat rejection as data, not verdict. A rejection from one company calibrates one signal — not your worth.
50.9 The 30-Day Communication Improvement Plan
Awareness
Record yourself answering 3 behavioral and 1 technical question per day. Just listen back — don't edit yet. Note 3 patterns by end of week.
Fillers + Apologies
Eliminate "um", "like", "basically", "sorry". Listen for each in playback. Replace with silence or specific phrases from Section 48.
Structure
Force every answer into one of three templates: (1) Direct answer + supporting detail, (2) Trade-off frame, (3) STAR. No freeform.
Mocks
3 external mocks (Pramp, interviewing.io, or peer). Apply the previous 3 weeks. Collect feedback; revise the worst-rated dimension.
50.10 Final Word
Two weeks of deliberate practice on the snippets, anti-patterns, and drills in Sections 48–50 will move you up half a level in every interview you take. Not because the underlying skills change — because the signal you radiate does.
50.11 References
51JavaScript Core — Everything an Engineer Should Know
Past the syntax. The model. What the engine actually does. Every snippet below is editable and runnable — experiment, break things, change values, hit Run again. This is the section to come back to before any senior interview.
51.1 The Execution Model — Stack, Heap, Queues, Loop
JavaScript is single-threaded with a concurrency model built on the event loop. The runtime has:
- Call stack — synchronous function frames; LIFO.
- Heap — where objects live; managed by the GC.
- Macrotask queue —
setTimeout, I/O, UI events, message events. - Microtask queue — Promise reactions,
queueMicrotask,MutationObserver. Drained completely between every macrotask. - Render steps —
requestAnimationFramecallbacks → style/layout/paint →requestIdleCallback.
await works at top level
51.2 Closures, Scope & Hoisting
A closure is a function that retains access to its lexical scope after that scope has finished executing. Lexical scope is fixed at write time, not call time. Closures power: data hiding, module patterns, currying, memoization, React hooks themselves.
var loop sees the final value of i after the loop completes. let/const create a new binding per iteration, which is why each closure sees a different value. This also explains why mutating the captured variable inside or outside the closure is visible on both sides.51.3 The this Binding
Four precedence rules + one exception for arrows:
newbinding —thisis the newly constructed object.- Explicit binding —
.call(obj)/.apply(obj, args)/.bind(obj). - Implicit binding — method call
obj.fn();thisisobj. - Default —
undefinedin strict mode; global in sloppy.
Arrows have no this of their own — they capture the enclosing lexical this.
51.4 Prototypes & Inheritance
Every object has an internal [[Prototype]] pointer (accessible via Object.getPrototypeOf) forming a prototype chain. Property lookups traverse this chain. class is sugar over function prototypes.
51.5 Type System & Coercion Rules
JS has 8 types: string, number, boolean, null, undefined, symbol, bigint, object. Coercion happens with ==, +, -, <, etc. Understanding the rules is the difference between writing code and debugging it.
51.6 Promises & Async Internals
A Promise is a state machine: pending → fulfilled | rejected. Once settled, it never changes. Promise reactions are microtasks. Understanding microtask scheduling explains most async surprises.
51.7 Iterators & Generators
The iteration protocol underpins for…of, spread, destructuring, Array.from. Generators give you lazy, pausable functions. Async generators stream data.
51.8 Proxy & Reflect — Meta-Programming
A Proxy intercepts fundamental operations on an object (get, set, has, deleteProperty, etc.). This is how reactivity systems (Vue 3, MobX 6, Valtio) work — and how some bundlers do automatic dependency tracking.
51.9 Memory — GC, Weak References, Leak Patterns
V8 uses generational GC: young generation (fast Scavenger) and old generation (Mark-Sweep + Mark-Compact). You don't free memory — you stop referencing it.
WeakMap,WeakSet— keys held weakly; GC can collect them.WeakRef— hold a reference that doesn't prevent collection.FinalizationRegistry— cleanup hook after GC.
- Forgotten event listeners on removed DOM nodes.
- Long-lived closures capturing large objects.
- Module-level arrays that only grow.
- Detached DOM nodes still referenced by JS.
- Timers (
setInterval) not cleared on unmount. - Subscriptions / observables without teardown.
51.10 Symbols & Well-Known Symbols
A Symbol is a unique primitive — used as a hidden / collision-proof property key. Well-known symbols let you customize built-in behavior.
51.11 Property Descriptors — Below the Dot
Every property has hidden flags: writable, enumerable, configurable, plus either a value (data descriptor) or get/set (accessor descriptor). This is how Object.freeze, const-like read-only behaviour, and computed properties work under the hood.
Three levels of immutability:
Object.preventExtensions— can't add new properties.Object.seal— above + can't delete or reconfigure.Object.freeze— above + can't modify values. Shallow — nested objects still mutable.
51.12 Modules — ESM, CJS, Dynamic, Top-Level Await
| Feature | ESM | CommonJS |
|---|---|---|
| Loading | Static, async, parallel | Synchronous, blocking |
| Resolution | At parse time | At runtime |
| Bindings | Live (read-only views of exports) | Copy of the value at require time |
| Circular deps | Resolved via live bindings (with TDZ risk) | Partial exports possible (gotcha) |
| Tree-shakable | Yes | No |
Top-level await | Yes | No |
// ESM
import { fn } from './mod.js'; // static; tree-shakable
const mod = await import('./mod.js'); // dynamic; code-splitting
export const x = 1;
export default function () {}
// Import maps (browser, Deno, modern bundlers)
<script type="importmap">
{ "imports": { "lodash": "https://esm.sh/lodash-es" } }
</script>
<script type="module">import _ from 'lodash';</script>
// CJS — Node legacy
const { fn } = require('./mod');
module.exports = { fn };
51.13 Numbers, BigInt & Intl
51.14 Strings, Unicode & Code Points
Strings are sequences of UTF-16 code units. Most "characters" you care about are code points, some of which take two code units (surrogate pairs). This bites when emoji or non-BMP scripts appear.
51.15 Modern Regex
Named groups, lookbehind, the unicode /v flag with set notation, sticky /y for tokenizers.
51.16 Functional Patterns You'll Actually Use
51.17 Error Handling — Beyond try/catch
51.18 Modern Array Methods — Mutating vs Immutable
| Mutating | Immutable (ES2023+) |
|---|---|
sort() | toSorted() |
reverse() | toReversed() |
splice() | toSpliced() |
copyWithin() | with(index, value) |
51.19 Modern Scheduling APIs
Beyond setTimeout: the Scheduler API gives priority-aware task scheduling. scheduler.yield() is the modern way to break up long tasks for better INP.
51.20 Lower-Level Topics — Performance, Memory Layout, Engine Quirks
V8 Hidden Classes & Inline Caching
V8 assigns each object a hidden class based on its property layout. Adding properties in the same order to many objects keeps them on the same hidden class → fast. Adding in different orders creates separate hidden classes → slow polymorphic access.
Typed Arrays — Contiguous Memory
Regular arrays are sparse object-like. Int32Array, Float64Array, etc. are contiguous fixed-type buffers — 10–100× faster for numeric work.
Tail Calls, Recursion Limits, Stack Depth
JS engines (except Safari briefly) don't implement proper tail call optimization. Deep recursion blows the stack. Solution: iterative form, or trampoline pattern.
Object Identity vs Equality
JS has four equality semantics: === (Strict Equality), == (Loose Equality), Object.is (SameValue), and SameValueZero (used by Map/Set/Array.includes).
51.21 Interview Classics — Implement From Scratch
These are the most-asked "implement X" questions at FAANG/Anthropic/Vercel. Practice each in the editor; aim to type them from memory.
51.22 Low-Level Building Blocks for Product Work
Structured Cloning & Transferable Objects
const cloned = structuredClone(complexObject); // deep clone with cycles, Maps, Dates // Transferable (zero-copy ownership transfer to a Worker) const ab = new ArrayBuffer(1024 * 1024); worker.postMessage(ab, [ab]); // `ab` is now neutered on this side
SharedArrayBuffer + Atomics (multi-thread shared memory)
Requires Cross-Origin-Opener-Policy: same-origin + Cross-Origin-Embedder-Policy: require-corp. Used by: video editing in browser, WASM threads, audio processing.
BroadcastChannel — cross-tab pub/sub
Performance APIs
// High-resolution timing
const start = performance.now();
doWork();
console.log(performance.now() - start, 'ms');
// User Timing API — show up in DevTools Performance panel
performance.mark('checkout-start');
performance.mark('checkout-end');
performance.measure('checkout', 'checkout-start', 'checkout-end');
// PerformanceObserver — listen for long tasks, layout shifts, LCP
new PerformanceObserver(list => {
list.getEntries().forEach(e => console.log(e.entryType, e.duration));
}).observe({ entryTypes: ['longtask', 'layout-shift', 'largest-contentful-paint'] });
Long Animation Frames (LoAF) — replaces Long Tasks
The successor API for INP debugging. Reports per-frame work + script + render time. web.dev — Long Animation Frames
51.23 Hard JS Questions Asked at Top Companies
await interacts with the microtask queue. What's the order of execution in async function a() { await b(); console.log('after'); }?await desugars to a Promise then. The continuation after the await is scheduled as a microtask once the awaited value resolves. So console.log('after') runs in a microtask after b() resolves — meaning all synchronous code after the a() call runs first, then microtasks drain in order.flushSync opts out for cases where you need synchronous DOM updates (e.g., before a measurement).Object.freeze and a deep freeze?Object.freeze is shallow — nested objects remain mutable. Deep freeze requires recursion: walk own properties, freeze each object value. Watch out for circular references (use a WeakSet). For runtime-enforced deep immutability, prefer libraries like Immer (structural sharing) or persistent data structures (Immutable.js, Mori).reject(err) explicitly.useState using only closures and an array?useState increments the index and either initializes or reads its slot. Setters capture their slot index in a closure. This explains why hook calls must be ordered consistently across renders — the slot index is positional, not symbolic. (The real React uses a linked list per fiber, not a module array, so each component instance has its own list.)delete (transitions to dictionary mode); avoid mixing types in arrays (PACKED_SMI_ELEMENTS > PACKED_DOUBLE_ELEMENTS > PACKED_ELEMENTS > HOLEY_ELEMENTS).51.24 References for Deep Mastery
- You Don't Know JS (Kyle Simpson)
- Exploring JS (Dr. Axel Rauschmayer)
- V8 Engineering Blog
- Mathias Bynens — JS Unicode
- 2ality — Axel's posts on TC39 proposals
- ECMAScript 262 spec (the standard)
- TC39 active proposals
- Sudheer Jonna — JS Interview Questions
- Lydia Hallie — JavaScript Questions
- BFE.dev — practice implementing primitives