Architecture Overview

Gen-X generates complete, production-ready Go web applications from a structured description called a depiction. You write a depiction script in Go that declares your application’s models, forms, validations, views, and routes using the Depicter API. Gen-X executes that script and emits a fully wired Go application — handlers, Maestros, fetchers, serializers, migrations, and all. No templates are filled in manually; the output is real, compilable code derived from your declarations.

The Generation Pipeline

When you run a depiction script, Gen-X processes your declarations through a layered pipeline. Each layer has a single responsibility and delegates to the next.

Depiction Script
      |
      v
  Depicter          <- High-level facade; your API surface
      |
      v
  Appliers          <- Post-creation orchestrators; run side-effects after each entity is saved
      |
      v
Configurators       <- Generate service configurations; wired by each Applier
      |
      v
  Handlers          <- Persist entities to the Gen-X database
      |
      v
Generated App Code  <- Written to the output directory (default: /tmp/gen-output/<app-name>)

Depicter — The single entry point for depiction scripts. Every call to AddModel, AddFormField, AddRouter, and so on passes through the Depicter, which coordinates the layers below it.

Appliers — After any entity (model, field, actor, relation, …) is persisted, the corresponding applier runs. Appliers are responsible for the cascade: creating dependent services, registering routes, seeding CRUD actors, and triggering configurators. The ModelCreateApplier, for example, creates all six CRUD configurators, seeds the utility fields, and registers the model’s services — all triggered by a single AddModel call.

Configurators — Configurators write structured configuration data for specific service types: model services, form presenters, Maestro structures, routes, breadcrumbs, and more. They do not write Go source files; they write the service records that the code-generation step later renders into Go.

Handlers — The Handler layer executes the actual database operations against the Gen-X internal database (the project graph). Every entity created during generation is stored here and later read by the serializers and code writers that produce the final output files.

Generated App Code — The final output: a complete Go application written to the configured output directory. The generated code follows the X-Go framework conventions and is ready to compile, run, and extend.

Core Concepts

Projects and Services

A project in Gen-X is the top-level container for everything that will be generated. It holds the application name, package name, output directory, port configuration, and a graph of services.

A service is the internal representation of any generated unit of code — a Maestro, a handler, a fetcher, a form presenter, a route, a view, a section, and so on. Services have a kind, optional data (stored as JSON), and can reference other services via injections and imports. When Gen-X writes the final output, it reads each service’s configuration and renders the corresponding Go source file.

The Depiction Script

A depiction script is a plain Go program — typically depict.go in your project’s root — that imports the Gen-X API and calls Depicter methods to declare your application. It is not a configuration file; it is executable Go code, which means you can use loops, conditionals, and helper functions to build complex applications programmatically.

The script is run with go run depict.go (usually via an environment-prefixed command like ENV=dev go run depict.go). Gen-X executes the script, processes all declarations through the generation pipeline, and writes the output files.

⚠️ Warning: Running a depiction script will overwrite generated files in the output directory. Files annotated with // |@@| W in the input directory are treated as intentional overrides and will replace their generated counterparts. Review the File Header Reference before running in a project with existing customisations.

The |@@| Annotation System

Gen-X uses a comment-based annotation system to control how individual Go files are handled during generation and subsequent re-generation. The annotation // |@@| <flag> at the top of a file tells Gen-X what to do when writing that file to the output directory. For example, // |@@| W marks a file as a manual override that should always be copied from the input directory, while // |@@| C marks a file as generated and safe to regenerate. See File Header Reference for the complete list of flags and their behaviour.

Key Components

Depicter

The Depicter is the high-level façade used in depiction scripts. It provides the complete public API for declaring models, forms, actors, routers, menus, and all other application elements, and delegates all persistence and side-effect work to the layers beneath it.

See Depicter API Reference for the full method reference.

Handlers

The Handler is the generic database persistence layer that sits between Maestro steps and the sql_db abstraction. It provides a unified interface for Create, Update, and Delete operations with automatic audit-field management, field validation, spy logging, and optional transaction support.

