Skip to content

Module Config Reference

The module config is a PHP array (or JSON object) that fully describes a single module to be generated. It is the primary input for all generator classes.


Top-Level Keys

json
{
  "id":                "string (UUID v5 derived from module name)",
  "module_name":       "Products",
  "module_type":       "Custom",
  "table_name":        "products",
  "id_type":           "uuid | bigint",
  "module_group_name": "Core | Custom | null",
  "version":           "1.0.0",
  "columns":           [],
  "indexes":           [],
  "morphs":            [],
  "features":          {},
  "delegations":       {},
  "actions":           {},
  "processors":        [],
  "seeder":            [],
  "menu_config":       {},
  "constants":         {}
}
KeyTypeRequiredDescription
idstringNoUUID v5 identifier. Auto-set by introspection.
module_namestringYesStudlyCase singular name, e.g. Products.
module_typestringNo"Custom" or "Core". Affects namespace/path. Default "Custom".
table_namestringYesExact DB table name, e.g. products.
id_typestringNo"uuid" (default) or "bigint". Affects model and migration.
module_group_namestring|nullNoSub-group label. Used in some menu groupings.
versionstringNoSemantic version. Default "1.0.0".
columnsarrayYesColumn definitions — see columns.md.
indexesarrayNoAdditional composite indexes beyond single-column ones.
morphsarrayNoPolymorphic relationship declarations — see below. A genuine flat array (unlike delegations/actions) — auto-detected by introspection, rarely hand-authored.
featuresobjectYesBackend + frontend + mobile feature config — see features-config.md.
delegationsobjectNoRelated-module tab/modal panels, keyed by delegation key — see delegations.md.
actionsobjectNoCustom action buttons and services, keyed by action key — see actions.md.
processorsarrayNoPipeline hooks (before/after save/delete) — see processors.md.
seederarrayNoSeed rows. Each entry is a flat object matching column names.
menu_configobject|nullNoNavigation placement — see below.
constantsobjectNoFlat { CONST_NAME: value } map — see below.

List filters. features.backend.list.filterFields can be left empty — it auto-derives type-aware filters from filterableFields, and id/uuid/ created_at are always added as default filters regardless of config. See features-config.md § Filter fields for the full behavior.


morphs Array

Declare polymorphic relationships on this table. Auto-detected by schema introspection (a {prefix}_type/{prefix}_id column pair) — name/type_column/id_column are populated for you; only targets is ever hand-authored.

json
"morphs": [
  {
    "name": "commentable",
    "type_column": "commentable_type",
    "id_column": "commentable_id",
    "targets": [
      { "alias": "post", "model": "App\\Project\\Modules\\Custom\\Posts\\PostsModel", "module": "Posts", "label": "Post" }
    ]
  }
]

The generator uses this to emit a morphTo() relationship method and correct migration lines ($table->morphs('commentable') on regeneration) — always, whether or not targets is set. morphMany()/morphOne() (the inverse, on the target side) is not emitted — that stays a manual add if you want e.g. $post->comments to work.

targets (optional, never auto-guessed) drives two things once populated: a morph-select create/edit field (type dropdown + API-backed record picker, replacing the fallback plain text/number input pair) and a Relation::morphMap() registration on this module's own generated boot() method. Each entry requires alias/model/module/label; option_label is optional (which field to show in the record picker, defaults to name). The same alias registered for two different model values across the whole project is a hard-fail at generation time — see the morphs example page for the full config shape and behavior.


Controls where this module appears in the navigation sidebar.

json
"menu_config": {
  "enabled":       true,
  "section":       "main",
  "section_label": "Main Menu",
  "icon":          "Package",
  "permission":    "Products.list",
  "nested":        false,
  "items": [
    {
      "title":      "All Products",
      "url":        "/products/list",
      "icon":       "List",
      "permission": "Products.list",
      "children":   []
    }
  ]
}
KeyTypeDefaultDescription
enabledbooleantrueSet false to hide from nav entirely.
sectionstring"main"ID of the nav section to place this module in.
section_labelstringOptional override for the section heading text.
iconstring"File"Lucide icon name.
permissionstring"{Module}.list"Guard permission for this nav item.
nestedbooleanfalseIf true, renders a parent item with List and Create children.
itemsarrayFully custom nav items. Overrides the auto-generated entry.

constants Object

Corrected 2026-08-02

constants is a flat key → value map, not an array of named groups. This page previously showed [{"name": "STATUS", "values": [...]}] — verified against ModelGenerator::generateConstants()'s actual source: foreach ($constants as $name => $value) { ... "public const {$name} = ...;" }.

Defines PHP public const values emitted directly on the generated model — used both by createSplash/editSplash features (field-level splash dropdowns) and, separately, by bulk_actions[].status_target (see features-config.md), which references a constant here by name to resolve the numeric status_id value to transition to.

json
"constants": {
  "ACTIVE":   1,
  "INACTIVE": 2,
  "RECEIVED": 3
}

Each key becomes public const {KEY} = {VALUE}; on the model — a numeric value is emitted unquoted (public const ACTIVE = 1;), anything else is quoted as a PHP string (public const STATUS = 'draft';).


seeder Array

Simple array of row objects to seed the table. Keys must match column names.

json
"seeder": [
  { "name": "Electronics", "code": "ELEC", "color": "blue" },
  { "name": "Clothing",    "code": "CLO",  "color": "green" }
]

indexes Array

Additional indexes beyond those auto-created from unique: true on columns.

json
"indexes": [
  { "columns": ["category_id", "status_id"], "unique": false }
]

Complete Minimal Example

json
{
  "module_name":    "Products",
  "module_type":    "Custom",
  "table_name":     "products",
  "id_type":        "uuid",
  "columns": [
    {
      "name": "name",
      "type": "string",
      "nullable": false,
      "unique": false,
      "featureSelections": {
        "backend":  { "create": true, "list": true, "view": true, "edit": true, "delete": false },
        "frontend": { "create": true, "list": true, "view": true, "edit": true, "delete": false }
      }
    }
  ],
  "features": {
    "backend": {
      "list":   { "endpoint": { "method": "GET",    "path": "/products",       "permission": "Products.list"   } },
      "create": { "endpoint": { "method": "POST",   "path": "/products",       "permission": "Products.create" } },
      "view":   { "endpoint": { "method": "GET",    "path": "/products/{uuid}", "permission": "Products.view"   } },
      "edit":   { "endpoint": { "method": "PUT",    "path": "/products/{uuid}", "permission": "Products.edit"   } },
      "delete": { "endpoint": { "method": "DELETE", "path": "/products/{uuid}", "permission": "Products.delete" } }
    },
    "frontend": {
      "list":   { "primaryField": "name", "fields": [] },
      "create": { "fields": [] },
      "view":   { "titleData": "name", "fields": [] },
      "edit":   { "fields": [] },
      "delete": { "fields": [] }
    },
    "mobile_app": { "enabled": false }
  },
  "menu_config": { "section": "main", "icon": "Package" }
}

Corrected 2026-08-02

This page previously linked to examples/module-config-full.json, which does not exist in this repository. See Examples instead — a set of worked, task-oriented recipes, each pointing at a real config that was actually generated and verified end-to-end (not a static example file).

Released under the Apache-2.0 License.