Content Services & API
Call generated Content Engine services from custom Hono routes, use typed Zod schemas, and listen to content events.
When you compile a content type with createContentModel, it provides a typed service, Zod validation schemas, and database events that can be used directly inside custom Hono endpoints.
Quick start
Access the typed repository in any Hono route via model.service(c):
import { buildRoute } from "@vitnode/core/api/lib/route"
import { articleContent } from "@/database/articles"
export const featuredRoute = buildRoute({
pluginId: "blog",
route: {
method: "get",
path: "/featured",
responses: { 200: { description: "Featured articles" } },
},
handler: async (c) => {
const { edges, pageInfo } = await articleContent.service(c).findMany({
filters: { featured: true },
orderBy: { column: "createdAt", order: "desc" },
query: { first: "5" },
})
return c.json({ edges, pageInfo })
},
})findMany returns { edges, pageInfo } formatted for cursor-based pagination.
Service Methods Reference
The service returned by model.service(c) includes standard repository methods:
| Method | Parameters | Returns |
|---|---|---|
findMany | { query, filters?, orderBy? } | { edges: T[], pageInfo: PageInfo } |
findById | id: number | Promise<T | null> |
create | data: CreateInput | Promise<T> |
update | id: number, data: UpdateInput | Promise<T> |
delete | id: number | Promise<void> |
Generated Zod Schemas
Use generated validation schemas in custom routes:
import { articleContent } from "@/database/articles"
export const createArticleRoute = buildRoute({
pluginId: "blog",
route: {
method: "post",
path: "/",
request: {
body: {
content: {
"application/json": {
schema: articleContent.schemas.create,
},
},
},
},
},
handler: async (c) => {
const data = c.req.valid("json")
const article = await articleContent.service(c).create(data)
return c.json(article, 201)
},
})Content Engine Events
Content modifications automatically emit typed domain events on the event bus:
import { buildEventListener } from "@vitnode/core/api/lib/events"
export const onArticleCreated = buildEventListener({
event: "content.article.created",
name: "notify-subscribers",
handler: async (c, payload) => {
await c.get("queue").dispatch({
name: "broadcast-new-article",
payload: { articleId: payload.id },
})
},
})Standard events include content.{id}.created, content.{id}.updated, and content.{id}.deleted.
Learn More
Database & Migrations
How the Content Engine maps content models to PostgreSQL tables using createContentModel, handles system columns, and executes Drizzle Kit migrations.
Publication & Editorial
Add draft/published lifecycles, revision histories, signed preview links, and scheduled publishing to content types.