Can I Use This?

In order to follow this guide, you must use Webiny version 5.21.0 or greater.

What you'll learn
  • the moving parts of the Admin app framework
  • what is a plugin
  • how the Admin app is rendered

Overview
anchor

Admin app is powered by a simple React framework, which allows you to add new React Context providersexternal link, compose existing UI components, register routes, and do all that using plain React componentsexternal link, and widely used concepts, like Higher Order Componentsexternal link (hereinafter: HOCs), and hooksexternal link.

In the following sections, we cover 5 fundamental components which make everything work. These 5 components make up the low-level API, and in the vast majority of cases, these are the only components you’ll need to use to develop new plugins (besides your own custom components and views).

The following diagram shows all 5 components in action:

Admin App Framework In ActionAdmin App Framework In Action
(click to enlarge)

As you can see, what you mount, is not exactly what gets rendered. The Admin component (the framework) takes care of rendering things where and when they need to be rendered, and also does various compositions and optimizations (caching) in the process.

A good example of that are the React Context providers (represented by the Provider component in the diagram). Traditionally, when using Higher Order Components (HOCs), we end up with a deep hierarchy of nested components, which is hard to read, and even harder to maintain. In these cases, we usually resort to HOC composition, to flatten out the hierarchy, and produce a single component which is constructed of the individual HOCs wrapped around the previous one. We use the same technique to construct React Context providers.

ThePluginsComponent
anchor

To explain why we need this component, let’s quickly describe what a plugin is.

A plugin is a React component that can do things like adding a route, adding a menu, adding a file type renderer, etc. Plugins can also be composed into larger plugin components, to perform more complex tasks.

More often than not, a plugin component needs to access one or more React Contexts provided by various apps (Page Builder, File Manager, etc.), to do its job. To be able to do that, plugin components need to be rendered as children of all those React Context providers (if unsure, revisit the diagram in the Overview section).

The purpose of the Plugins component is to make sure that its children are rendered at the right place within the app component hierarchy. It helps you not to think about where you mount your plugin components, so you’re more flexible with how you build your custom plugins.

You can mount as many Plugin elements as you need, anywhere in the app components hierarchy. The only important thing is that you do mount it when you want to add one or more plugins to the app.

Here’s the simplest, most straightforward example of using the Plugins component:

Using <Plugins/> to Add Routes and Menus

The AddRoute component is described in the dedicated Custom Routes article.

The AddMenu component is described in the dedicated Customize Navigation article.

Let’s see a more advanced example, and demonstrate a real-life example of menus, routes, and permissions:

Extension Composition
Extensions

We highly recommend using our Extensions to organize your code in a scalable and portable manner.

Naming Conventions
anchor

There are many components exported from the @webiny/app-serverless-cms package. These naming conventions will help you find your way around, and quickly filter out components in your IDE.

  • components that add things to the system start with Add prefix (e.g., AddMenu)
  • presentation components end with Renderer (e.g., MenuItemRenderer)
  • hooks, by React convention, start with use (e.g., useSecurity)

Almost always, renderer components go with a parent component that provides a React Context to the renderer. For example, a UserMenuItem has a corresponding UserMenuItemRenderer component. The renderer component doesn’t take any props; instead, it uses hooks to fetch the relevant data from React Context, provided by the UserMenuItem component. This approach drastically reduces prop drilling, and makes it easier to decouple logic from presentation.

If you want to change the appearance (the renderer) of a certain component, always look for the Renderer part of it, and decorate that component.

Conclusion
anchor

These few simple components is what makes up the core of the Admin app. This provides strong and simple foundations to build upon. It’s easily composable, and gives the ability to lazy-load plugins, apply plugins conditionally, compose component renderers, and also compose these atomic components into larger extensions.