Home / Docs / Content Lifecycle

Content Lifecycle

Guides

Most frameworks leave content visibility to the application developer — a forgotten WHERE status = 'published' clause and draft content leaks to public endpoints, sitemaps, and search indexes. Forge makes the lifecycle a framework-level guarantee. You define the states; Forge enforces them everywhere, automatically.

The four states

forge.Draft      // not publicly visible
forge.Scheduled  // publishes automatically at ScheduledAt
forge.Published  // publicly visible
forge.Archived   // hidden, preserved in storage

The lifecycle is enforced by Forge at the framework level. You cannot opt out of it. This is intentional — it is what guarantees that draft content never leaks to public endpoints, sitemaps, feeds, or AI indexes.

What Forge enforces automatically

StatusPublic GETSitemapRSSAIDocllms.txt
Draft404404
Scheduled404404
Published
Archived404404

Non-published content returns 404 — not 403. Forge does not leak the existence of draft or scheduled content.

Scheduled publishing

Set Status to forge.Scheduled and provide a ScheduledAt time:

schedAt := time.Now().Add(24 * time.Hour)
post := &Post{
    Node: forge.Node{
        Slug:        "my-post",
        Status:      forge.Scheduled,
        ScheduledAt: &schedAt,
    },
    Title: "My Post",
}

Forge runs an internal ticker. No external cron job required. When ScheduledAt arrives, the item transitions to Published and the AfterPublish signal fires — triggering sitemap regeneration, feed regeneration, and any custom hooks you have registered.

Signals

React to lifecycle events with forge.On:

forge.On(forge.AfterPublish, func(ctx forge.Context, p *Post) error {
    log.Printf("published: %s", p.Slug)
    return nil
})

Available signals: BeforeCreate, AfterCreate, BeforeUpdate, AfterUpdate, AfterPublish, SitemapRegenerate.

Why lifecycle is first-class

Content systems that treat visibility as an application concern invite mistakes. A new route, a new feed, a new AI endpoint — each one requires the developer to remember to filter by status. One oversight and draft content is public.

Forge takes a different approach: the lifecycle is the framework's responsibility, not the application's. Every public endpoint, sitemap entry, RSS item, and MCP resource is filtered at the framework level. A content type that embeds forge.Node gets this guarantee for free — there is no way to accidentally expose a draft.

This is why Forge describes content lifecycle as a first-class concept rather than a convention.