For the complete documentation index, see llms.txt. Prefer markdown by appending .md to documentation URLs or sending Accept: text/markdown.

Integrate AI Kit

Port complete AI templates into Core Kit while keeping Core authentication, billing, API, database, and application structure intact.

Core Kit already includes a small authenticated streaming chat endpoint. AI Kit adds complete product slices: persisted chat, model selection, attachments, web search, image generation, RAG, text to speech, voice, and a credits example.

Treat the integration as a feature port, not a repository merge. Keep Core Kit as the owner of shared infrastructure, then bring over only the AI capabilities your product needs.

Do not merge the repositories wholesale

Both kits define apps/web, packages/api, packages/auth, packages/db, packages/i18n, packages/shared, packages/storage, and UI packages. Replacing those directories with their AI Kit versions removes Core features such as organizations, billing, admin, email, analytics, and monitoring.

The paths below assume both repositories are cloned next to each other:

Decide ownership

Use Core Kit as the source of truth for the application shell. AI Kit should contribute feature code behind those existing boundaries.

ConcernKeep from Core KitPort from AI Kit
AuthenticationBetter Auth config, account flows, organizations, hooksAI routes that consume c.var.user.id
Billing and accessPlans, subscriptions, feature accessCredit costs only if your product needs a separate credit balance
APIExisting Hono app, middleware, error handlingAI route files under packages/api/src/modules/ai
DatabaseExisting auth and billing schemaSelected AI schemas such as chat.ts, rag.ts, and image.ts
StorageExisting @workspace/storage package and credentialsAI upload paths and attachment logic
UI and i18nCore packages, theme, layouts, translationsFeature-specific components, routes, and strings

This ownership rule is the main protection against difficult future updates. A shared package has one owner; imported AI features adapt to it.

Choose a first vertical slice

Start with one template and make it work end to end before adding another.

TemplateAI packageDatabase schemaWeb surface
Chatpackages/ai/core, packages/ai/chatchat.ts, optional creditsmodules/chat, (apps)/chat
Imagepackages/ai/core, packages/ai/imageimage.ts, optional creditsmodules/image, (apps)/image
RAGpackages/ai/core, packages/ai/ragrag.ts, pgvectormodules/rag, (apps)/rag
Text to speechpackages/ai/core, packages/ai/ttsOptional credits onlymodules/tts, (apps)/tts
Voicepackages/ai/core, packages/ai/voiceOptional credits onlymodules/voice, (apps)/voice

Chat is the best first integration because it exercises authentication, streaming, persistence, storage, and provider configuration without native dependencies.

Copy the selected AI packages

Copy ../ai/packages/ai/core and the feature package you selected into packages/ai/. Keep their package names, such as @workspace/ai and @workspace/ai-chat, so the source imports continue to resolve.

mkdir -p packages/ai
cp -R ../ai/packages/ai/core packages/ai/core
cp -R ../ai/packages/ai/chat packages/ai/chat

Do not copy ../ai/pnpm-lock.yaml. Merge the required entries from AI Kit's pnpm-workspace.yaml into Core Kit's catalogs, then run pnpm install from Core Kit so pnpm resolves one version per dependency.

Copy dependencies from the selected package's package.json rather than installing every provider. For example, the chat package lists its model and web-search providers in ../ai/packages/ai/chat/package.json.

Merge the database schema

Copy only the schema files used by the selected template into packages/db/src/schema/. Do not replace Core Kit's auth.ts, billing.ts, or the existing migration history.

AI Kit groups template tables into PostgreSQL schemas such as chat, rag, and image. The files reference Core Kit's existing user table, so authenticated and anonymous Core users can own AI data without a second identity system.

Merge the exports into the existing index:

packages/db/src/schema/index.ts
export * from "./auth";
export * from "./billing";
export * from "./chat";

AI Kit's credit example defines a customer table in customer.ts. Core billing already defines its own customer, so do not copy that file unchanged. Choose one design:

  • Rename the AI table and exports to a dedicated ai_credit or credit-ledger model if credits are separate.
  • Replace deductCredits with plan or entitlement checks if AI usage belongs to a Core subscription.
  • Remove the credit middleware and UI if the feature is unlimited.

RAG also requires the PostgreSQL vector extension. Use a database image or hosted provider with pgvector, enable CREATE EXTENSION vector, and include that change in the migration review.

Generate a new migration from the combined schema:

pnpm with-env pnpm --filter @workspace/db db:generate
pnpm with-env pnpm --filter @workspace/db db:migrate

Review the generated SQL before applying it to an existing production database. It should add the selected AI tables and schemas, not recreate Core auth tables.

Replace the demo AI route with the selected routers

Core Kit already mounts aiRouter at /api/ai in packages/api/src/index.ts. AI Kit uses the same mount point, so preserve Core's Hono app and replace the small packages/api/src/modules/ai/router.ts implementation with the selected nested routers.

For chat, port:

../ai/packages/api/src/modules/ai/chat.ts
../ai/packages/api/src/modules/ai/router.ts

Then add the selected workspace packages to packages/api/package.json. Keep Core Kit's existing middleware.ts, and port only the AI-specific deductCredits logic if you kept credits. Core's enforceAuth already resolves the session and sets c.var.user.

Route collision

The Core example exposes POST /api/ai/chat. AI Kit chat exposes its persisted operations below /api/ai/chat/chats, plus model and sharing routes. Remove or rename the example route before registering the AI Kit router.

Keep provider SDKs and provider keys in the server-side AI packages. Browser components should only call the Hono API.

Port the web feature

Copy the selected route group and feature module from AI Kit:

../ai/apps/web/src/app/[locale]/(apps)/chat
../ai/apps/web/src/modules/chat

Chat also imports shared AI application components from ../ai/apps/web/src/modules/common. Copy the components reached by the feature's imports, but adapt them to Core's existing app layout, navigation, auth client, query provider, theme, and UI package. Do not replace Core's root layout.

Use Core's authenticated dashboard when the AI feature is part of the product. A typical destination is:

apps/web/src/app/[locale]/dashboard/(user)/chat
apps/web/src/modules/ai/chat

Moving the files is optional, but keeping AI product features under the dashboard makes Core authorization and navigation boundaries explicit.

Merge the selected app dependencies from ../ai/apps/web/package.json. In particular, persisted chat uses @ai-sdk/react on the client while provider SDKs remain dependencies of the server-side AI package.

Port the AI elements imported by the feature from ../ai/packages/ui/web/src/components/ai-elements and merge the ai translation namespace from ../ai/packages/i18n/src/translations. Add each new @workspace/ai* package to Core's INTERNAL_PACKAGES list in apps/web/next.config.ts so Next.js transpiles workspace source.

Voice also runs @workspace/ai-voice as a separate LiveKit worker. Copying its web screen does not deploy that worker.

Merge environment validation

Copy variable definitions, not .env files. Add only the providers and tools used by your selected feature to:

  1. apps/web/.env.example
  2. apps/web/env.config.ts
  3. The relevant package env.ts presets
  4. apps/web/turbo.json for variables required by build or dev tasks
  5. Your deployment environment

For a Gateway-backed chat, the minimal provider variable is:

apps/web/.env.local
AI_GATEWAY_API_KEY=""

Attachments also need the existing Core storage variables. Web search needs the key for the strategy you enable, such as TAVILY_API_KEY, BRAVE_SEARCH_API_KEY, EXA_API_KEY, or FIRECRAWL_API_KEY.

Do not expose provider keys with NEXT_PUBLIC_.

Verify the integrated slice

Run the checks from the Core repository:

pnpm install
pnpm lint
pnpm --filter web build

Then verify the behavior that crosses package boundaries:

  1. Sign in with a normal Core account and, if enabled, an anonymous account.
  2. Send a request and confirm the response streams.
  3. Reload and confirm persisted content still belongs to the same user.
  4. Try to request another user's chat directly and expect an authorization failure.
  5. Upload an attachment if the selected feature uses storage.
  6. Confirm rate limits and plan or credit checks fail before invoking a paid provider.

Production readiness

The template gives you the feature shape. Before charging users, tighten the boundaries that retries and long streams exercise:

  • Make usage or credit deductions idempotent with a generation or message ID.
  • Pass c.req.raw.signal into model calls so cancelled requests stop provider work.
  • Persist provider usage separately from product credits for reconciliation.
  • Add structured AI telemetry without recording prompts or sensitive attachments by default.
  • Use resumable streams backed by durable state if conversations must survive navigation, reconnects, or multiple server instances.
  • Rate-limit by authenticated user or organization, with an IP fallback for anonymous traffic.

Other client platforms

The server integration is shared. Once the web slice works, add only the client layer required by each platform:

How is this guide?

Last updated on

On this page

Ship your startup everywhere. In minutes.Try TurboStarter