See Handler for the full reference.

Hydrator

The Hydrator provides a structured mechanism for declaring which related entities (associations) should be loaded alongside a primary entity. Fetchers use it to implement explicit opt-in loading, avoiding N+1 query patterns by only executing the SQL for associations the caller has declared via HydratorMod.AddHydratingPath.

See Hydrator for the full reference.

Fetcher

The Fetcher provides dynamic SQL SELECT query building with type-safe filtering, sorting, and pagination. It is the foundation for all data-retrieval services in the generated application. The FetcherMod configuration object accumulates filters, sort orders, and pagination settings before BuildSelect assembles and executes the query.

See Fetcher for the full reference.

Appliers

Appliers are post-creation orchestrators. After any domain entity is persisted to the Gen-X database, the corresponding applier runs a cascade of side-effects: creating dependent services, configuring CRUD actors, regenerating related structures, and keeping the project graph consistent. The ModelCreateApplier and ProjectCreateApplier are the two most substantial appliers; understanding their behaviour explains most of what AddModel and project initialisation produce.

See Appliers for the full reference.

Serializers

Serializers convert Gen-X domain model entities to JSON for API responses within the Gen-X application itself (not the generated app). Each serializer exposes OneToJson and SetToJson methods and follows a consistent structure across all entity types.

See Serializers for the full reference.


The Blue-Lila CRUD Approach

Gen-X does not generate generic CRUD screens. Instead, it uses an actor model that classifies every user-facing operation by its intent, producing views and routes that reflect what the user is actually doing rather than what table is being edited.

The Actor Model

An Actor is the unit of user-facing functionality in a generated application. Every actor produces a Maestro (the controller), a view, and one or more routes. The actor’s kind determines the Maestro structure and the HTTP verbs that are registered.

The four actor kinds are:

See — A read actor that always pairs with exactly one Perform actor. See generates the GET route that renders a form. Its paired Perform actor generates the POST route that processes the submission. Together they implement the complete read/write lifecycle of a form-based operation.

Display — A read-only actor that presents information. A Display actor generates a GET route and a view. It can be associated with zero or more Perform actors that offer actions from within the same page. Use Display for consumer-facing information views where the user reads data and optionally triggers actions via buttons.

Show — A data-centric read actor for CRUD detail views. Show is part of the standard CRUD set generated automatically when AddModel is called with crud: true. It is closely bound to a single model and presents one entity instance in detail.

Perform — A write actor. Perform handles form submissions or any state-changing operation. It is always paired with a See actor (for form flows) or attached to a Display actor (for action buttons). The Perform actor’s Maestro contains the steps that validate input, persist changes, and record audit events.

The structural rules of the actor model:

Rule Description
See always has exactly 1 Perform See/Perform is the canonical pair for all form-based interactions
Display has 0–N Performs A display page is read-only by default; Performs add optional actions
Show is data-centric (CRUD) Show belongs to the generated CRUD set and is tied to a single model
Perform is always paired A Perform actor is never created in isolation; it is always a child of See or Display

The Standard CRUD Set

When you call AddModel(ctx, config, "Task", true), the ModelCreateApplier generates the following actor set automatically:

Actor Kind HTTP Description
NewTask See GET /tasks/new Render the create form
CreateTask Perform POST /tasks Process the create form
EditTask See GET /tasks/:id/edit Render the edit form
UpdateTask Perform POST /tasks/:id Process the edit form
ShowTask Show GET /tasks/:id Display a single entity
ListTasks Display GET /tasks Display the entity list
DeleteTask Perform DELETE /tasks/:id Delete an entity

This set covers the complete CRUD lifecycle. Use the Depicter’s section and view methods to add, hide, or reorder elements within any of these generated views.

💡 Tip: You do not need to call AddModel with crud: true for every model. System models, lookup tables, or models that are only accessed via relations from other models can be created with crud: false to skip actor generation entirely.


Next Steps