Skip to main content

Overview

chat.config.ts is the central configuration for ChatJS. It’s generated by the CLI (npx @chat-js/cli@latest create) from lib/config-schema.ts with sensible defaults and inline comments.

Access patterns

To access the config, import it from @/lib/config:
import { config } from "@/lib/config";

const { appName } = config;

Configuration Shape

The schema is defined in lib/config-schema.ts. Each field’s .describe() comment appears as an inline comment in the generated config.
export type PricingConfig = {
  currency?: string;
  free?: {
    name: string;
    summary: string;
  };
  pro?: {
    name: string;
    monthlyPrice: number;
    summary: string;
  };
};

export type AiConfig = {
  /** Active AI gateway */
  gateway: "vercel" | "openrouter" | "openai" | "openai-compatible";
  /** Provider sort order in model selector */
  providerOrder: string[];
  /** Models to hide from all users */
  disabledModels: AppModelId[];
  /** Default models enabled for new users */
  curatedDefaults: AppModelId[];
  /** Models available to anonymous users */
  anonymousModels: AppModelId[];
  /** Default model for shared app workflows */
  workflows: {
    chat: AppModelId;
    title: AppModelId;
    pdf: AppModelId;
    chatImageCompatible: AppModelId;
  };
  /** Tool-level enablement and model defaults */
  tools: {
    webSearch: { enabled: boolean };
    urlRetrieval: { enabled: boolean };
    codeExecution: { enabled: boolean };
    mcp: { enabled: boolean };
    followupSuggestions: { enabled: boolean; default: AppModelId };
    text: { polish: AppModelId };
    sheet: { format: AppModelId; analyze: AppModelId };
    code: { edits: AppModelId };
    image: { enabled: boolean; default: ImageModelId };
    video: { enabled: boolean; default: VideoModelId };
    deepResearch: {
      enabled: boolean;
      defaultModel: AppModelId;
      finalReportModel: AppModelId;
      allowClarification: boolean;
      maxResearcherIterations: number;
      maxConcurrentResearchUnits: number;
      maxSearchQueries: number;
    };
  };
};

export type AnonymousConfig = {
  /** Message credits for anonymous users */
  credits: number;
  /** Tools available to anonymous users */
  availableTools: string[];
  /** Rate limits */
  rateLimit: {
    requestsPerMinute: number;
    requestsPerMonth: number;
  };
};

export type AttachmentsConfig = {
  /** Max file size in bytes after compression */
  maxBytes: number;
  /** Max image dimension (width/height) */
  maxDimension: number;
  /** Accepted MIME types with their file extensions */
  acceptedTypes: {
    "image/png": string[];
    "image/jpeg": string[];
    "application/pdf": string[];
  };
};

export type Config = {
  /** AI runtime and model configuration */
  ai: AiConfig;
  appPrefix: string;
  appName: string;
  /** Browser tab title (defaults to appName) */
  appTitle?: string;
  appDescription: string;
  appUrl: string;

  organization: {
    name: string;
    contact: {
      privacyEmail: string;
      legalEmail: string;
    };
  };

  services: {
    hosting: string;
    aiProviders: string[];
    paymentProcessors: string[];
  };

  /**
   * Feature flags.
   * Set to true to enable - requires corresponding env vars.
   * Validated at build time via scripts/check-env.ts.
   */
  features: {
    /** File attachments (requires BLOB_READ_WRITE_TOKEN) */
    attachments: boolean;
  };

  pricing?: PricingConfig;

  legal: {
    minimumAge: number;
    governingLaw: string;
    refundPolicy: string;
  };

  policies: {
    privacy: {
      title: string;
      lastUpdated?: string;
    };
    terms: {
      title: string;
      lastUpdated?: string;
    };
  };

  /** Auth provider toggles — set to true to enable, requires corresponding env vars */
  authentication: {
    /** Google OAuth (requires AUTH_GOOGLE_ID + AUTH_GOOGLE_SECRET) */
    google: boolean;
    /** GitHub OAuth (requires AUTH_GITHUB_ID + AUTH_GITHUB_SECRET) */
    github: boolean;
    /** Vercel OAuth (requires VERCEL_APP_CLIENT_ID + VERCEL_APP_CLIENT_SECRET) */
    vercel: boolean;
  };

  /** Anonymous user configuration */
  anonymous: AnonymousConfig;
  /** File attachment configuration */
  attachments: AttachmentsConfig;
};

Gateway

The ai.gateway field determines which AI backend is used for model creation and model-list fetching. Validated at build time.
ValueBackendRequired Env Vars
"vercel" (default)Vercel AI GatewayAI_GATEWAY_API_KEY or VERCEL_OIDC_TOKEN
"openrouter"OpenRouterOPENROUTER_API_KEY
"openai"OpenAIOPENAI_API_KEY
"openai-compatible"OpenAI CompatibleOPENAI_COMPATIBLE_BASE_URL

Feature flags + env validation

Feature flags live under ai.tools, features, and authentication. They’re validated at build time by scripts/check-env.ts:
  • Runs as prebuild step before next build
  • Missing env vars will fail the build immediately

Tool flags (ai.tools)

  • ai.tools.codeExecution.enabled: requires VERCEL_OIDC_TOKEN (on Vercel) or VERCEL_TEAM_ID + VERCEL_PROJECT_ID + VERCEL_TOKEN (self-hosted)
  • ai.tools.webSearch.enabled: requires TAVILY_API_KEY or FIRECRAWL_API_KEY
  • ai.tools.urlRetrieval.enabled: requires FIRECRAWL_API_KEY - fetch structured content from URLs
  • ai.tools.mcp.enabled: requires MCP_ENCRYPTION_KEY
  • ai.tools.image.enabled: requires BLOB_READ_WRITE_TOKEN - AI-powered image generation tool
  • ai.tools.video.enabled: requires BLOB_READ_WRITE_TOKEN - AI-powered video generation tool
  • ai.tools.deepResearch.enabled: requires a configured search provider (TAVILY_API_KEY or FIRECRAWL_API_KEY)
  • ai.tools.followupSuggestions.enabled: no extra env var, uses configured language model

Features

  • features.attachments: requires BLOB_READ_WRITE_TOKEN - file uploads (images and PDFs)

Authentication

  • authentication.google: requires AUTH_GOOGLE_ID + AUTH_GOOGLE_SECRET
  • authentication.github: requires AUTH_GITHUB_ID + AUTH_GITHUB_SECRET
  • authentication.vercel: requires VERCEL_APP_CLIENT_ID + VERCEL_APP_CLIENT_SECRET

Notes on behavior

  • Anonymous limits: anonymous.credits and rate limits are typically higher in dev and lower in prod (see config.anonymous implementation).
  • Models: ai.workflows defines shared workflow defaults, ai.tools.*.default defines tool defaults, ai.disabledModels hard-hides models globally, and ai.anonymousModels constrains what anonymous users can pick.
  • Deep research tuning: runtime knobs live under ai.tools.deepResearch (allowClarification, maxResearcherIterations, maxConcurrentResearchUnits, maxSearchQueries).