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.strategydefaults to"direct"; other options are"local"and"remote".files.storagecontains shared fields (path, endpoint, credentials) used by the strategies.debugtoggles scoped logging (seedebugging-and-troubleshooting.md).
File strategies
| Strategy | Behaviour | When to use |
|---|---|---|
direct (default) | Returns Notion-hosted URLs untouched. | Minimal setup, no caching needed. |
local | Downloads assets once, stores them using LocalStorage, serves stable public URLs. | Static site exports, longer-lived URLs. |
remote | Uploads 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, andsecretKeyare required.bucketdefaults to"default-bucket", but you should override it.- Optional
pathprefixes 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.
- Ensure the generator script is installed (comes with the package).
- Create a script in your app:
json
{
"scripts": {
"notion:generate": "ts-node packages/notion-cms/src/generator.ts"
}
}
- Run the generator with required env vars (database IDs, output path). Each project typically maintains a
notion-types-*.tsfile checked into source control. - Import the generated file early in your app (e.g.,
_app.tsx, entry server file) soregisterDatabaseruns 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: