Malcolm's Frontend Project Assignment Checklist

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:

  1. Project cannot be started at all, usually due to dependency issues or missing environment variables.
  2. If a design spec (e.g. Figma file) is given, the implementation is missing many design details, such as wrong spacing, wrong color etc.
  3. 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:

  1. Abstraction of components, e.g. a DataTable component that can be used to render any data table, instead of a UserDataTable 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.
  2. Abstraction of underlying operations, e.g. a copy function that abstract the usage of document.execCommand('copy') and navigator.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:

  1. A screenshot of the UI that is inserted into the README.md file.
  2. Instruction to run the projects, e.g. npm install and npm 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.
  3. 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 of formik, 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:

  1. Separate between generic and business-specific code. For example, don’t put all the components inside components folder. Use components folder for generic UI components like Button and use modules/user folder for business-logic components like UserList.
  2. 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 and user-data-table.tsx instead of both data-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 and prettier for linting and auto code formatting.
  • Add scripts to package.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:

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

ItemPoints
Fulfilling Requirements20
Good Abstraction20
Idiomatic TypeScript20
Documentation15
Project Structure and File Convention10
Tests10
Development Automation5

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

  1. 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.
  2. 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:

  1. 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.
  2. 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:

  1. 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.
  2. Read Effective TypeScript and start applying them.
  3. 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:

  1. src/modules/ folder to store the business logic for a specific domain. The modules folder mirrors the root src folder, i.e. it could have components and lib folder as well.
  2. Unique name for each file. For example, src/modules/owner/components/owner-overview.tsx instead of src/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.
  3. 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.
  4. 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

  1. It does’t have to be time-consuming though. Tweet at me if this is something you want to learn more.

  2. 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.

Thanks for reading!

Love what you're reading? Sign up for my newsletter and stay up-to-date with my latest contents and projects.

    I won't send you spam or use it for other purposes.

    Unsubscribe at any time.