Generate your first module
StackRivet’s code generator doesn’t just write CRUD. From a single database table it generates a reviewable module bundle: backend layers, frontend pages, permission seed SQL, OpenAPI annotations, a test scaffold, a module manifest and AI-readable module context — all of it respecting the architecture and security rules.
The generator lives inside the product (admin UI plus the /api/v1/generator API); you don’t run a separate tool. Preview creates an immutable, hash-addressed bundle. You can inspect exact content/diff, download the same ZIP and then apply that exact hash to a review directory (generated-output by default).
Before you start
Section titled “Before you start”- Have the backend and admin UI running (see Installation).
- Have a database table to generate from. The generator reads tables from MySQL 8.4 or PostgreSQL 18.4.
For a first run, create this small tutorial table in the local MySQL container:
cd stackrivet-serverdocker compose exec -T mysql mysql -ustackrivet -pstackrivet stackrivet <<'SQL'CREATE TABLE IF NOT EXISTS biz_todo_item ( id VARCHAR(32) NOT NULL, tenant_id VARCHAR(32) NOT NULL DEFAULT 'default', title VARCHAR(120) NOT NULL COMMENT 'Todo title', priority INT NOT NULL DEFAULT 3 COMMENT 'Priority', status VARCHAR(20) NOT NULL DEFAULT 'open' COMMENT 'Status', due_at DATETIME NULL COMMENT 'Due time', remark VARCHAR(500) NULL COMMENT 'Remark', created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, deleted TINYINT(1) NOT NULL DEFAULT 0, PRIMARY KEY (id), KEY idx_biz_todo_item_tenant_status (tenant_id, status), KEY idx_biz_todo_item_due_at (due_at)) COMMENT='Todo item tutorial table';SQLThe flow
Section titled “The flow”select a table → import metadata → configure fields → immutable preview→ inspect content/diff → download ZIP or apply exact hash → review and merge1. Open the generator
Section titled “1. Open the generator”Open http://127.0.0.1:5173/generator and sign in if needed. The page is also available from the admin navigation as Code Generator.
Click Import table, choose biz_todo_item, then set Strip prefix to biz_, Module name to todo and Package name to com.stackrivet.demo.todo before importing. The generator reads columns, types, primary key and comments while preserving those generation boundaries.
GET /api/v1/generator/database-tables # browse available tablesPOST /api/v1/generator/tables/import # import the selected table(s)This creates the sr_gen_table and sr_gen_column config rows. If the table was already imported, the API rejects the duplicate unless an overwrite import is requested; overwriting rebuilds the column config from the database metadata.
2. Configure fields
Section titled “2. Configure fields”Click Configure on the imported row. Verify Module name is todo, Feature name is todoItem and Package name is com.stackrivet.demo.todo; these values drive the frontend folder, permission prefix and Java package. For each column, set how it appears in the list, the form, queries, validation, dictionary and control type. StackRivet applies sensible defaults from the column type:
| DB type | Java | Control |
|---|---|---|
| varchar / text | String | input / textarea |
| integer / bigint | Integer / Long | number input |
| decimal | BigDecimal (never double, for money) | decimal input |
| boolean / tinyint(1) | Boolean | switch |
| date / datetime | LocalDate / LocalDateTime | date / datetime picker |
*_asset_id | String | asset uploader (auto-detected) |
*_dict | String | select |
id, tenant_id, created_at, updated_at and deleted stay out of the normal form by default. The stricter server contract locks Form off for tenant_id, dept_id, created_by and updated_by, because those values come from trusted runtime context. It also locks List off for tenant_id, deleted and deleted_at, which are absent from generated response DTOs; list display remains configurable for dept_id, created_by and updated_by. If you mark a field as a query condition, make sure the table has a matching index before you merge the module.
Controls also declare runtime dependencies. An asset control requires stackrivet-asset plus asset:asset:create and asset:asset:list; a select with a dictCode requires stackrivet-system plus system:dict:list. The generated manifest records only dependencies actually used, and the permission seed grants their existing active menu permissions to the deployment role. Do not clear a dependency warning unless you also remove the control that needs it.
For the tutorial table, keep title, priority, status, due_at and remark visible in the form. Enable query on status and due_at so the generated list page has useful filters.
3. Review the generated menu and permissions
Section titled “3. Review the generated menu and permissions”The generator produces a permission seed SQL file with a menu entry plus menu, button and API permissions for the module, so it is locked down by default. The seed is bound to the source tenant and contains a required __SR_ROLE_ID__ deployment placeholder; replace it with an active, non-deleted role from that same tenant before turning the file into a Flyway migration. See Add a permission for the permission model.
4. Preview, then apply
Section titled “4. Preview, then apply”Click Preview. The generator always previews before it writes. Preview returns an expectedHash, template version, governance status and the exact file content, content hash, current-target hash and unified diff. Each file is CREATE, MODIFIED or UNCHANGED.
POST /api/v1/generator/tables/{id}/previewGET /api/v1/generator/tables/{id}/bundles/{expectedHash}POST /api/v1/generator/tables/{id}/applyApply uses a JSON body bound to the reviewed bundle:
{ "expectedHash": "<lowercase SHA-256 from preview>", "overwriteModified": false}overwriteModified defaults to false. If a target changes after preview,
Apply returns a stale/conflict response and writes nothing; re-preview instead
of retrying an old hash. Apply stages all files and replaces the target
atomically, so a failure cannot leave a partial tree.
Community defaults retain bundles for 24 hours, at most 5 bundles per table,
with a 5 MiB bundle limit and 1 MiB content/diff inspection limit. Operators can
change bundle-root, bundle-ttl, max-bundles-per-table,
max-bundle-bytes and max-inspection-bytes under stackrivet.generator.
What you get
Section titled “What you get”Generated files are staged under generated-output/ unless you configured another output root.
| Area | Files |
|---|---|
| Backend | {Name}Entity, {Name}Mapper, {Name}Service + Impl, {Name}Controller, Create/Update/Query DTOs, a Response VO |
| Frontend | {resource}.api.ts, a list page, a form drawer and an auto-discovered generated route descriptor |
| Governance | menu + button + API permission seed, OpenAPI annotations, a base test, module manifest, AI-readable module context |
The generated backend follows the same rules as hand-written modules: the Controller does not call a Mapper directly, DTO/VO are not reused entities, list APIs paginate (max pageSize 200), and generated files carry template metadata and file hashes for the upgrade path.
After generating
Section titled “After generating”The staged bundle is ready to merge, but it is not automatically part of the running app. Follow Land a generated module by hand for the full beginner workflow:
- Choose the target Maven module, or create a new one with root reactor, BOM and
stackrivet-appdependency updates. - Copy backend files from
generated-output/src/...into that Maven module. - Replace the same-tenant deployment role placeholder, then rename
generated-output/db/migration/<module>-<resource>__permissions.sqlto the next Flyway version and place it undercommon/,mysql/orpostgresql/. - Copy
generated-output/frontend/src/...intostackrivet-admin-ui/src/...; this includessrc/generated/routes/<module>-<resource>.ts. - Verify that the generated route descriptor path/permission matches
sr_sys_menu; the Admin UI discovers it at build time and fails on duplicate paths/names. - Verify RBAC, menu visibility and API access before customizing further.
An AI tool can read the generated module context to extend the module safely; see AI coding workflow.
After you merge the staged files, a minimal verification loop is:
cd stackrivet-server./mvnw -pl <target-module> -am test./mvnw -pl stackrivet-app -am package -DskipTestsjava -jar stackrivet-app/target/stackrivet-app.jar
cd ../stackrivet-admin-uipnpm typecheckpnpm devEdition boundary
Section titled “Edition boundary”Community generates single-table modules with immutable preview, exact ZIP and atomic Apply safeguards. Master-detail, tree, many-to-many and upgrade compatibility automation remain labeled Roadmap in the Team pilot; see the pricing page.