Get Hedhog updates in your inbox
New releases, fresh recipes, and breaking changes — no spam.
Module Development
Modules are how you extend a HedHog project. Instead of hand-writing SQL, controllers,
DTOs, and permission tables, you describe a table in YAML and let the CLI generate the
migration, a full CRUD API, and the route/role permissions that guard it. This guide walks
that flow end to end by building a small catalog module with a product table.
By the end you will have:
- a new library scaffolded under
libraries/, - a
producttable defined in YAML and applied through a migration, - a working CRUD API with route-level permissions,
- and an admin page to manage records.
Development Flow
- Create the library.
- Define the table in YAML.
- Generate and apply the migration.
- Seed initial data (optional).
- Synchronize route and role permissions.
- Build the admin/frontend experience.
1. Create the library
Scaffold a new library with the CLI, then install so the workspace picks it up:
hedhog dev create-library --name catalog
pnpm install
This creates libraries/catalog/ with the standard hedhog/ directory (table/, data/,
query/, frontend/) and wires the package into the monorepo.
2. Define the table in YAML
A table lives in libraries/<library>/hedhog/table/<table>.yaml. The file name, in
snake_case, becomes the PostgreSQL table name — so product.yaml creates a product
table.
# libraries/catalog/hedhog/table/product.yaml
columns:
- type: pk
- name: name
- name: price
type: decimal
precision: 12
scale: 2
- type: created_at
- type: updated_at
What each line does:
| Line | Meaning |
|---|---|
type: pk | Serial id primary key. Always prefer this over isPrimaryKey. |
name: name | A "bare" column with no type is an implicit VARCHAR — a common repo convention. |
type: decimal + precision/scale | A DECIMAL(12, 2) money column. |
type: created_at / updated_at | TIMESTAMPTZ audit columns. updated_at also gets a trigger that refreshes it on every UPDATE. |
For every column type, alias, foreign key, and the auto-generated locale table, see the full Hedhog YAML reference.
3. Generate and apply the migration
When a library is added, the CLI runs this pipeline:
- Scan
libraries/<library>/hedhog/table/for schema definitions — one file per table. - Pair each table with its seed data in
hedhog/data/(matched by file name). - Generate a PostgreSQL migration (
CREATE TABLE, indexes, FK constraints,INSERTs) underapps/api/prisma/migrations/. - Apply the migration through Prisma.
hedhog add catalog
Monorepo policy: in a migration-first repository, never edit apps/api/prisma/schema.prisma by hand and never reset or recreate existing migrations. When a table/ or data/ YAML changes, add a new SQL migration under apps/api/prisma/migrations/ that mirrors the change, then apply it with pnpm prisma:deploy from apps/api.
4. Seed initial data (optional)
Seed rows go in libraries/<library>/hedhog/data/<table>.yaml, matched to the table by file
name. Each list entry is one row:
# libraries/catalog/hedhog/data/product.yaml
- name: Starter plan
price: 19.90
- name: Pro plan
price: 49.90
The id, created_at, and updated_at columns are filled automatically, so you only list
the business columns.
5. Synchronize route and role permissions
The CRUD endpoints are protected by route permissions. Two files keep them in sync — both
under libraries/<library>/hedhog/data/.
Declare the library admin role in role.yaml:
# libraries/catalog/hedhog/data/role.yaml
- slug: admin-catalog
name:
en: Catalog Administrator
pt: Administrador de Catálogo
description:
en: Administrator with full access to catalog management.
pt: Administrador com acesso total à gestão de catálogo.
Then map each endpoint to the roles that may call it in route.yaml. Always include the
global admin role plus the library-specific admin-catalog role:
# libraries/catalog/hedhog/data/route.yaml
- url: /product
method: GET
relations:
role:
- where:
slug: admin
- where:
slug: admin-catalog
- url: /product
method: POST
relations:
role:
- where:
slug: admin
- where:
slug: admin-catalog
Keep route.yaml and role.yaml in step with the API whenever an endpoint's URL, method, auth, or roles change — including when an endpoint is removed. See the CLI command reference for the tooling that helps automate this.
6. Build the admin experience
With the API and permissions in place, add the admin page that lists and edits records. A
standard list page uses a PageHeader, a KPI row, a flat search/filter toolbar with a table
or cards view, and a pagination footer — with a sheet-based form for create/edit. Reuse the
shared primitives (EntityPicker, useFormDraft, ResizableSheetContent, the KPI and
search components) rather than building local variants.
After you add or change admin pages and their message files, sync them back into the library:
hedhog dev assets-to-library catalog
Recommended checklist
- Keep architecture boundaries clear: business logic in
libraries/*, entrypoints inapps/*, shared utilities inpackages/*. - Reuse shared components before creating local variants.
- Keep
route.yaml/role.yamlsynchronized with the live endpoints. - Validate focused lint/build/tests for the areas you touched.
Next steps
- Hedhog YAML reference — every column type, relationship, and seed pattern.
- CLI command reference —
new,add,update, and thedevsub-commands. - Modules — explore the Core module and the Enterprise modules that ship with HedHog.