CodeSignal Front-End Development Assessment: Four Levels of UI and API Practice

Prepare for CodeSignal Front-End Development with four UI practice stages, API normalization, selection rules, regression tests, and environment checks.

Author: PracHub

Published: 9/9/2026

CodeSignal Front-End Development Assessment: Four Levels of UI and API Practice

September 9, 2026

Quick Overview

Prepare for the CodeSignal Front-End Development Assessment with a clear explanation of the official four-level framework, supported environments and evidence limits. Work through an original event-registration UI, tested selection logic, API normalization and a cumulative regression matrix that preserves earlier behavior as requirements grow.

Frontend EngineerFree

The CodeSignal Front-End Development Assessment is best prepared for as an application that grows across successive requirements. A screen that works with static data can fail as soon as an API changes the payload or a new filter changes which records are visible. Your preparation should expose those failures before the timer starts.

Our preparation thesis: build a small interface, add one requirement at a time, and rerun the earlier acceptance checks after every change. The event-registration exercise below is original PracHub practice, not a CodeSignal question or a prediction of your employer's task.

Use PracHub's Frontend Engineer questions for targeted follow-up practice once you identify whether layout, state, or asynchronous behavior is slowing you down.

Four stages of an event-registration interface: render, interact, connect, and extend

What the official four-level framework confirms

Official facts: CodeSignal's published framework describes four progressive levels with a maximum completion time of 90 minutes and scores from 200 to 600. The sequence covers basic layout and rendering, dynamic interaction, API consumption, and extending the design for related requirements. Level four tests how an existing solution accommodates change rather than introducing a separate fundamental skill category. These are specifications of that framework, not proof that every employer-created CodeSignal assessment follows it. CodeSignal's Front-End Development framework.

Official environment information: CodeSignal lists React with JavaScript or TypeScript, Vue with JavaScript or TypeScript, and Angular with TypeScript for this certified assessment. Check your invitation and available environment before choosing a practice stack; this list does not establish that every dependency you use locally will be installed. CodeSignal's supported environments.

Candidate report: one Reddit author described TypeScript diagnostics in a React starter project and said switching to JavaScript removed the issue. That is an individual account with an unverified diagnosis, not evidence that the editor is generally broken or that changing languages is always possible. We did not establish two independent same-cycle reports of a recurring task. The candidate's environment discussion.

Our inference: opening a practice environment and confirming how to run, preview, and inspect errors is useful preparation. It is not a reason to spend your assessment rewriting the starter configuration without first identifying the actual failure.

An original exercise that grows across four stages

Build a fictional community-events page. Each event has a stable string ID, title, category, and nonnegative integer number of available places. A visitor can select events for a local shortlist. Selection does not reserve a seat or send a booking request.

That last distinction matters. A local selected count is a UI exercise; real booking availability requires server-side enforcement. Keep the practice contract small enough to finish and explain.

Practice stageNew requirementEarlier behavior to preserve
RenderShow three supplied events and their availabilityAccurate titles, categories, and counts
InteractSelect or deselect an event; block full eventsCorrect content and stable event identity
ConnectLoad an API payload with different field namesSelection and availability rules
ExtendFilter by category and show total selectedHidden selections remain selected

These are our practice stages, not official prompts. Start with e1, a Design workshop with two places; e2, a Data clinic with zero places; and e3, a second Design workshop with one place. Give the two workshops the same displayed title to reveal any accidental reliance on titles as identifiers.

Write down one invariant before coding: the selected set contains valid, available event IDs, independent of the active category filter. That sentence will guide both implementation and testing.

Build the layout and interaction before adding the network

Render one card per event with a heading, category, places count, and a real button. Show “Full” for zero availability. Keep a visible text summary such as “1 selected” so the selection is understandable without relying only on color.

For this exercise, the button's label remains “Select Design workshop,” and its pressed state communicates selection. Duplicate visible titles need additional context in a real interface; include the event ID in this small demo's accessible button name so the two workshops can be distinguished during testing. A production design would usually offer a meaningful date or location instead.

Keep the event data and selected IDs separate. Do not add a second selected flag to every event and then maintain both representations. React's documentation recommends avoiding redundant and duplicated state because synchronized copies are easier to get out of agreement. React's state-structure guidance.

The following function is the framework-independent core. Its contract assumes that the event list already satisfies the exercise's ID and availability rules:

function toggleSelection(selected, events, id) {
  const event = events.find(item => item.id === id);
  if (!event || event.places === 0) return selected;
  const next = new Set(selected);
  if (next.has(id)) next.delete(id);
  else next.add(id);
  return next;
}

Returning a new set for a valid change makes state ownership visible. In React, use a functional state update when the next selection depends on the previous selection. In another framework, keep the same contract while using its supported update mechanism.

Test clicking e1 twice: the count should go from zero to one and back to zero. Clicking the full e2 should not change it. Try a missing ID directly against the function, because a disabled button alone does not prove the state operation rejects invalid input.

Avoid polishing spacing while the displayed count and button state disagree. Fixing the source of truth first makes later visual work less likely to conceal a behavioral defect.

Add an API boundary without rewriting the interface

Now replace the static source with a fictional endpoint whose JSON contains items, using event_id, name, kind, and spots_remaining. Convert that transport shape into your existing UI shape at one boundary.

