Configuration

Notion CMS ships with sensible defaults but can be tailored via NotionCMSConfig and the type generation CLI. This guide explains how to customise file handling, debug logging, and generate database metadata.

Configuration overview

typescript
import { NotionCMS } from "@mikemajara/notion-cms"

const notion = new NotionCMS(process.env.NOTION_TOKEN!, {
  files: {
    strategy: "local",
    storage: {
      path: "./public/notion-files"
    }
  },
  debug: {
    enabled: true,
    level: "info"
  }
})

mergeConfig combines user input with default values:

  • files.strategy defaults to "direct"; other options are "local" and "remote".
  • files.storage contains shared fields (path, endpoint, credentials) used by the strategies.
  • debug toggles scoped logging (see debugging-and-troubleshooting.md).

File strategies

StrategyBehaviourWhen to use
direct (default)Returns Notion-hosted URLs untouched.Minimal setup, no caching needed.
localDownloads assets once, stores them using LocalStorage, serves stable public URLs.Static site exports, longer-lived URLs.
remoteUploads files to S3-compatible storage via S3Storage.CDN-backed delivery, multi-region setups.

Local strategy

  • Requires a writable storage.path (defaults to ./public/assets/notion-files).
  • Uses generateFileId() to keep filenames stable between runs.
  • Falls back to the original Notion URL if download fails.

Remote strategy

typescript
const notion = new NotionCMS(token, {
  files: {
    strategy: "remote",
    storage: {
      endpoint: process.env.S3_ENDPOINT!,
      bucket: "notion-cms",
      accessKey: process.env.S3_ACCESS_KEY!,
      secretKey: process.env.S3_SECRET_KEY!,
      region: "us-east-1",
      path: "uploads/notion/"
    }
  }
})
  • endpoint, accessKey, and secretKey are required.
  • bucket defaults to "default-bucket", but you should override it.
  • Optional path prefixes all stored keys (e.g., uploads/notion/page-id.png).
  • Errors are logged via debug.error; the original URL remains available.

Checking cache state

typescript
const cached = notion["databaseService"] // internal
console.log(notion instanceof Object) // placeholder to discourage direct access

Public API:

typescript
import { FileManager } from "@mikemajara/notion-cms"

// Via dependency injection in converters
const isCacheEnabled = fileManager.isCacheEnabled()

Debug logging

debug.configure is called in the NotionCMS constructor. Settings:

  • enabled: toggles logging entirely.
  • level: "error" | "warn" | "info" | "debug". Higher verbosity → more logs.

Logs include scoped helpers (debug.query, debug.log, debug.error) used across services.

Type generation CLI

Generating database metadata improves DX and runtime validation.

  1. Ensure the generator script is installed (comes with the package).
  2. Create a script in your app:
json
{
  "scripts": {
    "notion:generate": "ts-node packages/notion-cms/src/generator.ts"
  }
}
  1. Run the generator with required env vars (database IDs, output path). Each project typically maintains a notion-types-*.ts file checked into source control.
  2. Import the generated file early in your app (e.g., _app.tsx, entry server file) so registerDatabase runs before queries.

Generated files export types and call registerDatabase("databaseKey", { id, fields }). Fields are mapped to DatabaseFieldMetadata, powering autocomplete:

typescript
registerDatabase("blog", {
  id: "xxxxxxxx",
  fields: {
    Title: { type: "title" },
    Tags: { type: "multi_select", options: ["Docs", "Product"] },
    PublishedAt: { type: "date" }
  }
})

If you cannot run the generator (e.g., during prototyping), you can manually call registerDatabase with the same shape. Minimal metadata still unlocks QueryBuilder validation.

Last updated: