# Module Generator Frontend The frontend generator UI collects module metadata, selected assets, form layout, and datatable configuration. It converts the configuration into TypeScript/TSX source strings and sends them to the backend generator. ## Main Flow | Responsibility | Source | | ------------------------------------------------------ | ------------------------------------------------------------------------------------- | | Page submission, notifications, and mutation callbacks | `apps/admin/src/devtools/pages/ModuleGeneratorPage/index.tsx` | | Payload assembly | `apps/admin/src/devtools/pages/ModuleGeneratorPage/lib/buildGenerateModulePayload.ts` | | Form state and initial values | `apps/admin/src/devtools/view/forms/ModuleGeneratorForm/form.ts` | | Metadata, form, and datatable sections | `apps/admin/src/devtools/view/forms/ModuleGeneratorForm/sections/` | | Payload DTOs | `apps/admin/src/devtools/data/api/dto.ts` | | HTTP client | `apps/admin/src/devtools/data/api/index.ts` | | React Query hooks | `apps/admin/src/devtools/data/queries/` | | Source-code builders | `apps/admin/src/devtools/data/builders/` | The page submits through `useGenerateModule`. On success it resets the form and shows a success alert; backend or network errors are normalized through the shared React Query error helpers. ## Metadata and Assets The required metadata is: - `name`: frontend folder name, backend module identity, route segment, and permission-slug base. - `table`: existing PostgreSQL source table. - `generate`: selected backend and frontend assets. Supported asset values are defined by `ModuleAsset`: | Asset | Workspace | Output | | ------------ | --------- | --------------------------------------------------- | | `model` | Backend | Lucid model | | `controller` | Backend | Authenticated resource controller and test | | `routes` | Backend | Resource route registration | | `validator` | Backend | Create and update Vine validators | | `policy` | Backend | Bouncer policy and permission configuration | | `api` | Backend | API controller, validators, routes, and test | | `form` | Frontend | Form definition, component, and modal/sheet trigger | | `datatable` | Frontend | List page table and menu entry | The default selection includes all backend assets. Form and datatable generation are opt-in. ## Schema Queries The frontend uses two authenticated read endpoints before generation: - `GET /makeModule/tables` populates the table selector. - `GET /makeModule/columns/:table` populates form and datatable field choices. Table and column requests are cached through React Query. Column queries remain disabled until a table is selected. ## Payload Builders `buildGenerateModulePayload` delegates source generation to focused builders: | Builder | Payload field | Generated destination | | ------------------------------------- | ---------------- | ----------------------------------- | | `FormTemplateBuilder.buildComponent` | `form` | `view/forms/MainForm/Component.tsx` | | `FormTemplateBuilder.buildDefinition` | `formDefinition` | `view/forms/MainForm/form.ts` | | `FormDialogTemplateBuilder` | `formDialog` | `view/widgets/ManageTrigger.tsx` | | `DataTableTemplateBuilder` | `dataTable` | `view/widgets/DataTable.tsx` | | `ListPageTemplateBuilder` | `list` | `pages/ListPage/index.tsx` | | `MenuTemplateBuilder` | `menu` | `config/menu.ts` | | `ModuleTemplateBuilder` | `module` | `config/module.ts` | If form generation is disabled, `form`, `formDefinition`, and `formDialog` are `null`. If datatable generation is disabled, `dataTable` and `menu` are `null`, while the list-page builder emits a page without a table. ## Generated Frontend Architecture ```txt apps/admin/src/modules// ├── api/ │ ├── create.ts │ ├── delete.ts │ ├── detailed.ts │ ├── keys.ts │ ├── list.ts │ └── update.ts ├── config/ │ ├── translation/ │ ├── menu.ts │ ├── messages.ts │ ├── meta.ts │ ├── module.ts │ └── routing.tsx ├── entities/ │ └── Entity.ts ├── pages/ │ └── ListPage/ │ └── index.tsx └── view/ ├── forms/ │ └── MainForm/ │ ├── Component.tsx │ ├── constants.ts │ ├── form.ts │ ├── index.ts │ └── submit.ts ├── layouts/ │ └── Layout.tsx └── widgets/ ├── DataTable.tsx ├── DeleteTrigger.tsx └── ManageTrigger.tsx ``` The `api` directory intentionally has no barrel file. Consumers import each operation directly, for example: ```ts import { useCreate } from "../../../api/create"; import { invalidateDetailed } from "../../../api/detailed"; import { invalidateList } from "../../../api/list"; import { useUpdate } from "../../../api/update"; ``` Each CRUD operation remains isolated in its own file. `keys.ts` owns React Query key builders, while `list.ts` and `detailed.ts` own their cache invalidation helpers. ## Layer Responsibilities - `entities/Entity.ts` is generated from database columns and is shared by API hooks, forms, and widgets. - `api/` owns Axios calls, React Query hooks, cache keys, and mutation notifications. - `pages/` owns route-level composition and permission page gates. - `view/forms/` owns schema, form values, UI integration, and submission orchestration. - `view/widgets/` owns stateful table, delete, and manage interactions. - `config/` integrates routes, menu, translations, metadata, and permissions with the app module registry. ## Extending the Frontend Generator When adding a new generated frontend artifact: 1. Add its configuration type under `apps/admin/src/devtools/entities/`. 2. Add UI controls to `ModuleGeneratorForm`. 3. Add a focused builder under `data/builders/` if the artifact contains dynamic source. 4. Add the payload field to `GenerateModulePayload` and `buildGenerateModulePayload`. 5. Accept and write the field in `backend/app/controllers/module_controller.ts`. 6. Add the static structure to `apps/admin/src/modules/_template/` when every module needs it. 7. Verify generation with and without the new asset selected.