function normalizeEvents(payload) {
  if (!Array.isArray(payload?.items)) {
    throw new Error("Expected an items array");
  }
  const seen = new Set();
  return payload.items.map(row => {
    if (!row || typeof row.event_id !== "string" ||
        row.event_id.length === 0 || seen.has(row.event_id) ||
        typeof row.name !== "string" ||
        typeof row.kind !== "string" ||
        !Number.isSafeInteger(row.spots_remaining) ||
        row.spots_remaining < 0) {
      throw new Error("Invalid event record");
    }
    seen.add(row.event_id);
    return {
      id: row.event_id, title: row.name,
      category: row.kind, places: row.spots_remaining
    };
  });
}

This exercise rejects a malformed batch rather than quietly dropping records. That is a deliberate practice policy, not a universal API rule. If partial results are required, define how the UI explains omitted events before changing the validator.

Keep loading, successful empty results, and failure distinct. “No events” should mean a valid empty response, not a failed request. On failure, display a retry action. Disable concurrent reloads in this version so you do not accidentally introduce an unspecified response-order policy.

Technical fact: fetch() does not reject merely because the response has an HTTP error status. Check response.ok, then parse and normalize the body inside the error-handling path. Parsing can also fail. MDN's Fetch guidance.

When fresh data arrives, reconcile selections against the new event list. In our contract, selections for removed or newly full events are cleared. Selections for unchanged available IDs survive. Make that policy visible in the interface; otherwise a visitor may wonder why their count decreased.

A useful counterexample is a selected e1 that returns with zero places after refresh. Preserving the selection blindly breaks the availability invariant, while clearing every selection unnecessarily discards valid choices for e3.

Extend filtering while keeping selection independent

Add an “All,” “Design,” and “Data” category filter. The visible cards are derived from the event list and the active filter. The selected count comes from the complete selected set, not just the cards currently on screen.

Suppose the visitor selects e1, switches to Data, then returns to Design. The Design selection should still be present. If the count becomes zero in the Data view, the interface is mixing “selected overall” with “selected among visible results.” Either metric could be legitimate, but the label and contract must agree.

Do not remove hidden IDs from selection when a filter changes. Visibility is not availability. Reconciliation belongs to accepting new event data, not to calculating a filtered view.

This separation also makes a later requirement easier to discuss. If the product requests “Clear visible selections,” you can remove only the visible IDs. If it requests “Clear all,” clear the complete set. One ambiguous “Clear” button should not silently choose between those operations.

Filtering hides cards; refreshing data reconciles selections against availability

Verify the cumulative contract with a regression matrix

Use a small deterministic fixture and check user-visible outcomes. Each check should expose a different failure mode.

Action or inputExpected outcomeDefect it exposes
Render two events with the same titleTwo distinct cards and controlsTitle used as identity
Select e1, then deselect itCount returns to zeroInconsistent toggle state
Attempt to select full e2Count stays unchangedButton-only validation
Select e1, filter to Data, then backSelection survivesFiltering deletes hidden state
Refresh with e1 full and e3 still availableRemove only invalid selectionsBlind retention or total reset
Return duplicate API IDsVisible error, no partial replacementAmbiguous record ownership
Return a valid empty listEmpty-result messageEmpty and failed requests conflated
Fail the request, then retry successfullyError clears and cards returnRecovery path never exercised

We checked the reference implementation with pure JavaScript assertions and browser interactions. Those checks cover the stated local selection contract; they do not verify a real reservation system, all assistive technologies, or an employer's hidden tests.

During a rehearsal, make one intentional mutation: calculate the selected count from visible cards. Run the filter scenario and watch it fail. Then restore the complete-set count. A test is more convincing when you understand the specific incorrect implementation it rejects.

Rehearse in the environment you will actually use

Before the timed session, confirm the allowed language, framework, startup command, preview workflow, and how test output is displayed. Read the actual assessment rules for outside assistance and references. CodeSignal documents that candidates can revisit rules from the IDE's Rules section; do not infer permission to use an AI tool from its availability elsewhere. CodeSignal's certified-assessment rules.

For a practice run, record when each stage first works and when a later change breaks an earlier check. This produces a useful diagnosis: perhaps API normalization takes three minutes, but recovering from a state reset takes fifteen. Rehearse the expensive failure rather than automatically starting another blank project.

If the starter fails, distinguish an editor diagnostic from a compile error, a server startup failure, and a preview problem. Read the output before modifying dependencies. Capture the specific error through the permitted support route if the environment itself prevents progress.

Near the end, stop adding speculative features. Run the current build, exercise the highest-risk transition, and ensure the required behavior is saved. Our exercise includes useful extensions, but your actual written requirements should determine where you spend the remaining time.

Five questions for focused follow-up practice

These are adjacent practice questions from PracHub, not a CodeSignal question bank or a claim about repeated assessment content.

PracHub questionSkill to rehearse
Build a React naval boardKeep cell identity and derived status consistent after repeated interaction.
Clarify and Implement Search Filters for a Library TableSpecify combined filtering behavior before changing state.
Debug an Angular UI from User ReportsTurn a visible symptom into a reproducible state or lifecycle problem.
Design a Debounced Product Search BoxHandle input changes and asynchronous results deliberately.
Debug Metrics Computed Before FilteringDecide which population a displayed summary actually measures.

Choose the weak point from your rehearsal and practise it in PracHub's Frontend Engineer collection. Then return to the event page and add one change while keeping every earlier acceptance check green.

Sources and Further Reading


Comments (0)