
A frontend take-home assignment gives you a brief, a few hours or a few days, and no interviewer watching you think. That changes what is being judged. In a live machine coding round, an interviewer sees your reasoning as you work. In a take-home, the reviewer sees only what you submit: whether it runs from your instructions, whether it handles the cases the brief did not spell out, how the code is organized and what you wrote down about your choices. This guide covers what reviewers check, how long to spend, what to do about AI tools and how to handle a vague spec. It then follows one worked example, a searchable, paginated Hacker News story list, from the plan to a README you can adapt.
When reviewing a frontend take-home assignment, the first priority is whether the application works as expected. Beyond that, reviewers look at correctness, code quality, edge-case handling, and the overall user experience.
For senior roles, reviewers may also expect stronger architectural decisions, appropriate separation of responsibilities, meaningful tests, and clear explanations of technical trade-offs.
Evaluation priorities vary by assignment. Some place more emphasis on visual accuracy and responsive design, while others focus on code organization, testing, or maintainability. Start by identifying the mandatory requirements and evaluation criteria. Complete those first, then use any remaining time to improve the overall quality of the submission.
Frontend take-home assignments can range from a few hours to several days, depending on the role and the scope of work. Use the time estimate or deadline provided by the employer to plan your approach. If the requirements seem too large for the available time, clarify priorities rather than silently spending significantly more time than expected.
Policies differ by company, so the answer comes from the brief or the company's hiring page. Some companies ask candidates to complete assessments without AI. Others allow it for research if you disclose it and write answers in your own words. Some live formats now expect candidates to use AI tools. Treat a policy as specific to the format it describes, and recheck it before you rely on it, since these pages change.
A practical routine:
Take-home assignments may leave certain requirements open to interpretation. Before implementation, identify anything that could affect the application's behavior, architecture, or scope. Clarify important ambiguities with the recruiter or hiring team rather than making assumptions that could lead to unnecessary rework. A workable approach:
The remaining sections use one small, invented brief. It is not from any company:
> Build a small web app that lets a user search Hacker News stories and browse the results. Use the public HN Search API (no key needed). Requirements: a search box; a list of results showing title, author, points and comment count, with each title linking to the story; pagination; sensible loading, error and empty states. Bonus: tests, accessibility, deploy. Spend about 3 hours. Add a short README covering how to run it, the decisions you made and what you would do next.
We'll use this assignment as a practical example throughout the guide, focusing on planning, implementation decisions, testing priorities, and submission quality rather than the complete application code. The timings below are a plan, not a measurement of how long the build took.
Before designing anything, call the API and read the real response. The HN Search API documents a limit of 10,000 requests per hour per IP, and the endpoint is GET https://hn.algolia.com/api/v1/search?query=<q>&tags=story&page=<n>. Calling it showed several things its documentation page does not spell out:
| What the API returned | What it means for the build |
|---|---|
page is 0-based | The interface shows 1-based pages, so convert at the edge of the code |
For react at 20 results per page, nbHits was 305,341 but nbPages was only 50 | Only the first 1,000 hits are reachable by paging. Observed on the day of writing, not documented |
A query with no matches returns HTTP 200 with hits: [] | An empty state is a success response, not an error |
A page past the end returns HTTP 200 with empty hits, and nbHits and nbPages come back as 0 | nbHits cannot be trusted out of range, so handle an out-of-range page on its own |
"Ask HN" stories have no url key at all, not null | Type url as optional and link to the HN thread when it is missing |
The response sends access-control-allow-origin: * | A browser can call the API directly, with no proxy |
Each row is something a reviewer finds by clicking around, and each becomes an edge case below. The example uses this API instead of GitHub's search API because unauthenticated GitHub search allowed 10 requests per minute, which would make a debounced search fragile while a reviewer clicks around.
Here is one way to divide the three hours.
| Time | What | Commit |
|---|---|---|
| 0:00 to 0:15 | Read the brief twice. Write the edge-case list. Decide scope. Send any question now. | none, notes only |
| 0:15 to 0:30 | Call the API with curl and read the real response. Scaffold Vite, React, TypeScript and Vitest. | "Scaffold app and check API shape" |
| 0:30 to 1:15 | API layer, search with loading, error and success, the list. Make it work first. | "Search and results list" |
| 1:15 to 1:50 | Query and page in the URL, pagination, empty and out-of-range handling. | "Pagination and URL state" |
| 1:50 to 2:25 | Four tests on behavior, not implementation. | "Tests for states and stale responses" |
| 2:25 to 2:45 | Accessibility pass (keyboard, labels, live region, focus) and a manual edge-case pass in the browser. Light styling only. | "A11y and edge-case fixes" |
| 2:45 to 3:00 | README, delete dead code, clone fresh and follow the README steps. | "README" |
Checking the API early prevents the biggest surprises, and the last 15 minutes are for the README and a fresh-clone run.
A take-home is small enough that a reviewer can see every decision. The ones below carried the most weight in the example, with the trade-off behind each. These are the choices to put in your README.
| Decision | What the example does | Trade-off |
|---|---|---|
| How to model request state | One status of loading, error or success instead of separate booleans | A single status cannot be two things at once, so the interface cannot render an impossible combination. It is slightly more typing than two booleans |
| Stale responses | Cancel the previous request when the query or page changes, and ignore any late result | Debouncing makes the race rarer but not impossible, so the example keeps both. GreatFrontEnd's 3 years machine coding guide explains the race and the AbortController fix in detail |
| Where the query and page live | In the URL, with replaceState while typing and pushState for page changes | A refresh, the Back button and a shared link all work, and a reviewer can type ?q=react&page=2 to test edge cases. Typing with replaceState keeps Back from filling with one entry per keystroke |
| What knows about the API | One file owns the URL and the response shape | A change to the API touches one place, and the Ask HN quirk is handled once. It adds a file the brief did not ask for |
| How the component gets its data | The search function is passed in as a prop, defaulting to the real one | Tests control timing exactly and never touch the network. It is a small abstraction, so name it in the README |
| Dependencies | React and TypeScript on Vite. No UI library, state library or router | For a small, single-screen application, fewer dependencies can reduce setup complexity and make the implementation easier to review. Additional libraries should solve a specific need rather than add unnecessary abstraction |
Prioritization is the skill underneath all of this. With limited time, prioritize the explicit requirements first, followed by critical edge cases and verification. Reserve time for a clear README, and only add extra features when the essentials are complete. A smaller, working submission is better than an ambitious one that cannot be run or evaluated.
Write the edge-case list before you write code, then check each item in the browser before you submit. For the example, the list is:
Two of these needed product decisions, not just code. The 1,000-hit ceiling means the interface should not promise 305,341 results that the Next button can never reach, so the example says how many are browsable. A page past the end shows "There is nothing on page N" with a "Back to page 1" button instead of a blank screen.
Accessibility should be considered during implementation, not treated as a last-minute addition. For this example, that means using semantic HTML, labeling controls, supporting keyboard navigation, communicating loading and error states, and managing focus when the page changes. The checklist below is general practice applied to the example, with how each item was verified:
| Item | What the example does | How it was checked |
|---|---|---|
| Labeled input | A <label> linked to the input, with role="search" on the form | The tests find the input by its label, which only passes if the link works |
| Native elements | <button> for Next, Previous, Try again and Back to page 1, <a> for stories, <ul> for the list, <nav aria-label="Pagination"> | Code reading, plus role queries in the tests |
| Announced loading and counts | One role="status" live region for loading and result counts, role="alert" for errors | Code reading and role queries. Not run with a screen reader |
| Focus after a page change | The results heading is focusable and receives focus when the page changes | Checked in a real browser: after clicking Next, the active element was the heading |
| Boundary buttons | Previous disabled on page 1, Next disabled on the last page | Code reading |
Three things were not checked, and a README should say so when it makes accessibility claims: no screen reader was run, colour contrast was not measured because the demo is unstyled, and only one browser was used. Two shortcuts are also worth owning instead of hiding: aria-current="page" sits on a text span rather than on a link in a list of page links, and links opening in a new tab do not warn the user. Both belong under "what I would do with more time". For more background on what interviewers expect, see GreatFrontEnd's guide to accessibility interview questions for 3 years experience.
Whether tests are mandatory depends on the assignment requirements. If the brief requires tests, include them. Even when tests are optional, a few focused tests can demonstrate that you've considered important user flows, failure scenarios, and edge cases. Prioritize tests that verify meaningful behavior rather than implementation details.
The example has four tests, each covering something a reviewer would try by hand:
The testing decisions matter more than the test code:
Make the structure answer the reviewer's first question, which is "where is the fetch?". The example uses one file per responsibility and nothing the brief does not need:
Use small, descriptive commits to keep your work organized and make changes easier to understand. A clean commit history can also help you explain how the implementation evolved during a follow-up discussion. You don't need a commit for every minor change, but avoid submitting a confusing history if the repository is part of the deliverable. The commands behind a clean history are in the Git interview questions for frontend developers.
A clear README helps reviewers understand and run your submission without having to explore the entire codebase. Include setup instructions, a summary of the implemented features, important technical decisions, assumptions, known limitations, and what you would improve with more time. Here is the example's, written in the candidate's voice:
Two details are worth copying. The Assumptions block turns a vague spec into decisions the reviewer can agree or disagree with. The Known limitations block shows you saw the gaps, which is better than hoping nobody notices. Before you submit, follow your own README on a fresh clone. If it does not run from your instructions, nothing else in the repo matters, which is the first thing a reviewer checks.
Resist extras until every explicit requirement is done. A useful test: an idea that accomplishes or improves the stated requirements is probably worth it, and one that is merely cool or tangential is probably scope creep. Be mindful of time spent on primary features versus additional ones. Make it work, then make it pretty, then make it fast.
Common mistakes to avoid:
node_modules, generated build output, and other files that don't belong in the submission.VITE_* values are bundled into the client source and should not contain sensitive information such as API keys. Keep *.local files out of git. If a secret does get committed, revoke or rotate it first, because deleting it from the latest commit does not remove it from history.Before you submit, run through a short checklist: clone fresh and follow the README, delete dead code, check that no secrets or build output are in the repo, confirm the repo visibility the brief asks for, and note your honest time spent.
Some companies schedule a follow-up discussion after reviewing your assignment. You may be asked to explain your architecture, justify technical decisions, discuss limitations, or make a small change to your implementation. Be prepared to explain why you chose a particular approach, what alternatives you considered, and what you would improve with more time.
Preparing for it is mostly about defending your own work:
package.json and why it is there.This is also where the machine coding skills from live rounds come back. GreatFrontEnd's machine coding round guide covers how to explain a UI build out loud, and a mock interview is a good way to practice the walkthrough.
Sometimes, and politely. Many employers are open to a candidate who raises concerns about unpaid work or asks for more time, and some will offer an alternative. Reasonable requests:
None of these guarantees a yes. A reasonable employer can say no, and you can decide whether the role is worth the hours. The point is to decide with information, not to discover the cost at hour ten.
Is a frontend take-home assignment harder than a live coding round? It is different. You control the clock and can use your own tools, but the reviewer judges only the result, so the README, the structure and the edge cases carry more weight.
Should I use TypeScript on a frontend take-home? If the brief names a stack, use it. If it does not, use the one you can write fastest and explain best. The example uses TypeScript because typing the API response is what exposed the missing url key on Ask HN stories.
Should I deploy it? If deployment is required, include it. Otherwise, prioritize completing the assignment and ensuring it runs locally from the README instructions. A live preview can be a useful bonus when time permits.
What if I run out of time? Prioritize completing the most important requirements. If you cannot finish everything, submit the working parts and clearly document what remains, the assumptions you made, and what you would implement next.
Can I reuse a boilerplate or starter? Check the assignment rules. If starter templates are allowed, use one that helps you focus on the requirements without adding unnecessary complexity. Be transparent about what you built yourself.
A frontend take-home assignment usually rewards the same things: it runs from your instructions, it does what the spec says, it handles the edge cases around it and it is easy to read. After that, assignments differ on tests, accessibility, polish, time and AI, so the brief in front of you decides. The example in this guide shows one way to meet that bar in about three hours of planned work: check the API first, keep state in the URL, cancel stale requests, test behavior and write a README that states your assumptions and your gaps. Do the explicit requirements first, document what you chose and what you skipped, and be ready to talk about every decision.
A frontend-focused guide to machine coding round questions, including what is machine coding round, how to prepare for machine coding round interviews, and how to practice in React.
Run a useful frontend mock interview with realistic timing, prompt selection, scoring signals, feedback notes, and a repair plan for the next session.
Prepare for frontend testing interviews with 30 fresher questions on unit, integration, E2E, React Testing Library, mocks, async tests, coverage, CI, and accessibility.