⏱ Estimated reading time: 6 minutes

By Hugo Pérard, Front-End Developer @ BearStudio
By Quentin Lerebours, Project Manager & Developer @ BearStudio

Table of Contents

History

So many applications look the same. Create, Read, Update, Delete, interactions, list interfaces. Same choices, same ideas, same technologies. What if there was a better way to build apps? If we’re talking web app, we could reasonably by start looking for technologies abstracting away the hard parts. TypeScript is one of these with its types, autocompletions, its capacity to catch errors early, syntactic sugar and its transpiler options. But TypeScript is not without flaws; type inference arrived later notably for JavaScript events, Pick and Omit are new additions to adjust types and there are plenty of operators to make types more expressive. It’s not perfect and there are other solutions, but this one will do.

We can consider TypeScript to be our first opinionated choice. What other choices would one have to make before actually writing their first meaningful lines of code in a new project?

Technologies

Frontend

Angular
It has grown with structure, with an approach to web development. It’s ideal for inexperienced teams. But version upgrades are complex, the performance leaves to be desired and it’s not easy separating it into small dynamically loaded chunks.

Vue
Lightweight, library-like. It’s easy to work with: learning curve, upgrades, integration. However it’s not that intuitive and quite verbose with no official UI framework and it’s difficult to create and maintain components.

React
The cleanest Developer eXperience of the trio. Highly extensible, performant, supports TSX and JSX, if fairly exhaustive, can reach the mobile platform with React Native and CLI interfaces. No conventions are enforced in React and sometimes migrations can be complex.

Rendering notions

CSR: Client Side Rendering
The application is rendered on the browser. The browser loads the application bundle, loads data and displays content.

SSR: Server Side Rendering
The application is rendered on the Node server. There may be a hydration phase client side to add interactivity.

SSG: Static Site Generation
The website is built statically then hydrated but the initially delivered content is necessarily static.

ISG: Incremental Static Generation
The website is built statically then hydrated, but a Node server regularly rebuilds the page. This avoids rebuilding the whole application for few changes.

Scaffolders / Servers

Create React App
Suffers from low maintenance and only implements CSR.

Gatsby
A complete solution that is complex to use because of its expansive integration with GraphQL.

Remix
SSR-first and difficult to adapt to other rendering modes.

NextJS
The Developer eXperience is good enough, migrations from JavaScript to TypeScript are simplified and supports all rendering methods described previously. This framework is simple to pick up if coming from React thanks to their similarities, plus it supports backend functions thanks to its API Routes.

Routing requests

Next Router
The routing is file-based. v12 has its limits regarding layout choice for multi-layout applications —think administration pages. v13 changes the structure enough that this is not an issue anymore. However, v13 cannot implement SPA because routing is only backend-side. Other than that this tool is optimal.

TanStack Router
TanStack comes with solid and agnostic value propositions. Their libraries, including this one, invest in their Developer eXperience and are type-safe. Unfortunately their routing library is in Beta. Too young for production but keep an eye on that one, it’s promising!

React Router
The most famous and in use, suited for SPA and only SPAs. Its migration from v5 to v6 was a nightmare and the solution is opinionated to suit Remix.

This one is a more complex decision with no clear winner on the market. You might be best served by a mix between what Next and React Router offer.

UI framework

Material UI
CSS gets computed at runtime, and it supports many components. However, the style looks very Google and the framework is difficult to customize and extend.

Tailwind CSS
Pure CSS, ultra customizable and easy to integrate notably thanks to its support for design tokens. As for components, Tailwind UI is official non-free alternative for ready to be used components.

Chakra UI
Customizable JS-rendered CSS. Uses component props, supports design systems and tokens and its out-of-the-box components implement accessibility features. Components themselves are composable for maximum reusability.

Data and state

useState / useEffect
It’s the standard, but it’s not a clean one. Blank screen until the data is present, no native error handling, everything must be reimplemented every time.

SWR
Stale While Revalidate. Cached data is used while new data is being fetched.

TanStack Query
Just like TanStack Router, Query is agnostic and has good Developer eXperience. The useQuery hook requires a query identifier and a query function to handle the data. Loading state, error handling and request resends are built-in. It’s a wrapper around Promises that adds a configurable layer caching with revalidation.

StartUI

StartUI implements an administration interface using all the technical choices discussed here and additional features that will make teams save time during development. This project is Open Source and developed by BearStudio because they were reimplementing a similar technical stack on every new project. This battery-packed starter includes configured ESLint, Prettier, Husky, i18n, Storybook, Cypress and Formiz.

Developers can start with StartUI even faster using the generator package create-start-ui. Your new project is seconds away, type yarn create start-ui --web my-project on the nearest terminal to try it! There are even starters for native applications and Figma!

Questions and Answers

Is it possible to replace Cypress with Jest in StartUI?

No, it is not yet supported but could soon be for unit tests.

Why the hesitation between React and Next Router?

The best technology choice for routers is very dependent on the way the application is rendered. For instance, an application using SSG may need two layers: one for the static part and one for the browser.

Is route internationalization supported?

NextJS supports path internationalization and user preferences. An alternative would be to create URLs via redirections to support translations.