One of the most common ways to evaluate candidates for frontend engineer role is to give them a frontend project assignment. Although it is not an ideal process for candidate because it is time-consuming 1, it is a closer simulation of the actual works of the role compared to other processes like live coding.
This is a checklist that I use when evaluating frontend project assignments.
Disclaimers
- The list is not adopted by any of my employers (past or current). It is a mental checklist that I use to evaluate frontend project assignments, when no criteria is provided by the hiring manager.
- This list is based on my experience evaluating frontend project assignments for junior to mid-level frontend product engineers, whose responsibilities are mainly adding UI for features by using UI components that are created by others (third-party or in-house). How relevant it is to other roles, I’ll leave it to you for judgement.
What Matters
Below is the items that I look for in a frontend project assignment. I provide points for each of them to represent the relative weight I give to each of them.
It Works According to Requirements
Weight: 20 points
This seems obvious, but failure to do it happened more than I expected. Common mistakes include:
- Project cannot be started at all, usually due to dependency issues or missing environment variables.
- If a design spec (e.g. Figma file) is given, the implementation is missing many design details, such as wrong spacing, wrong color etc.
- Missing deliverables, e.g. not including any test or documentation when they are explicitly stated.
It is understandable if you as a candidate is time-poor and cannot complete all the requirements, but it is important to at least mention the missing requirements in your README.md
to show that it is intentional instead of entirely missing it out due to carelessness.
Good Abstraction
Weight: 20 points
One of the most important skill for a software engineer is to be able to abstract away the complexity of the problem, and provide a simple interface for other engineers to use.
Things that I look for:
- Abstraction of components, e.g. a
DataTable
component that can be used to render any data table, instead of aUserDataTable
component that is specific to user data. It is also important to wrap the component library that you use (e.g. Material UI) instead of importing it everywhere in the codebase. - Abstraction of underlying operations, e.g. a
copy
function that abstract the usage ofdocument.execCommand('copy')
andnavigator.clipboard.writeText
to copy text to clipboard.
Idiomatic TypeScript
Weight: 20 points
In my opinion, using TypeScript in a frontend project that involves more than one engineers is a no-brainer as of today (July 2023), and I would enforce the usage of it if I owns the authority to decide tech stack.
With such opinion on TypeScript, I would expect candidates to be familiar and able to write idiomatic code with it, such as reasonable usage of generics and type inference, as const
assertion etc.
It may seems that I’m giving a lot of weight to TypeScript, but I believe that it is a good indicator of a candidate’s ability to write good JavaScript code, as it requires you to think type-first and balancing between writing code that are too dynamic (less repetitive but hard to infer type) versus code that are too constrained (easy to infer type but tedious to write).
Documentation
Weight: 15 points
Software engineers are not just about writing code, it is also about communicating with others. Putting effort into crafting a good README.md
shows that you care about that part of the job, and understand its importance.
Things that I look for:
- A screenshot of the UI that is inserted into the
README.md
file. - Instruction to run the projects, e.g.
npm install
andnpm start
. It is good to mention other dependencies, such as the version of Node.js and npm that you use, as it helps to reduce the chance of dependency issues. - Technical decision made, e.g. the library and tools that you use. Justification is not mandatory (especially those being specified in the requirements), but it would be good for those library/tools that you decide to add. For example, if you choose to use
react-hook-form
instead offormik
, it would be good to explain why with a short description. Sometimes, I even choose a library over another just because I want to learn the library, and I would mention it here.
Project Structure and File Convention
Weight: 15 points
As JavaScript is an un-opinionated language, it is important to have a consistent project structure and file convention to make it easier for other engineers to navigate the project and understand the context.
Things that I look for:
- Separate between generic and business-specific code. For example, don’t put all the components inside
components
folder. Usecomponents
folder for generic UI components likeButton
and usemodules/user
folder for business-logic components likeUserList
. - A file naming convention that optimizes developer experience, e.g. minimal code in
index.ts(x)
and unique file names (e.g.data-table.tsx
anduser-data-table.tsx
instead of bothdata-table.tsx
, just in different folder).
It is important that you lean slightly towards over-organization when it comes to project assignment. Although in your actual project with a small codebase you probably can get away with a flat folder structure, but be mindful that a project assignment is a simulation of a real large project, so it is important to show that you know how to organize code.
Tests
Weight: 10 points
Although testing tools for JavaScript ecosystem has improved tremendously in last few years, I still see many frontend projects without any tests. I would expect a frontend engineer to be familiar with testing tools and write tests for their code. It doesn’t have to be 100% coverage, but at least write a few test to shows the quality of your test code.
Development Automation
Weight: 5 points
JavaScript ecosystem is notorious for its lack of standardization, and to have a good developer experience usually requires you to stitch together multiple tools. Therefore, it is beneficial to show that you are familiar with the tools and able to configure and use them effectively.
Things that I look for:
- Usage of
eslint
andprettier
for linting and auto code formatting. - Add
scripts
topackage.json
for the command required for this project. - Setup CI/CD to automate deployment
Compared to other items in this list, this is the least important one, because in most companies there is usually senior engineers that will be responsible for them. However, it is still a plus point as a software engineer to shows that you care about your work and find ways to make it more efficient.
What Doesn’t Matter
To me, the following items are not important when evaluating a frontend project assignments, although they seems to be popular suggestions when someone ask about feedbacks of their code.
The choice between equivalent tools
Equivalent tools are the tools that have mostly similar APIs and choosing one over another has minimal impact to how you write your code.
For examples:
- Create React App versus Vite,
- Jest versus Vitest
- Puppeteer vs Playwright
Choosing a specific tool from a few compatible tools is mostly a matter of preference and whether you heard of them, so it is not very useful when evaluating a frontend engineer. However, it does matter if you include a type of tool to achieve specific requirements, e.g. adding a testing framework itself is a plus point when requirements includes testing, but choosing Vitest over Jest is not.
Whether you use the “latest” library or language feature
Many junior engineers that mainly learn from YouTube or social media like Twitter tends to see new library/tools as a way to show that they are “up-to-date” with the latest trend. However, in a real-world project, it is not always a good idea to use the latest library/tools, as it may not be stable enough or have enough documentation to support it.
Unless listed as assignment requirement, I don’t care whether you use the latest library/tools or not when evaluating a project assignment. I only care if the code is easy to understand to me. In other words, using latest library/tools could be detrimental, as the interviewer may not be familiar with it, and it may take more time for them to understand your code.
The key takeaway is that, feel free to choose a library or use certain language feature because you are familiar with it or you want to learn it, but don’t do it because you think it would help to improve the rating of the assignment.
Checklist Summary
Item | Points |
---|---|
Fulfilling Requirements | 20 |
Good Abstraction | 20 |
Idiomatic TypeScript | 20 |
Documentation | 15 |
Project Structure and File Convention | 10 |
Tests | 10 |
Development Automation | 5 |
One thing that you may realize is that I’m missing some important skills of frontend engineer, such as CSS and accessibility. The reason is that although I think they are important, but based on my previous experience, once you learnt the fundamentals2 they are not something that impacts the output for a frontend product engineer significantly. If you are applying for a frontend engineer role that are responsible for the frontend architecture and design system, then it would be a different story.
Improving Scores
Here are my suggestions on how to improve each of them. Note that the suggestions are what worked for me (instead of what I think what could work), and they may not be the best resource today. But they did help me to improve those items in the checklist.
How to Ensure You Fulfill Requirements
- Reread the requirements and make a checklist. Make sure you go through each of them and check it off once you have done it, or added a comment to explain why you didn’t do it.
- Ask friends to review the project. Your friends don’t have to be expert, by just trying to setup the project, they could discover basic issues like missing dependencies or unclear documentation.
How to Create Good Abstractions
This is not a skill that you can learn overnight, but here are what worked for me:
- Read good technical books. Refactoring version 1 and Code Complete are two books that I enjoyed with plenty of tips and suggestions that are actionable.
- Read what abstractions are created in open source projects and see how they abstract their code. I used to read fbjs and peek into utilities packages of popular libraries like Material UI (its utility package code is available here).
How to Write Idiomatic TypeScript
Similar to creating good abstractions, this is not something that you can learn overnight. Here are what worked for me:
- Refactor code from JavaScript to TypeScript, or removing
any
from your codebase, one file at a time. In my opinion, this is the best way to learn TypeScript, as you will learn the language features when you need them, and you will learn how to use them in a real-world project. - Read Effective TypeScript and start applying them.
- Subscribe to TypeScript blog and read everything they posted. They are well written and with good examples. I have to admit that I don’t understand everything they posted, but they often gave me a new perspective on how to use TypeScript, and pitfalls of different approaches.
How to Improve Documentation
This is relatively simpler for project assignment. Find a template and fill in the blanks. This gist is one of the example, but feel free to shop around.
How to Have a Good Project Structure and File Convention
This is also something that you need to shop around and find one and stick with it. Being intentional about your project structure and file convention is more important than the actual structure and convention you choose.
For React projects, my go-to project structure is implemented here, which I may tweak slightly based on the framework I use. Key highlights of the structure:
src/modules/
folder to store the business logic for a specific domain. The modules folder mirrors the rootsrc
folder, i.e. it could havecomponents
andlib
folder as well.- Unique name for each file. For example,
src/modules/owner/components/owner-overview.tsx
instead ofsrc/modules/owner/components/overview.tsx
. The reason? I can use file search of my IDE to find the file easily, without multiple similar file names in different folder appear in the result. kebab-case
for all file names, including React components. PascalCase for React components come from Facebook if I remember correctly, but I really dislike it after being bitten by the issue of Windows OS not being case-sensitive.- Avoid default export unless required by the framework. Why? Read the article Why I’ve stopped exporting defaults from my JavaScript modules.
How to Write Tests
There are many resources, Kent C. Dodds’s Testing JavaScript is the best resource that I know, but it’s paid course.
If you not willing to spend money on it and short of time, learn Cypress. It’s a tool that allows you to write end-to-end tests that run on all major browsers, and it has fantastic docs that are beginner friendly.
How to Automate Development
As this is not as important as others, and it is a rabbit hole that could get as deep as you want, I won’t go into too much details.
As starter, install prettier
and configure your IDE so it auto-format your code on save. This is the most basic automation that you should have.
Conclusion
That are all I could think of about this topic. As this note is something that I would update over time, please let me know if you have any suggestions, or if you have any questions.
Footnotes
-
It does’t have to be time-consuming though. Tweet at me if this is something you want to learn more. ↩
-
For CSS, you should know how to implement responsive design. For accessibility, understand the importance of using the right HTML elements, and spend some time to learn how to provide sufficient attributes to HTML elements for them to be reasonably accessible. ↩