{"id":51544944,"url":"https://github.com/robertolima-dev/gize","last_synced_at":"2026-07-10T18:00:33.928Z","repository":{"id":369345025,"uuid":"1289392986","full_name":"robertolima-dev/gize","owner":"robertolima-dev","description":"Productivity-first backend framework for Rust","archived":false,"fork":false,"pushed_at":"2026-07-08T19:20:37.000Z","size":428,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-09T17:26:32.410Z","etag":null,"topics":["axum","batteries-included","framework","rust","sqlx"],"latest_commit_sha":null,"homepage":"https://gize-rust-framework.vercel.app/en","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/robertolima-dev.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":"docs/roadmap.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-07-04T17:33:51.000Z","updated_at":"2026-07-08T23:03:45.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/robertolima-dev/gize","commit_stats":null,"previous_names":["robertolima-dev/gize"],"tags_count":24,"template":false,"template_full_name":null,"purl":"pkg:github/robertolima-dev/gize","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robertolima-dev%2Fgize","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robertolima-dev%2Fgize/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robertolima-dev%2Fgize/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robertolima-dev%2Fgize/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/robertolima-dev","download_url":"https://codeload.github.com/robertolima-dev/gize/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robertolima-dev%2Fgize/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35338653,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-10T02:00:06.465Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["axum","batteries-included","framework","rust","sqlx"],"created_at":"2026-07-09T17:01:45.852Z","updated_at":"2026-07-10T18:00:33.864Z","avatar_url":"https://github.com/robertolima-dev.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# Gize\n\n**Productivity-first backend framework for Rust.**\n\nDjango-like velocity (scaffolding, conventions, generators, migrations)\nwithout giving up Rust's guarantees, performance, or transparency.\n\n[![License](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](#license)\n[![Rust](https://img.shields.io/badge/rust-1.85%2B-orange.svg)](https://www.rust-lang.org)\n[![Status](https://img.shields.io/badge/status-MVP-yellow.svg)](#project-status)\n\n\u003c/div\u003e\n\n\u003e The name comes from the plateau of the Great Pyramids: solid foundations meant to last.\n\nGize lets you go from an empty directory to a running, production-shaped CRUD API in\nminutes. It generates **idiomatic Rust you own**: plain Axum handlers, plain SQLx\nqueries, plain SQL migrations. No hidden runtime, no reflection, no magic. Delete Gize and\nyou still have a working, idiomatic Rust codebase.\n\n---\n\n## Table of contents\n\n- [Why Gize?](#why-gize)\n- [Philosophy](#philosophy)\n- [Project status](#project-status)\n- [Installation](#installation)\n- [Quickstart](#quickstart)\n- [Command reference](#command-reference)\n- [The generated project](#the-generated-project)\n- [Built-in `users` resource](#built-in-users-resource)\n- [Models and field types](#models-and-field-types)\n- [Anatomy of a generated CRUD resource](#anatomy-of-a-generated-crud-resource)\n- [The `gize.toml` manifest](#the-gizetoml-manifest)\n- [Database and migrations](#database-and-migrations)\n- [Runtime configuration](#runtime-configuration)\n- [The safety model](#the-safety-model)\n- [Architecture](#architecture)\n- [Developing Gize](#developing-gize)\n- [Roadmap](#roadmap)\n- [Comparison](#comparison)\n- [Contributing](#contributing)\n- [License](#license)\n\n---\n\n## Why Gize?\n\nRust is excellent for backends (fast, safe, predictable) but **starting** a real project\nis slow. There is no blessed layout, no scaffolding, no generators. Every team hand-wires a\nrouter, a database pool, config, migrations, error handling, and repeats the\nmodel → migration → repository → service → DTO → handler → routes → tests dance for every\nresource.\n\nGize removes that day-one tax. One command scaffolds the project; one command generates a\nfull CRUD resource wired end-to-end; one command applies migrations; one command runs it.\nWhat you get is normal Rust you can read and edit: Gize writes the boring 80%, you own\n100%.\n\n## Philosophy\n\n- **Zero-cost abstractions.** Generated code is idiomatic and explicit.\n- **No magic.** No hidden framework runtime; everything is a file you can read and diff.\n- **You own the code.** Gize is an accelerator, not a cage: remove it and the app still\n  works.\n- **No unnecessary dependencies.** Every dependency is justified in an ADR.\n- **Convention over configuration**, but customization is always possible.\n- **Analyze, then decide, then implement.** Every significant choice is recorded as an ADR\n  in [`ADR/`](./ADR).\n\n## Project status\n\n**Release Candidate (v0.8.x).** The Beta feature set (Admin UI, OpenAPI, multi-database, plugin\nAPI) is complete and the **1.0 feature set is frozen** — the project is now hardening rather than\nadding features. See [`STABILITY.md`](./STABILITY.md) for what is stable and the deprecation\npolicy, [`SECURITY.md`](./SECURITY.md) for the generated apps' security model, and the\n[roadmap](./docs/roadmap.md) for what remains before 1.0 (benchmarks, docs). New frameworks such\nas Actix are planned for v2.0.\n\n| Command | State | What it does |\n| --- | --- | --- |\n| `gize new` | ✅ | Scaffold a project (built-in `users` + auth; `--database sqlite\\|mysql`, `--openapi`, `--api-version`, `--ws`) |\n| `gize make app` | ✅ | Scaffold a module and wire it in |\n| `gize make model` | ✅ | Generate a model + migration |\n| `gize make crud` | ✅ | Generate a full CRUD resource (incl. `belongs_to`) |\n| `gize make migration` | ✅ | Blank (named) or model-diff `ALTER` migrations |\n| `gize make admin` | ✅ | Generate a separate React admin SPA for all resources |\n| `gize sync` | ✅ | Reconcile the project from `gize.toml` |\n| `gize migrate` | ✅ | Apply / inspect migrations (Postgres, SQLite or MySQL) |\n| `gize createadmin` | ✅ | Create the first admin user (interactive or CI) |\n| `gize serve` | ✅ | Build and run the app (and the admin dev server, when present) |\n| `gize fmt` / `gize check` | ✅ | rustfmt / clippy wrappers |\n| `gize doctor` | ✅ | Diagnose environment/project |\n| `gize \u003cplugin\u003e` | ✅ | Run a `gize-\u003cname\u003e` plugin (plugin API v0) |\n\nNew in Beta: **`gize make admin`** (Vite + React + TS SPA, data-driven from the manifest),\n**OpenAPI** generation (`--openapi` → `/openapi.json` + `/docs`), **SQLite** behind a database\nseam (`gize new --database sqlite`), and a **plugin API** (`gize-\u003cname\u003e` subcommands). See\n[`docs/roadmap.md`](./docs/roadmap.md) for the full plan (MVP → Alpha → Beta → RC → v1.0 →\nv2.0).\n\n## Installation\n\n**From crates.io:**\n\n```bash\ncargo install gize   # installs the `gize` binary\n```\n\n**From source:**\n\n```bash\ngit clone https://github.com/robertolima-dev/gize\ncd gize\ncargo build --release\n# the CLI binary is target/release/gize\ncp target/release/gize /usr/local/bin/   # or add target/release to PATH\n```\n\n### Prerequisites\n\n- Rust **1.85+** (edition 2024).\n- **PostgreSQL** for running generated apps (`gize migrate` / `gize serve`).\n\n## Quickstart\n\nBuild a working product API in four commands.\n\n```bash\n# 1. Scaffold a project (Axum + SQLx + PostgreSQL)\ngize new shop\ncd shop\n\n# 2. Generate a full CRUD resource\ngize make crud Product name:String price:i32 active:bool\n\n# 3. Point at a database and apply the generated migration\ncp .env.example .env                     # then edit DATABASE_URL if needed\nexport DATABASE_URL=postgres://localhost:5432/shop\ncreatedb shop\ngize migrate\n\n# 4. Run it\ngize serve\n```\n\n\u003e Every new project already ships a **`users` resource** (model, CRUD and a migration with\n\u003e an `is_admin` flag) wired in, so after `gize migrate` you also have working\n\u003e `GET/POST/PUT/DELETE /users` endpoints. Pass `gize new shop --no-user` to skip it. See\n\u003e [Built-in `users` resource](#built-in-users-resource).\n\nNow exercise the API:\n\n```bash\n# Create\ncurl -X POST localhost:8080/products \\\n  -H 'content-type: application/json' \\\n  -d '{\"name\":\"Widget\",\"price\":1299,\"active\":true}'\n# → {\"id\":\"…\",\"name\":\"Widget\",\"price\":1299,\"active\":true,\"created_at\":\"…\",\"updated_at\":\"…\"}\n\ncurl localhost:8080/products            # list\ncurl localhost:8080/products/\u003cid\u003e       # show\ncurl -X PUT localhost:8080/products/\u003cid\u003e \\\n  -H 'content-type: application/json' \\\n  -d '{\"name\":\"Widget\",\"price\":1500,\"active\":false}'   # update\ncurl -X DELETE localhost:8080/products/\u003cid\u003e            # delete → 204\n```\n\nDeleting a missing id returns `404`: the generated typed error maps `RowNotFound` to\n`NOT_FOUND` for you.\n\n## Command reference\n\nGlobal flags on every **generating** command (`new`, `make …`):\n\n| Flag | Effect |\n| --- | --- |\n| `--dry-run` | Print the planned file operations; write nothing. |\n| `--force` | Overwrite files that already exist (otherwise they are skipped). |\n\n### `gize new \u003cname\u003e`\n\nScaffolds a new project into a directory named `\u003cname\u003e`: `Cargo.toml`, `gize.toml`,\n`.env.example`, `.gitignore`, and the full `src/` layout (see below). The project compiles\nand serves immediately.\n\nBy default it also generates a built-in **`users`** resource (model, full CRUD and a\nmigration) already registered in `src/app/mod.rs` and `gize.toml`\n(see [Built-in `users` resource](#built-in-users-resource)).\n\n| Flag | Effect |\n| --- | --- |\n| `--no-user` | Scaffold the bare skeleton, without the built-in `users` resource. |\n| `--database \u003cdb\u003e` | Target database: `postgres` (default), `sqlite` or `mysql` ([ADR-015](./ADR/adr-015-second-database.md)). |\n| `--openapi` | Generate an OpenAPI spec (`/openapi.json`) and docs UI (`/docs`) ([ADR-010](./ADR/adr-010-openapi.md)). |\n| `--api-version \u003cv\u003e` | Mount CRUD routes under a versioned prefix. `--api-version 1` (or `v1`) serves them at `/api/v1/...`; omit for root-mounted routes ([ADR-016](./ADR/adr-016-api-versioning.md)). |\n| `--ws` | Scaffold a WebSocket module (`src/app/ws/`) with a typed echo endpoint at `/ws` ([ADR-018](./ADR/adr-018-websocket.md)). |\n\nWith `--api-version`, the version is recorded in `gize.toml` under `[api]` and the whole API\n(including the OpenAPI paths) is mounted under `/\u003cprefix\u003e/\u003cversion\u003e`:\n\n```toml\n[api]\nversion = \"v1\"\nprefix = \"/api\"\n```\n\nWithout it, routes stay at the root (`/users`) exactly as before — existing projects are\nunaffected.\n\n### `gize make app \u003cname\u003e`\n\nScaffolds an application module `\u003cname\u003e` (the nine files of the module layout) with a\nplaceholder health route, then **registers it idempotently**: adds `mod \u003cname\u003e;` and\n`.merge(\u003cname\u003e::routes())` to `src/app/mod.rs` and appends it to `[modules]` in\n`gize.toml`. Re-running is a no-op.\n\n### `gize make model \u003cName\u003e field:Type …`\n\nGenerates `src/app/\u003ctable\u003e/model.rs` (an `sqlx::FromRow` struct with `id` + timestamps) and\na `CREATE TABLE` migration. The module directory is the pluralized snake_case of the model\n(`User` → `users`).\n\n### `gize make crud \u003cName\u003e field:Type …`\n\nThe headline command. Generates a complete, wired vertical slice for the resource:\n\n```\nsrc/app/\u003ctable\u003e/\n  mod.rs          model.rs      dto.rs        error.rs\n  repository.rs   service.rs    handler.rs    routes.rs      tests.rs\nmigrations/\u003cts\u003e_create_\u003ctable\u003e.sql\n```\n\n…and registers the module in `src/app/mod.rs` and `gize.toml`. The result exposes working\n`GET / POST / PUT / DELETE` endpoints backed by the database.\n\n```bash\ngize make crud Product name:String price:i32 active:bool\ngize make crud Order   total:i64 paid:bool\ngize make crud Article title:String body:String published:bool --dry-run\n```\n\n### `gize migrate [--status]`\n\nApplies pending migrations from `migrations/*.sql` against `DATABASE_URL`, using SQLx's\nmigrator (tracked in the `_sqlx_migrations` table, ordered and idempotent).\n\n```bash\ngize migrate            # apply all pending\ngize migrate --status   # list applied [x] vs pending [ ]\n```\n\n### `gize createadmin`\n\nCreates the first admin user (`is_admin = true`) in the database — Gize's `createsuperuser`\n([ADR-017](./ADR/adr-017-createadmin.md)). Reads the dialect from `gize.toml` and connects with\n`DATABASE_URL`, so it works against Postgres, SQLite or MySQL. The password is hashed with\nArgon2id (the same format the generated login verifies), so the created admin can sign in\nimmediately.\n\n```bash\n# Interactive: prompts for Email, Name, then a hidden (confirmed) Password.\ngize createadmin\n\n# Non-interactive (CI): email/name as flags, password from an env var — never an argument.\nGIZE_ADMIN_PASSWORD=... gize createadmin \\\n  --email admin@example.com --name Admin --password-env GIZE_ADMIN_PASSWORD\n```\n\nA duplicate email is rejected, and if the `users` table has not been migrated yet the command\ntells you to run `gize migrate` first.\n\n### `gize serve`\n\nBuilds and runs the generated application (`cargo run`), streaming its logs. Reads\n`DATABASE_URL` and `PORT` (default `8080`) from the environment.\n\nWhen the project has a generated admin ([ADR-006](./ADR/adr-006-admin.md)), `gize serve` also\nstarts the **admin dev server** alongside the API ([ADR-019](./ADR/adr-019-serve-admin.md)). It\ndetects a package manager (pnpm → npm → yarn), runs the install on first use, and prints both\nURLs; Ctrl-C stops both. This needs Node.js for the admin path only.\n\n```bash\ngize serve                # API + admin dev server (when an admin exists)\ngize serve --api-only     # just the API\ngize serve --admin-only   # just the admin dev server\ngize serve --with-admin   # explicitly both\n```\n\n### `gize doctor`\n\nSanity-checks the environment and project: `cargo`/`rustfmt` availability, whether you are\ninside a Gize project, and whether `DATABASE_URL` is set.\n\n## The generated project\n\n`gize new` produces this layout ([ADR-005](./ADR/adr-005-module-layout.md) explains every\ndirectory):\n\n```\nshop/\n├── Cargo.toml            # axum, tokio, sqlx, serde, uuid, chrono, tracing\n├── gize.toml             # the project manifest\n├── .env.example          # runtime config template\n├── migrations/           # plain SQL migrations (…_create_users.sql ships by default)\n└── src/\n    ├── app/\n    │   ├── mod.rs        # aggregates modules + merges their routers (has gize: markers)\n    │   ├── users/        # built-in resource (unless --no-user); same layout as below\n    │   └── \u003cresource\u003e/   # one directory per resource (added by make app / make crud)\n    │       ├── mod.rs        # declares the module's files, re-exports routes\n    │       ├── model.rs      # domain struct (sqlx::FromRow)\n    │       ├── dto.rs        # request/response payloads\n    │       ├── repository.rs # SQL access (SQLx)\n    │       ├── service.rs    # business logic\n    │       ├── handler.rs    # Axum handlers (HTTP ↔ service)\n    │       ├── routes.rs     # this module's Router\n    │       ├── error.rs      # typed error → IntoResponse\n    │       └── tests.rs      # tests\n    ├── config/           # typed runtime configuration\n    ├── database/         # (reserved) pool/migration hooks\n    ├── middleware/       # (reserved) Tower layers\n    ├── shared/           # (reserved) cross-cutting utilities\n    ├── router.rs         # top-level router; applies AppState\n    ├── state.rs          # AppState { db: PgPool }\n    └── main.rs           # entrypoint: build state, serve\n```\n\nThe `// gize:modules` and `// gize:module-routes` markers in `app/mod.rs` are how `make\napp` / `make crud` wire new modules in without disturbing your code. Leave them in place;\nedit anything else freely.\n\n## Built-in `users` resource\n\nEvery project starts with authentication-ready data. Unless you pass `--no-user`, `gize\nnew` scaffolds a full `users` resource (the same layered slice `gize make crud` produces)\nand wires it into `src/app/mod.rs` and `gize.toml`. Its migration:\n\n```sql\n-- migrations/…_create_users.sql\nCREATE TABLE users (\n    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n    name TEXT NOT NULL,\n    email TEXT NOT NULL UNIQUE,\n    password TEXT NOT NULL,\n    is_admin BOOLEAN NOT NULL DEFAULT false,\n    created_at TIMESTAMPTZ NOT NULL DEFAULT now(),\n    updated_at TIMESTAMPTZ NOT NULL DEFAULT now()\n);\n```\n\n- **`email`** is `UNIQUE`.\n- **`is_admin`** ships from day one as the flag a future admin panel / `gize-auth` can gate\n  access on; it defaults to `false`.\n- **`password`** is marked `#[serde(skip_serializing)]` on the model, so its hash is read\n  from the database but **never serialized into API responses**.\n\n\u003e The `users` resource reuses the generic CRUD templates, so `CreateUser` currently accepts\n\u003e `password` as plain text and lets `is_admin` be set on create. Password hashing, dropping\n\u003e `is_admin` from the create DTO, and register/login endpoints are tracked in\n\u003e [`BACKLOG.md`](./BACKLOG.md) and land with `gize-auth`.\n\n## Models and field types\n\nFields are given inline as `name:Type` (the canonical UX per\n[ADR-012](./ADR/adr-012-cli.md)). Every model also gets an `id: Uuid` primary key and\n`created_at` / `updated_at` timestamps automatically.\n\n| Gize type | Aliases | Rust type | PostgreSQL type |\n| --- | --- | --- | --- |\n| `String` | `str` | `String` | `TEXT` |\n| `bool` | `boolean` | `bool` | `BOOLEAN` |\n| `i32` | `int` | `i32` | `INTEGER` |\n| `i64` | `bigint`, `long` | `i64` | `BIGINT` |\n| `f64` | `float`, `double` | `f64` | `DOUBLE PRECISION` |\n| `Uuid` | (none) | `uuid::Uuid` | `UUID` |\n| `DateTime` | `timestamp` | `chrono::DateTime\u003cUtc\u003e` | `TIMESTAMPTZ` |\n\nTypes are case-insensitive. Unknown types are rejected early with a helpful message.\n\n## Anatomy of a generated CRUD resource\n\n`gize make crud Product name:String price:i32 active:bool` produces a clean layered slice.\nA taste of each layer:\n\n**`model.rs`**\n```rust\n#[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)]\npub struct Product {\n    pub id: uuid::Uuid,\n    pub name: String,\n    pub price: i32,\n    pub active: bool,\n    pub created_at: chrono::DateTime\u003cchrono::Utc\u003e,\n    pub updated_at: chrono::DateTime\u003cchrono::Utc\u003e,\n}\n```\n\n**`repository.rs`** (SQLx runtime queries, compile without a database connection)\n```rust\npub async fn create(pool: \u0026PgPool, input: \u0026CreateProduct) -\u003e Result\u003cProduct, sqlx::Error\u003e {\n    sqlx::query_as::\u003c_, Product\u003e(\n        \"INSERT INTO products (name, price, active) VALUES ($1, $2, $3) RETURNING *\",\n    )\n    .bind(input.name.clone())\n    .bind(input.price)\n    .bind(input.active)\n    .fetch_one(pool)\n    .await\n}\n```\n\n**`handler.rs`** (plain Axum)\n```rust\npub async fn create(\n    State(state): State\u003cAppState\u003e,\n    Json(input): Json\u003cCreateProduct\u003e,\n) -\u003e Result\u003c(StatusCode, Json\u003cProduct\u003e), Error\u003e {\n    let item = service::create(\u0026state.db, \u0026input).await?;\n    Ok((StatusCode::CREATED, Json(item)))\n}\n```\n\n**`error.rs`** (typed, maps to HTTP)\n```rust\nimpl IntoResponse for Error {\n    fn into_response(self) -\u003e Response {\n        let (status, message) = match self {\n            Error::NotFound =\u003e (StatusCode::NOT_FOUND, \"not found\".to_string()),\n            Error::Database(e) =\u003e (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),\n        };\n        (status, message).into_response()\n    }\n}\n```\n\nNo macros hide any of this: it is exactly what you would write by hand\n([ADR-007](./ADR/adr-007-macros.md) explains why Gize prefers generated source over\nproc-macros).\n\n## The `gize.toml` manifest\n\nThe declarative source of truth for a project's shape ([ADR-009](./ADR/adr-009-configuration.md)).\nIt drives the (planned) `gize sync` and is updated automatically by `make app` / `make\ncrud`. It never holds secrets: those live in the environment.\n\n```toml\n[project]\nname = \"shop\"\n\n[stack]\nframework = \"axum\"\ndatabase  = \"postgres\"\norm       = \"sqlx\"\n\n[features]\nauthentication = false\nadmin          = false\nopenapi        = false\n\n[modules]\nlist = [\"orders\", \"products\"]\n```\n\n## Database and migrations\n\n- Migrations are **plain SQL** files in `migrations/`, named\n  `\u003cversion\u003e_create_\u003ctable\u003e.sql` ([ADR-011](./ADR/adr-011-migrations.md)).\n- `gize make model` / `gize make crud` derive a `CREATE TABLE` from the model's fields;\n  review and edit the SQL before applying.\n- `gize migrate` applies them via the SQLx migrator, which records applied versions in\n  `_sqlx_migrations` (ordered, idempotent). There is **no** risky runtime auto-migration.\n\n```sql\n-- migrations/…_create_products.sql\nCREATE TABLE products (\n    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n    name TEXT NOT NULL,\n    price INTEGER NOT NULL,\n    active BOOLEAN NOT NULL,\n    created_at TIMESTAMPTZ NOT NULL DEFAULT now(),\n    updated_at TIMESTAMPTZ NOT NULL DEFAULT now()\n);\n```\n\n\u003e `gen_random_uuid()` is built into PostgreSQL 13+. On older versions run\n\u003e `CREATE EXTENSION pgcrypto;` once.\n\n## Runtime configuration\n\nGenerated apps are 12-factor: runtime config comes from **environment variables**, not from\n`gize.toml`.\n\n| Variable | Default | Purpose |\n| --- | --- | --- |\n| `DATABASE_URL` | (required) | PostgreSQL connection string |\n| `PORT` | `8080` | HTTP listen port |\n\n`gize new` writes a `.env.example` you can copy to `.env` for local development.\n\n## The safety model\n\nGenerators never destroy your work ([ADR-012](./ADR/adr-012-cli.md)):\n\n- Existing files are **skipped** unless you pass `--force`.\n- `--dry-run` shows the full plan (`create` / `skip` / `update`) and writes nothing.\n- Registry edits to `app/mod.rs` and `gize.toml` are **idempotent**: re-running a\n  generator does not duplicate anything.\n\n```text\n$ gize make crud Product name:String price:i32 --dry-run\nGenerated CRUD for `Product`:\ndry-run: no files written\n  create  src/app/products/mod.rs\n  create  src/app/products/model.rs\n  …\n  update  src/app/mod.rs (would register module + routes)\n  update  gize.toml (would add module to [modules])\n```\n\n## Architecture\n\nGize is a Cargo workspace ([ADR-001](./ADR/adr-001-workspace.md)). The dependency direction\nflows toward a framework-agnostic core:\n\n```\ngize ──\u003e gize-generator ──\u003e gize-templates ──┐\n   │           │                              ├──\u003e gize-core\n   └──\u003e gize-db ┴──────────────────────────────┘\n```\n\n| Crate | Responsibility |\n| --- | --- |\n| `gize-core` | Domain model: manifest, field/model specs, naming. No framework deps. |\n| `gize-generator` | Codegen engine: pure `Plan`s, the safe `Writer`, idempotent registry edits. |\n| `gize-templates` | The templates for generated projects, modules, models, and CRUD. |\n| `gize-db` | Data-layer conventions + the SQLx migration runner. |\n| `gize-macros` | Procedural macros (intentionally tiny; see ADR-007). |\n| `gize` | The `gize` binary (clap). Orchestrates the above. |\n| `gize-admin`, `gize-auth`, `gize-openapi`, `gize-testing` | Planned feature crates (placeholders today). |\n\nDesign decisions live in [`ADR/`](./ADR). Guides live in [`docs/`](./docs):\n\n- [Getting started](./docs/getting-started.md) — empty directory to a running authenticated API.\n- [Architecture](./docs/architecture.md) — how Gize generates code, and the shape of what it emits.\n- [Cookbook](./docs/cookbook.md) — task-sized recipes (relationships, auth, OpenAPI, admin, …).\n- [FAQ](./docs/faq.md) — is it an ORM, does it lock me in, is the auth production-ready, …\n- [Migration guide](./MIGRATION.md) · [Stability policy](./STABILITY.md) · [Security](./SECURITY.md)\n- [Vision](./docs/vision.md) · [MVP](./docs/mvp.md) · [Roadmap](./docs/roadmap.md)\n\n## Examples\n\n- [`examples/gize-chat`](./examples/gize-chat) — a real-time group chat: `gize new --ws` plus a\n  `Message` resource, the built-in users/auth and an admin, on SQLite. It shows the Gize idea end\n  to end — everything is generated, and turning the WebSocket echo starter into a real broadcast\n  chat is a small, readable hand edit you own. Run it with `gize migrate \u0026\u0026 gize serve`, then open\n  \u003chttp://localhost:8080\u003e.\n- [`examples/gize-healthcheck`](./examples/gize-healthcheck) — a tiny external plugin\n  (`gize-\u003cname\u003e`) that generates a `/health` route ([ADR-008](./ADR/adr-008-plugins.md),\n  plugin API v0).\n\n## Developing Gize\n\n```bash\ncargo build --workspace\ncargo test --workspace\ncargo clippy --workspace --all-targets -- -D warnings\ncargo fmt --all\n```\n\nCI (`.github/workflows/ci.yml`) enforces fmt + clippy (`-D warnings`) + tests on every push\nand PR.\n\n## Roadmap\n\n- **MVP** (now): project + module + model + CRUD generators, migrations, serve.\n- **Alpha**: `gize sync`, auth scaffolding, relationships, validation, migration diffing.\n- **Beta**: admin UI (`gize make admin`), OpenAPI generation, a plugin API.\n- **RC → v1.0**: API/codegen stability, benchmarks, security review, complete docs.\n\nFull detail with acceptance criteria in [`docs/roadmap.md`](./docs/roadmap.md).\n\n## Comparison\n\n- **vs. Django / Rails / Laravel**: the same generator/convention productivity, but\n  compiled, type-safe, and with generated code you can read.\n- **vs. plain Axum**: Gize *uses* Axum; it adds the layout, scaffolding, and ecosystem\n  Axum leaves to you. You still ship plain Axum code.\n- **vs. Loco**: a different bet: transparent generated code over a heavy framework runtime,\n  and SQLx-first over an ORM.\n\nSee [`docs/vision.md`](./docs/vision.md) for the detailed comparison.\n\n## Contributing\n\nContributions are welcome. Because Gize is decision-driven, please open an ADR (or discuss\none) for anything architectural before implementing; see\n[ADR-000](./ADR/adr-000-process.md) for the process. Keep `cargo fmt`, `cargo clippy -D\nwarnings`, and `cargo test` green.\n\n## License\n\nLicensed under either of\n\n- Apache License, Version 2.0 ([LICENSE-APACHE](./LICENSE-APACHE))\n- MIT license ([LICENSE-MIT](./LICENSE-MIT))\n\nat your option. Unless you explicitly state otherwise, any contribution intentionally\nsubmitted for inclusion in the work by you shall be dual licensed as above, without any\nadditional terms or conditions.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobertolima-dev%2Fgize","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobertolima-dev%2Fgize","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobertolima-dev%2Fgize/lists"}