Skip to main content

Overview

The thepopebot/config export provides Next.js configuration helpers and server initialization hooks.

thepopebot/config

Next.js config wrapper with framework-specific settings.

Import

import { withThepopebot } from 'thepopebot/config';

Function

withThepopebot
function
Wraps user’s Next.js config with Pope Bot framework requirements
Usage in next.config.mjs:
import { withThepopebot } from 'thepopebot/config';

export default withThepopebot({
  // Your custom Next.js config
});

What It Does

  1. Enables instrumentation - Allows server startup hooks for cron scheduling
  2. Transpiles package - Ensures thepopebot package is bundled correctly
  3. Sets environment variables - Exposes feature flags to browser
  4. Configures SQLite - Marks database packages as server-external
  5. Custom build directory - Respects NEXT_BUILD_DIR env var
export function withThepopebot(nextConfig = {}) {
  return {
    ...nextConfig,
    distDir: process.env.NEXT_BUILD_DIR || '.next',
    transpilePackages: [
      'thepopebot',
      ...(nextConfig.transpilePackages || []),
    ],
    env: {
      ...nextConfig.env,
      NEXT_PUBLIC_CODE_WORKSPACE: process.env.CLAUDE_CODE_OAUTH_TOKEN && process.env.BETA ? 'true' : '',
      NEXT_PUBLIC_VOICE_ENABLED: process.env.ASSEMBLYAI_API_KEY ? 'true' : '',
    },
    serverExternalPackages: [
      ...(nextConfig.serverExternalPackages || []),
      'better-sqlite3',
      'drizzle-orm',
    ],
  };
}

Configuration Options

distDir
string
Build output directory (default: .next, override with NEXT_BUILD_DIR)
transpilePackages
array
Adds thepopebot to package transpilation list
env.NEXT_PUBLIC_CODE_WORKSPACE
string
Set to 'true' if code workspaces are enabled (requires CLAUDE_CODE_OAUTH_TOKEN + BETA)
env.NEXT_PUBLIC_VOICE_ENABLED
string
Set to 'true' if voice features are enabled (requires ASSEMBLYAI_API_KEY)
serverExternalPackages
array
Marks better-sqlite3 and drizzle-orm as external (prevents bundling issues)

thepopebot/instrumentation

Server startup hook for initializing cron jobs and database.

Import

import { register } from 'thepopebot/instrumentation';

Function

register
function
Called once when Next.js server starts. Initializes database, loads environment, starts cron scheduler.
Usage in instrumentation.js:
import { register } from 'thepopebot/instrumentation';
export { register };

What It Does

  1. Loads .env - Ensures environment variables are available
  2. Initializes database - Creates SQLite tables if needed
  3. Starts cron scheduler - Loads config/CRONS.json and schedules jobs
import 'dotenv/config';
import { initDatabase } from '../lib/db/index.js';
import { startCron } from '../lib/cron.js';

export async function register() {
  if (process.env.NEXT_RUNTIME === 'nodejs') {
    initDatabase();
    startCron();
  }
}

Runtime Guard

Only runs in Node.js runtime (skips Edge runtime):
if (process.env.NEXT_RUNTIME === 'nodejs') {
  // Server initialization
}

Environment Variables

The config module reads these variables:
NEXT_BUILD_DIR
string
Custom build output directory (default: .next)
CLAUDE_CODE_OAUTH_TOKEN
string
Enables code workspace feature when combined with BETA=true
BETA
string
Set to true to enable beta features (code workspaces)
ASSEMBLYAI_API_KEY
string
Enables voice features when present

Why Instrumentation?

Next.js 15+ supports instrumentation hooks for server startup. This is the cleanest way to:
  • Load cron jobs before handling requests
  • Initialize database schema atomically
  • Avoid race conditions from multiple workers

Cron Scheduling

The register() function calls startCron(), which:
  1. Reads config/CRONS.json
  2. Parses cron expressions via node-cron
  3. Schedules tasks (agent jobs, commands, webhooks)
  4. Runs continuously in background
See Cron Jobs for scheduling details.

Database Initialization

Calls initDatabase() from lib/db/index.js:
  1. Connects to SQLite (data/thepopebot.sqlite)
  2. Runs migrations from drizzle/ directory
  3. Creates tables if they don’t exist
  4. Returns database connection
Database path can be overridden with DATABASE_PATH env var.

Example Setup

next.config.mjs:
import { withThepopebot } from 'thepopebot/config';

export default withThepopebot({
  images: {
    domains: ['your-cdn.com'],
  },
});
instrumentation.js:
import { register } from 'thepopebot/instrumentation';
export { register };
File structure:
your-project/
├── next.config.mjs          # Uses withThepopebot()
├── instrumentation.js       # Exports register()
├── .env                     # Environment variables
└── config/
    └── CRONS.json           # Scheduled jobs

Build docs developers (and LLMs) love