Core Concepts · Reference

Field Types

The complete set of field types you can pass to grit generate resource --fields. Each one drives the Go struct field, the shared TypeScript type, the Zod schema, and the default admin form control and table column — from one declaration.

Field syntax

A field is name:type, with optional extra segments. Separate multiple fields with commas inside --fields.

Terminal
$grit generate resource Product --fields "name:string,price:float,category:belongs_to:Category,gallery:files:image"
  • Modifiersname:string:unique — append :unique, :required, or :optional. String fields default to required; everything else defaults to optional.
  • Slug sourceslug:slug:title — the 3rd segment is the field to slugify. Slugs are auto-unique and generated on save.
  • belongs_tocategory:belongs_to (model inferred → Category) or author:belongs_to:User (explicit). Creates a <name>_id UUID foreign-key column.
  • many_to_manytags:many_to_many:Tag — the related model is required. GORM builds the join table.
  • File acceptsimage:file:image, doc:file:all, or att:file:[pdf,doc,image,video]. Aliases: image, video, audio, pdf, doc, all — or a bracketed list.

Type mapping

How each field type resolves across the stack. Source of truth: internal/generate/field.go.

One field declarationResolves across the stackmaps toprice:float--fieldsGo struct fieldfloat64TypeScript typenumberZod rulez.number()Admin formnumber inputTable columnright-aligned
DeclarationGoTypeScriptAdmin UI
Declare a field once — Grit resolves it into Go, TypeScript, Zod, and the admin UI
TypeExampleGoTypeScriptZod
stringname:stringstringstringz.string()
textbio:textstringstringz.string()
richtextbody:richtextstringstringz.string()
intqty:intintnumberz.number().int()
uintstock:uintuintnumberz.number().int().nonnegative()
floatprice:floatfloat64numberz.number()
boolactive:boolboolbooleanz.boolean()
datetimepublished_at:datetime*time.Timestring | nullz.string().nullable()
datedue:date*time.Timestring | nullz.string().nullable()
slugslug:slug:titlestringstringz.string()
belongs_tocategory:belongs_tostring (FK)stringz.string().uuid()
many_to_manytags:many_to_many:Tag[]stringstring[]z.array(z.string().uuid())
string_arraysizes:string_arraydatatypes.JSONSlice[string]string[]z.array(z.string())
fileimage:file:image*files.FileRefFileRef | nullFileRefSchema.nullable()
filesgallery:files:imagefiles.FileRefsFileRef[]z.array(FileRefSchema)

Primary keys are always UUID string (never uint); a belongs_to FK column is a matching UUID string.

Default admin rendering

Each type also picks a default form control and DataTable column format in the generated admin resource. You can override either in the resource definition.

TypeForm controlTable format
stringText inputtext
textTextareatext
richtextRich-text editor (Tiptap)richtext
int / uint / floatNumber inputtext
boolSwitchboolean
datetime / dateDate / time pickerrelative
slugAuto-filled (read-only)text
belongs_toRelationship select (searchable)text (dotted key)
many_to_manyMulti-select
string_arrayTag / chips inputtext
fileDropzone (single)file
filesDropzone (multiple)files
Escape hatchThe generated types are a starting point. Edit the Go struct tags, tune the Zod rules in packages/shared/schemas, or override the form/table rendering in the admin resource definition — then run grit sync to keep TypeScript in step with Go. Grit generates opinions, not a cage.