Content Types
Every Forge content type is a plain Go struct that embeds forge.Node. The embed provides UUID identity, a URL slug, and the full content lifecycle. Forge derives routing, storage, validation, and MCP schema directly from the struct — no separate configuration required.
forge.Node
Every content type embeds forge.Node as a value — not a pointer:
type BlogPost struct {
forge.Node // always embed this
Title string `forge:"required,min=3"`
Body string `forge:"required"`
Tags []string
}
forge.Node fields:
| Field | Type | Description |
|---|---|---|
| ID | string | UUID v7 — immutable after creation |
| Slug | string | URL-safe identifier, auto-generated |
| Status | forge.Status | Draft, Published, Scheduled, Archived |
| PublishedAt | time.Time | Zero until first publish |
| ScheduledAt | *time.Time | Non-nil when Scheduled |
| CreatedAt | time.Time | Set on insert |
| UpdatedAt | time.Time | Set on every Save |
Validation tags
Title string `forge:"required,min=3,max=200"`
Body string `forge:"required,min=50"`
Slug string `forge:"slug"`
Email string `forge:"required,email"`
For business-rule validation beyond tags, implement Validate() error:
func (p *Post) Validate() error {
if p.Status == forge.Published && len(p.Tags) == 0 {
return forge.Err("tags", "required when publishing")
}
return nil
}
Interfaces
| Interface | Method | Purpose |
|---|---|---|
| Headable | Head() forge.Head | SEO, OG, sitemap, AI metadata |
| Markdownable | Markdown() string | text/markdown negotiation, llms-full.txt |
| AIDocSummary | AISummary() string | /llms.txt summary field |
| Validatable | Validate() error | Business-rule validation |
Storage
// SQLite / PostgreSQL
repo := forge.NewSQLRepo[*Post](db)
// In-memory (tests and prototypes)
repo := forge.NewMemoryRepo[*Post]()
Table names are auto-derived from the type name: Post → posts, DocPage → doc_pages. Override with forge.Table("custom_name").
Field format hints for AI agents
Use forge_format and forge_description struct tags to tell AI agents what a field expects. These hints appear directly in MCP tool descriptions at the point of authoring — so any MCP-compatible agent knows whether to write Markdown, raw HTML, or something else without having to guess from the field name.
type DocPage struct {
forge.Node
Title string `forge:"required,min=3"`
Body string `forge:"required" forge_format:"markdown" forge_description:"Write content in Markdown. Supports headings, lists, and code blocks."`
Embed string `forge_format:"html" forge_description:"Raw HTML only. Use for iframes and third-party embeds. Must be trusted content."`
}
Supported forge_format values:
| Value | Meaning |
|---|---|
markdown | CommonMark/GFM markdown — also covers plain text |
html | Trusted raw HTML — caller is responsible for sanitisation |
Fields without forge_format are unaffected. No validation is performed — the tags are hints only.