Code Generation
Understand generated backend code in SolidX, how the CLI updates it, and the frontend conventions followed by solid-ui modules.
Code Generation
SolidX uses metadata to generate and maintain large parts of the backend application in solid-api.
The frontend in solid-ui is different: it is not scaffolded model-by-model in the same way, but it does follow a clear set of conventions so project-specific UI modules can be discovered and registered dynamically.
This page gives you the complete picture in one place:
- what gets generated in
solid-api, - how the CLI updates generated backend code,
- and how
solid-uishould be structured so it plugs cleanly into@solidxai/core-ui.
What Is Generated vs What Is Conventional?
solid-api (Generated)
Metadata drives the creation and maintenance of:
- NestJS module wiring
- Controllers
- Services
- DTOs
- Entities
- Repositories
- Model-related layout metadata
solid-ui (Convention-driven)
Projects follow a convention-based structure:
- App bootstrap lives in
src/ - Feature folders define project-specific UI modules
*.ui-module.tsfiles are discovered dynamically- Each UI module contributes routes, Redux pieces, extension functions, and extension components
solid-api Generated Structure
At a high level, generated code in solid-api turns metadata into a working NestJS module with CRUD behavior.
Module Structure
When a SolidX module is created, the backend gets a module folder and a NestJS module file that acts as the integration point for models generated under that module.
solid-api/
├── src/
│ └── fees-portal/
│ └── fees-portal.module.tsThe module file starts as a thin NestJS @Module() container. As more models are generated, it becomes the parent wiring point for their controllers, services, repositories, and entities.
Model Structure
Each generated model adds the standard backend files needed for a metadata-driven CRUD resource.
solid-api/
├── src/
│ └── fees-portal/
│ ├── controllers/
│ │ └── fee-type.controller.ts
│ ├── dtos/
│ │ ├── create-fee-type.dto.ts
│ │ └── update-fee-type.dto.ts
│ ├── entities/
│ │ └── fee-type.entity.ts
│ ├── repositories/
│ │ └── fee-type.repository.ts
│ └── services/
│ └── fee-type.service.tsController
Generated controllers expose the REST API surface for the model. They typically include:
- create and bulk-create endpoints,
- full update and partial update endpoints,
- read endpoints for single records and filtered lists,
- soft delete and recovery endpoints,
- auth decorators,
- Swagger decorators,
- and file upload handling where required by field metadata.
In practice, the controller is the generated HTTP layer for a model.
Service
Generated services usually extend CRUDService<T> from @solidxai/core.
That gives each model a metadata-aware service layer with:
- standard CRUD behavior,
- query parsing,
- soft delete and recovery support,
- media/file handling,
- and integration with module/model metadata services.
This is the generated business layer that sits between the controller and the repository.
DTOs
Each model gets a create and update DTO.
- The create DTO represents the required and optional data for creation.
- The update DTO mirrors the same fields but generally treats them as optional and includes the record
id. - Validation decorators and Swagger decorators are generated from field configuration.
These files are directly affected when fields are added, removed, or their types change.
Entity
The generated entity maps model metadata into a TypeORM entity.
This includes:
- column definitions,
- relation decorators such as
@ManyToOne, - nullability,
- indexes,
- uniqueness constraints,
- and inherited common fields such as audit and soft-delete support.
This is the database-facing representation of the model.
Repository
Generated repositories inherit from SolidBaseRepository<T> and provide the data-access layer for the model.
They already come with:
- metadata-aware TypeORM behavior,
- security-rule aware queries,
- request-context integration,
- and a clean place to add project-specific query methods later.
How Field Changes Affect Generated Files
One useful way to think about code generation is this:
- module metadata defines the model,
- model metadata defines the fields,
- field changes flow into generated backend files.
When you add or modify a field, SolidX typically updates:
solid-api/src/<module>/
├── dtos/
│ ├── create-<model>.dto.ts
│ └── update-<model>.dto.ts
└── entities/
└── <model>.entity.tsExamples:
- adding a new string field usually adds validation decorators to both DTOs and a matching column in the entity,
- changing a field from text to number updates the DTO validation decorators and the entity column type,
- adding a relation field changes both entity decorators and the expected DTO shape.
Layout Metadata Generated Alongside Models
Although solid-ui itself is not generated the same way, model generation often also creates or updates the layout metadata used by the UI.
Typical generated layout metadata includes:
- list view layout definitions,
- form view layout definitions,
- column/filter/search configuration,
- and default field placement for forms.
Those layouts define how generated admin screens behave, even though the project-specific React code in solid-ui is maintained separately.
Refer to Layout Editor, List View, and Form View for the UI-side explanation of those layouts.
CLI Commands That Affect Generated Backend Code
The SolidX code builder can be triggered from the admin experience or from the CLI. The CLI is especially useful when you want to explicitly refresh generated backend code from metadata.
generate module (Recommended)
Generates or refreshes code for an entire module and all of its models.
npx @solidxai/solidctl@latest generate moduleUse when:
- a module has been added
- multiple models in a module have changed
- fields have changed
- generated files have fallen out of sync with metadata
- or you want the safest full refresh path
generate model (Targeted Refresh)
Refreshes a single model and its related models.
npx @solidxai/solidctl@latest generate modelUse when:
- only one model has changed
- you want a faster refresh than regenerating the full module
- or you are iterating on one model repeatedly during development
For the latest command syntax and supported options, see solidctl Reference.
How To Think About CLI Impact
The CLI does not generate arbitrary new architecture. Its job is mainly to keep the generated backend aligned with metadata.
The practical effect of running the CLI is usually one of these:
- A missing generated backend file is created.
- An existing generated file is updated to match changed metadata.
- Generated DTO/entity/service/controller/repository wiring is brought back into sync.
Because of that, it is best to think of generated backend code as metadata-owned scaffolding.
When you need project-specific behavior, prefer extending or customizing in the appropriate extension points instead of treating generated files as the primary place for handwritten business logic.
Related docs:
solid-ui Structure and Conventions
Even though SolidX does not auto-generate app-specific React modules in the same way, solid-ui still follows a predictable structure. Repeating this here is intentional, because understanding the backend generation story is much easier when you can also see how the frontend plugs into it.
High-Level Structure
solid-ui/
├── index.html
├── public/
├── src/
│ ├── main.tsx
│ ├── App.tsx
│ ├── AppRoutes.tsx
│ ├── solid-ui-modules.ts
│ └── <project-module>/
│ ├── <project>.ui-module.ts
│ ├── admin-layout/
│ ├── custom-layout/
│ ├── redux/
│ └── utils/
├── vite.config.ts
└── package.jsonImportant Bootstrap Files
src/main.tsx
This mounts the React application.
src/App.tsx
This is the main application shell. It typically wires together:
- the router,
- store provider,
- theme and layout providers,
- application event listeners,
- and the route tree.
src/AppRoutes.tsx
This usually calls getSolidRoutes(...) from @solidxai/core-ui and merges project-specific route contributions into the shared SolidX route structure.
src/solid-ui-modules.ts
This file is the key convention that allows dynamic discovery of project modules.
A typical implementation looks like this conceptually:
const moduleImports = import.meta.glob("./*/*.ui-module.ts", {
eager: true,
import: "default",
});That means any module placed under src/<something>/<something>.ui-module.ts can be discovered automatically and registered into the app runtime.
UI Module Convention
Each project-specific frontend module typically exports a default object from a *.ui-module.ts file.
That module can contribute:
- extra routes,
- extension components,
- extension functions,
- reducers,
- middleware,
- and any other runtime pieces expected by
@solidxai/core-ui.
Conceptually, a UI module is the frontend equivalent of a project feature package.
Typical Module Folder Layout
src/venue/
├── venue.ui-module.ts
├── admin-layout/
│ ├── <model>/
│ │ ├── extension-components/
│ │ └── extension-functions/
├── custom-layout/
│ ├── auth/
│ ├── dashboards/
│ └── home/
├── redux/
└── utils/What Belongs in Each Folder?
*.ui-module.ts
This is the registration file for the frontend module. It usually defines:
- module name,
- extra routes,
- extension components,
- extension functions,
- reducers,
- and middleware.
admin-layout/
Use this for code that extends or customizes generated admin screens.
Typical examples:
- custom list header actions,
- form widgets,
- form load handlers,
- field change handlers,
- model-specific admin behavior.
custom-layout/
Use this for pages that are fully custom and not just tweaks to generated admin screens.
Typical examples:
- dashboards,
- login overrides,
- landing pages,
- custom home screens,
- or business-specific workflows.
redux/
Use this for RTK Query APIs and other Redux logic owned by the module.
These reducers and middleware are commonly surfaced through the module registration file so the app shell can compose them into the global store.
utils/
Use this for module-specific utilities such as:
- export helpers,
- data-formatting helpers,
- display helpers,
- and small reusable module-level functions.
Recommended Mental Model
The cleanest way to think about the two apps together is:
solid-apiis metadata-driven and heavily generated,solid-uiis convention-driven and manually extended,- generated layouts and APIs connect the two,
- and project-specific customization lives in extension points around that generated core.
That division is important:
- backend generation gives you consistency and speed,
- frontend module conventions give you flexibility,
- and the shared
@solidxai/core-uiruntime keeps the UI pluggable.