# Module Generator Frontend The generator UI collects module metadata, selected assets, form layout, and datatable configuration, converts it into TypeScript/TSX source strings, and sends them to the backend generator. | Responsibility | Source (under `apps/admin/src/devtools/`) | | ------------------------------------------------------ | ------------------------------------------------------------- | | Page submission, notifications, and mutation callbacks | `pages/ModuleGeneratorPage/index.tsx` | | Payload assembly | `pages/ModuleGeneratorPage/lib/buildGenerateModulePayload.ts` | | Form state, initial values, and sections | `view/forms/ModuleGeneratorForm/` | | Payload DTOs and HTTP client | `data/api/` | | React Query hooks | `data/queries/` | | Source-code builders | `data/builders/` | The page submits through `useGenerateModule`; success resets the form and shows an alert, errors go through the shared React Query error helpers. ## Metadata and Assets Required metadata: `name` (frontend folder, backend module identity, route segment, permission-slug base), `table` (existing PostgreSQL table), `generate` (selected assets). Backend assets are all selected by default; form and datatable are opt-in. | 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 | Before generation the UI reads `GET /makeModule/tables` (table selector) and `GET /makeModule/columns/:table` (field choices) — cached via React Query, columns disabled until a table is selected. ## Payload Builders `buildGenerateModulePayload` delegates to focused builders: | Builder | Payload field | Generated destination | | ----------------------------------- | ---------------- | ----------------------------------- | | `FormSourceBuilder.buildComponent` | `form` | `view/forms/MainForm/Component.tsx` | | `FormSourceBuilder.buildDefinition` | `formDefinition` | `view/forms/MainForm/form.ts` | | `ManageTriggerSourceBuilder` | `formDialog` | `view/widgets/ManageTrigger.tsx` | | `DataTableSourceBuilder` | `dataTable` | `view/widgets/DataTable.tsx` | | `ListPageSourceBuilder` | `list` | `pages/ListPage/index.tsx` | | `MenuSourceBuilder` | `menu` | `config/menu.ts` | | `ModuleConfigSourceBuilder` | `module` | `config/module.ts` | Form disabled → `form`, `formDefinition`, `formDialog` are `null`. Datatable disabled → `dataTable` and `menu` are `null`, and 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 (from database columns) ├── pages/ListPage/ └── view/ ├── forms/MainForm/ # Component.tsx, constants.ts, form.ts, index.ts, submit.ts ├── layouts/Layout.tsx └── widgets/ # DataTable.tsx, DeleteTrigger.tsx, ManageTrigger.tsx ``` `api/` deliberately has no barrel file — each CRUD operation is its own file, imported directly (`import { useCreate } from "../../../api/create"`); `keys.ts` owns query key builders, `list.ts`/`detailed.ts` their invalidation helpers. Layer ownership: `entities/Entity.ts` is shared by API hooks, forms, and widgets; `api/` owns Axios calls, hooks, keys, and notifications; `pages/` owns route composition and permission gates; `view/forms/` owns schema, values, UI, and submission; `view/widgets/` owns stateful interactions; `config/` integrates routes, menu, translations, and permissions with the module registry. ## Extending To add a generated frontend artifact: add its configuration type under `entities/`, UI controls to `ModuleGeneratorForm`, a focused builder under `data/builders/` (for dynamic source), the payload field to `GenerateModulePayload` + `buildGenerateModulePayload`, accept and write it in `module_controller.ts`, and add static structure to `_template/` when every module needs it. Verify generation with and without the asset selected.