Skip to content

Configuration

All configuration is passed to createCMS() as a single CMSConfig object.

typescript
import { createCMS } from '@viseed/core'

const cms = createCMS({
  db: { driver: 'postgres', url: process.env.DATABASE_URL! },
  admin: { ... },
  plugins: [],
  themes: [],
  server: { port: 3000 },
  media: { uploadDir: './uploads', maxFileSizeMb: 10 },
})

db (required)

Database connection settings.

typescript
db: {
  driver: 'postgres'  // Only PostgreSQL is supported
  url: string         // Full connection string
}

Example:

typescript
db: {
  driver: 'postgres',
  url: process.env.DATABASE_URL ?? 'postgresql://localhost:5432/hana',
}

Set DATABASE_URL as an environment variable rather than hardcoding it in source.


admin

Admin panel settings.

typescript
admin?: {
  path?: string              // URL path for the admin panel. Default: '/admin'
  enabled?: boolean          // Whether to mount the admin panel. Default: true
  bootstrapAdmin?: {
    email: string            // Email for the initial admin account
    password: string         // Password for the initial admin account
    name?: string            // Display name. Default: 'Administrator'
    siteId?: string          // Specific site to create the admin for (multi-site)
  }
}

bootstrapAdmin only creates the account if no admin user exists yet — safe to leave in production config.

Example:

typescript
admin: {
  bootstrapAdmin: {
    email: process.env.HANA_ADMIN_EMAIL ?? 'admin@local.dev',
    password: process.env.HANA_ADMIN_PASSWORD ?? '12345678',
    name: process.env.HANA_ADMIN_NAME ?? 'Administrator',
  },
},

plugins

Array of plugin instances to register at startup. Plugins can also be registered via cms.use() before cms.launch().

typescript
plugins?: CMSPlugin[]

Both approaches are equivalent:

typescript
// Option A — via config
const cms = createCMS({ ..., plugins: [authPlugin(), blogPlugin()] })

// Option B — via cms.use()
const cms = createCMS({ ... })
cms.use(authPlugin())
cms.use(blogPlugin())

See the Plugin System guide for details.


themes and defaultTheme

Register one or more themes. The active theme is stored in the database and can be changed via the admin panel.

typescript
themes?: CMSTheme[]          // All available themes
defaultTheme?: string        // Name of the theme to use when none is set in DB

Example:

typescript
import { blogTheme } from 'viseed-theme-blog'
import { insuranceTheme } from 'viseed-theme-insurance'

const cms = createCMS({
  ...,
  themes: [blogTheme(), insuranceTheme()],
  defaultTheme: 'blog',
})

theme (singular) is also accepted as shorthand when you only have one theme:

typescript
theme: blogTheme(),

See the Themes guide for details.


server

HTTP server settings.

typescript
server?: {
  port?: number       // Default: 3000
  hostname?: string   // Default: '0.0.0.0'
}

The PORT environment variable takes precedence over server.port when using the standard Bun.serve() pattern from the starter template.


media

Media upload settings.

typescript
media?: {
  uploadDir?: string      // Directory to store uploaded files. Default: './uploads'
  maxFileSizeMb?: number  // Maximum upload size in megabytes. Default: 10
}

Example:

typescript
media: {
  uploadDir: './uploads',
  maxFileSizeMb: 20,
},

See the Media guide for the full upload API.


Environment Variables

VariableUsed byDescription
DATABASE_URLdb.urlPostgreSQL connection string
PORTBun.serve()HTTP server port (default 3000)
HANA_ADMIN_EMAILbootstrapAdminInitial admin email
HANA_ADMIN_PASSWORDbootstrapAdminInitial admin password
HANA_ADMIN_NAMEbootstrapAdminInitial admin display name

Create a .env file at the project root for local development:

bash
DATABASE_URL=postgresql://postgres:admin@localhost:5432/hana
PORT=3000
HANA_ADMIN_EMAIL=admin@local.dev
HANA_ADMIN_PASSWORD=12345678