10 principles of scalable frontend projects

Web apps have come a long way since their initial appearance. We all now know just how powerful JavaScript on the web is, and how many endless possibilities exist in terms of framework and technology choices.

Different frameworks have their pros and cons, but some core methodologies can be applied to almost every framework. Tools such as create-react-app, next.js, vue-cli, etc., are really helpful for bootstrapping a project and its structure, but after that, you’re free to form an application to your preferences and project’s requirements.

I’ve collected some principles I found valuable when building web applications with React and Vue that can help you in defining a direction and keeping things tidy and sound. Most of the principles can be applied to all software, but this list is a bit specific to web apps.

1 — Developing components, not screens

  • try to encapsulate all the logic of a component in isolation, so it can be rendered everywhere with ease – for example, in different screens and sections
  • all the CRUD operations go inside the controllers / providers for the data it needs, and that data is passed to presentational components
    • one common scenario is redux/vuex — data is persisted to a store and is treated as a single source of truth, and container components extract the relevant data

2 — Separating presentational and business / controller layer

  • not all components need to be connected to stores, backend API or some other service
  • by making components “data source agnostic”, reusability is greatly increased

3 — Using a standardized way of fetching the data

  • rest-hooks is a great example of this principle as it encourages a predictable and readable structure for API calls
  • for some projects, using explicit fetch calls may be sufficient, but if you’re dealing with a lot of resources and relationships, having an abstraction over backend API can be helpful


4 — Having a common user input strategy

  • forms, select tags, validations, error states all fall into this category
  • UI component libraries such as antd provide a solution for this out of the box
  • if you’re creating an app without a UI library, consider putting a bit more emphasis on standardizing these elements for better UX

5 — Writing automated tests

  • components are, in my experience, best tested with integration tests, specifically with Cypress
  • business logic should be thoroughly covered with unit tests
  • e2e are valuable for smoke testing larger user flows; they can help detect regressions between the client and the API

6 — Using a storybook for creating reusable components

  • storybook.js.org
  • great way to collaborate with designers and discuss functionality
  • serves as a “living style guide” for your app

7 — Using linters and formatters

  • examples of linters — ESLint, stylelint
  • most bootstrap tools, such as create-react-app, pre-install linters for you, but if you’re on a legacy codebase, they might not be applied
  • they can help you catch bugs, but they can also be used in defining code style for your team — this can help in reducing mental load when developing upon a feature that you’ve inherited from your colleague
  • sonarJS eslint plugin can help improve code quality as it checks for logical structure
  • prettier is an awesome code formatter that you set up only once, and never think about it again — very useful when working in a team


8 — Avoiding global styles

  • overrides and resets can be made global
  • CSS modules or CSS-in-JS are some of the technologies that can help in achieving scoped, isolated styles
  • local styles can often lead to better component reusability

9 — Using structured version control

  • using a branching model
    • e.g. gitflow — a branching model for Git, created by Vincent Driessen
    • having a structure in your version control is indispensable for working in a team, but it is helpful even when working on your own
  • linting commit messages – commitlint
    • useful in creating a changelog and finding bugs as the project develops
    • angular’s commit message rules are often applicable to any software project, and commitlint can help you in keeping those messages consistent with the ruleset

10 — Keeping a changelog

  • at the beginning of every project, it’s usually easy to keep track of all the changes in your mental context
  • as the project grows, the changelog can serve as a central place for discovering notable changes to a codebase, even months and years into development

The never-ending list

That’s all folks — there could surely be many more items added to the list, depending on the project domain and technology, but I find these can improve many front-end apps radically. Almost all of the principles can be applied progressively and by priority defined by you and your team — so no need to worry about applying them all at once.