Primitives, conventions, and levers
In this section, we will categorize the different features Remix offers. A framework provides the foundation and framing for your application. It further exposes tools to you as a developer. We can divide these tools into three categories:
- Primitives
- Conventions
- Levers
Primitives, conventions, and levers can serve as a great mental model to map different features of Remix. Let’s see how the three categories differ.
Primitives
Primitives are used in your application code to interact with the framework layer. They are the wiring that integrates your application into the foundation and framing provided by the framework. Common primitives are functions, hooks, constants, types, classes, and components. The framework exposes these primitives so you can use them in your code. The art is to make primitives easy to understand yet composable enough to enable powerful business logic. Remix has done just that.
Remix provides primitives for both your client and server code. Remix primitives are often just a thin abstraction layer of the web platform and offer similar APIs to the native primitives. For instance, Remix’s Form
component accepts the same properties as the native form element but also offers some additional properties to enhance the experience.
Also, Remix’s primitives themselves expose standard web APIs. Most server-side code you write in Remix has access to a Request
object that follows the Web Fetch API specification. Remix does not reinvent the wheel.
Conventions
Frameworks also introduce conventions. Common conventions are file and folder naming conventions. In the previous section, we showed a code example of a route file in Remix. Remix’s route files (route modules) allow you to export specific functions that are part of Remix’s route filenaming convention.
Conventions are meant to improve the developer experience. For instance, file-based routing lets you define your application’s route structure as a file and folder hierarchy. Remix compiles your code and infers your route hierarchy, so you don’t have to define your route hierarchy as code.
Intuitive conventions reduce the amount of configuration required to wire an application. They shift the burden toward the framework. Conventions make up the contract between the framework and your application and can significantly reduce the amount of boilerplate code you have to write.
The API of a framework is mainly composed of primitives and conventions. All frameworks include primitives, and many frameworks utilize conventions. However, Remix places a particular emphasis on a third category: levers.
Levers
Levers can be interpreted as options. Ryan coined the metaphor in one of his first conference talks about Remix. Ryan emphasizes that Remix is just a thin abstraction layer on top of the web platform. Remix lets you decide what web vitals to optimize for. Time to First Byte (TTFB) or Cumulative Layout Shift (CLS)? Loading spinners or slower page loads? Optimizing for different web vitals can be conflicting goals. Remix offers levers so that you can stir your web app in the direction that is right and important for you.
With levers comes utility but also responsibility. Remix provides the primitives, but you must decide how to design your application. I believe this power makes you a better web developer. But more importantly, it unlocks the full potential of the web platform. There are many things to optimize for, and Remix provides the levers. This sets Remix apart from other frameworks that don’t give you the same kind of flexibility and control.
Now that we’ve prepared a mental model for how to categorize Remix’s features, we will have a look behind the scenes. Remix offers many great features and comes with many quality-of-life improvements. This is because it takes on several responsibilities at once. Let’s peek under the hood to understand what that means.