Project Architecture

Steroids provides a unified architecture for your projects. By following these principles and rules, you will be able to quickly create complex applications that will be easy to maintain in the future.

Application Structure

The general structure of an application with a single page and layout looks as follows:

├── node_modules
├── public - build directory used by the web server
├── src
│   ├── actions - redux actions
│   ├── reducers - redux reducers
│   ├── modals - modal windows
│   ├── routes - application routes (pages)
│   │   └── IndexPage - react component folder
│   │       └── views - components used only in IndexPage
│   │           ├── MyBox.ts
│   │           └── MyBox.scss
│   │       ├── IndexPage.ts - react component
│   │       ├── IndexPage.scss - BEM styles for the component
│   │       └── index.ts - component loading as a directory
│   ├── shared - shared components
│   │   └── Layout
│   │       ├── Layout.ts
│   │       ├── Layout.scss
│   │       └── index.ts
│   ├── ui - styled and custom UI components
│   │   └── form
│   │       ├── Button
│   │       │   ├── ButtonView.tsx
│   │       │   └── ButtonView.scss
│   │       └── CustomField
│   │           ├── CustomField.ts
│   │           ├── CustomFieldView.tsx
│   │           └── CustomFieldView.scss
│   ├── style
│   │   ├── index.scss - main style file
│   │   └── variables.scss - SCSS variables
│   ├── Application.tsx - main application component
│   └── index.tsx
├── .eslintrc
├── index.d.ts - global definition of types for code written without typescript
├── package.json
├── tsconfig.json
├── webpack.js
└── yarn.lock

You can add static assets (images, fonts) to the public directory for their use in the application via absolute paths. This directory will also store minified application bundles generated by Webpack.

The src directory contains the project's source code, which is not published when deploying the project to production.

At the root of the sources, there are two files - index.tsx and Application.tsx. It's recommended to keep their separation and names exactly as they are, as when using SSR (Server-Side Rendering), the Node.js server application will render Application.tsx. The index.tsx file is used solely for rendering through react-dom in the browser.

The actions and reducers directories contain actions and reducers for the redux store, respectively. They don't need to be created if the library already provides many reducers that the application can use. If the reducers directory is not created, Webpack will use reducers from the library node_modules/@steroidsjs/reducers.

All routes are defined in the routes/index.ts file. You can read more about their capabilities and format in the Routing.

React components of the application are distributed according to the foldersmodals, routes,shared and ui. They should not be declared in other folders to maintain the structure and ease of navigation.

Application Customization

In the Application.tsx file, you can customize the application by adding custom reducers, components, and icons. Here is how the file looks in the boilerplate:

import useApplication from '@steroidsjs/core/hooks/useApplication';
import HttpComponent from '@steroidsjs/core/components/HttpComponent';
import LocaleComponent from '@steroidsjs/core/components/LocaleComponent';
import customIcons from 'icons/index';

import 'style/index.scss';

export default function Application() {
    const {renderApplication} = useApplication({
        reducers: require('@steroidsjs/core/reducers').default,
        routes: () => require('routes').default,
        layoutView: () => require('shared/Layout').default,
        screen: {},
        components: {
            locale: LocaleComponent,
            http: HttpComponent,
        },
        onInit: ({ui}) => {
            ui.addViews(require('./ui/bootstrap').default);
            ui.addFields(require('@steroidsjs/core/ui/form').default);
            ui.addFormatters(require('@steroidsjs/core/ui/format').default);
            ui.addIcons(require('@steroidsjs/bootstrap/icons/index').default(customIcons));
        },
    });

    return renderApplication();
}

Detailed instructions on customizing various parts of the application can be found in the article Application Customization.

React Components

React components in the Steroids framework have some distinctive features and advantages:

  • Separate core and view parts for each component.
  • The ability to customize styles through SCSS variables.
  • Full replacement capability for both *.scss and *.tsx component files for customization.
  • The option to add custom components.
  • TypeScript interfaces described for components and their view parts.
  • Global configuration (default props) for all components or selected ones.
  • Logic of UI components working in conjunction with application components, routing, and Redux.
  • The possibility of processing metadata models and enums coming from the backend to create forms based on them.

Separation of Logic and Presentation in a Component

Each UI component (form element, list, modal window, etc.) consists of two parts:

1. Core: The core of the component contains all the business logic. It receives and processes data from props, finds the appropriate view of the component, and passes the prepared data to it. The core component does not contain jsx code and does not interact with DOM elements.

2. View: The view is responsible for the direct rendering of the component. It includes only jsx code and scss styles for the component with minimal or no business logic. When customizing the component, its *View.tsx and/or *View.scss files can be fully copied into the project and modified to fit the design of a specific project.

For more details on how to take advantage of the separation of core and view parts of a component, you can read here.

File Structure of a Component

React components consist of two files - tsx and scss. Even if there is no immediate need to style a component, but it contains jsx code, it is still recommended to create a *.scss style file and import it via import in the *.tsx file. This ensures a consistent file structure for all components in the project.

Each component is placed in a separate folder with an index.ts file. This file contains the import and export of the component:

import IndexPage from './IndexPage';
export default IndexPage;

The index.ts file is used to export the component from the folder. With these files for components, the project code can use concise imports, for example, routes/IndexPage instead of lengthy imports from the component file, such as routes/IndexPage/IndexPage.

For larger components, such as application pages, nested components are extracted. If such components are only used in a specific component, they should be placed in the views folder (see routes/IndexPage/views/* in the structure). If components are reused in other large components, such as on other application pages, they should be moved to the top level in the shared folder (see src/shared in the structure).

Common Styles

The base styles of the application are located in the src/style folder and are exported from the src/style/index.scss file. They are imported during the initialization of the application in the Application.tsx file.

Common styles are used to declare the fonts used, basic styles for HTML tags, mixins, and SCSS variables. Additionally, in this file, CSS files from various libraries or default styles for Steroids can be included, for example: @import '@steroidsjs/bootstrap/index.scss';

SCSS variables that will be used in various components are imported into a separate file - style/variables.scss. Its further usage in components looks like this:

@use "style/variables";

.Block {
  background-color: variables.$gray;
  border: 1px solid variables.$graphite;
}

If you have a large number of variables that can be grouped, the file structure would look like the following:

├── style
│   ├── variables - папка с файлами для scss-переменных
│   │   ├── colors.scss - scss-переменные для цветов
│   │   ├── typography.scss - scss-переменных для типографики
│   │   └── index.scss - экспорт всех файлов с scss-переменными из папки
│   ├── index.scss - главный файл стилей
│   └── variables.scss - содержит импорт index файла из папки variables и другие файлы с переменными (например для библиотек)

SCSS mixins are imported into a separate file - style/mixins.scss. Their further usage in components looks like this:

@use "style/mixins";

.Block {
  @include mixins.loading(1s);
}

If scss-mixins can be divided into groups, with each group in a separate file, the structure will be the same as for scss-variables.