Content Engine

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):

plugins/blog/src/api/modules/articles/routes/featured.route.ts
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:

MethodParametersReturns
findMany{ query, filters?, orderBy? }{ edges: T[], pageInfo: PageInfo }
findByIdid: numberPromise<T | null>
createdata: CreateInputPromise<T>
updateid: number, data: UpdateInputPromise<T>
deleteid: numberPromise<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:

plugins/blog/src/api/lib/listeners.ts
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