Files
nextjs-notion-starter-kit/lib/config.ts

219 lines
6.3 KiB
TypeScript

/**
* Site-wide app configuration.
*
* This file pulls from the root "site.config.ts" as well as environment variables
* for optional depenencies.
*/
import { parsePageId } from 'notion-utils'
import { type PostHogConfig } from 'posthog-js'
import {
getEnv,
getRequiredSiteConfig,
getSiteConfig
} from './get-config-value'
import { type NavigationLink } from './site-config'
import {
type NavigationStyle,
type PageUrlOverridesInverseMap,
type PageUrlOverridesMap,
type Site
} from './types'
export const rootNotionPageId: string = parsePageId(
getSiteConfig('rootNotionPageId'),
{ uuid: false }
)!
if (!rootNotionPageId) {
throw new Error('Config error invalid "rootNotionPageId"')
}
// if you want to restrict pages to a single notion workspace (optional)
export const rootNotionSpaceId: string | null =
parsePageId(getSiteConfig('rootNotionSpaceId'), { uuid: true }) ?? null
export const pageUrlOverrides = cleanPageUrlMap(
getSiteConfig('pageUrlOverrides', {}) || {},
{ label: 'pageUrlOverrides' }
)
export const pageUrlAdditions = cleanPageUrlMap(
getSiteConfig('pageUrlAdditions', {}) || {},
{ label: 'pageUrlAdditions' }
)
export const inversePageUrlOverrides = invertPageUrlOverrides(pageUrlOverrides)
export const environment = process.env.NODE_ENV || 'development'
export const isDev = environment === 'development'
// general site config
export const name: string = getRequiredSiteConfig('name')
export const author: string = getRequiredSiteConfig('author')
export const domain: string = getRequiredSiteConfig('domain')
export const description: string = getSiteConfig('description', 'Notion Blog')
export const language: string = getSiteConfig('language', 'en')
// social accounts
export const twitter: string | undefined = getSiteConfig('twitter')
export const mastodon: string | undefined = getSiteConfig('mastodon')
export const github: string | undefined = getSiteConfig('github')
export const youtube: string | undefined = getSiteConfig('youtube')
export const linkedin: string | undefined = getSiteConfig('linkedin')
export const newsletter: string | undefined = getSiteConfig('newsletter')
export const zhihu: string | undefined = getSiteConfig('zhihu')
export const getMastodonHandle = (): string | undefined => {
if (!mastodon) {
return
}
// Since Mastodon is decentralized, handles include the instance domain name.
// e.g. @example@mastodon.social
const url = new URL(mastodon)
return `${url.pathname.slice(1)}@${url.hostname}`
}
// default notion values for site-wide consistency (optional; may be overridden on a per-page basis)
export const defaultPageIcon: string | undefined =
getSiteConfig('defaultPageIcon')
export const defaultPageCover: string | undefined =
getSiteConfig('defaultPageCover')
export const defaultPageCoverPosition: number = getSiteConfig(
'defaultPageCoverPosition',
0.5
)
// Optional whether or not to enable support for LQIP preview images
export const isPreviewImageSupportEnabled: boolean = getSiteConfig(
'isPreviewImageSupportEnabled',
false
)
// Optional whether or not to include the Notion ID in page URLs or just use slugs
export const includeNotionIdInUrls: boolean = getSiteConfig(
'includeNotionIdInUrls',
!!isDev
)
export const navigationStyle: NavigationStyle = getSiteConfig(
'navigationStyle',
'default'
)
export const navigationLinks: Array<NavigationLink | undefined> = getSiteConfig(
'navigationLinks',
null
)
// Optional site search
export const isSearchEnabled: boolean = getSiteConfig('isSearchEnabled', true)
// ----------------------------------------------------------------------------
// Optional redis instance for persisting preview images
export const isRedisEnabled: boolean = getSiteConfig('isRedisEnabled', false)
// (if you want to enable redis, only REDIS_HOST and REDIS_PASSWORD are required)
// we recommend that you store these in a local `.env` file
export const redisHost: string | undefined = getEnv('REDIS_HOST')
export const redisPassword: string | undefined = getEnv('REDIS_PASSWORD')
export const redisUser: string | undefined = getEnv('REDIS_USER', 'default')
export const redisUrl = getEnv(
'REDIS_URL',
`redis://${redisUser}:${redisPassword}@${redisHost}`
)
export const redisNamespace: string | undefined = getEnv(
'REDIS_NAMESPACE',
'preview-images'
)
// ----------------------------------------------------------------------------
export const isServer = typeof window === 'undefined'
export const port = getEnv('PORT', '3000')
export const host = isDev ? `http://localhost:${port}` : `https://${domain}`
export const apiHost = isDev
? host
: `https://${process.env.VERCEL_URL || domain}`
export const apiBaseUrl = `/api`
export const api = {
searchNotion: `${apiBaseUrl}/search-notion`,
getNotionPageInfo: `${apiBaseUrl}/notion-page-info`,
getSocialImage: `${apiBaseUrl}/social-image`
}
// ----------------------------------------------------------------------------
export const site: Site = {
domain,
name,
rootNotionPageId,
rootNotionSpaceId,
description
}
export const fathomId = isDev ? undefined : process.env.NEXT_PUBLIC_FATHOM_ID
export const fathomConfig = fathomId
? {
excludedDomains: ['localhost', 'localhost:3000']
}
: undefined
export const posthogId = process.env.NEXT_PUBLIC_POSTHOG_ID
export const posthogConfig: Partial<PostHogConfig> = {
api_host: 'https://app.posthog.com'
}
function cleanPageUrlMap(
pageUrlMap: PageUrlOverridesMap,
{
label
}: {
label: string
}
): PageUrlOverridesMap {
return Object.keys(pageUrlMap).reduce((acc, uri) => {
const pageId = pageUrlMap[uri]
const uuid = parsePageId(pageId, { uuid: false })
if (!uuid) {
throw new Error(`Invalid ${label} page id "${pageId}"`)
}
if (!uri) {
throw new Error(`Missing ${label} value for page "${pageId}"`)
}
if (!uri.startsWith('/')) {
throw new Error(
`Invalid ${label} value for page "${pageId}": value "${uri}" should be a relative URI that starts with "/"`
)
}
const path = uri.slice(1)
return {
...acc,
[path]: uuid
}
}, {})
}
function invertPageUrlOverrides(
pageUrlOverrides: PageUrlOverridesMap
): PageUrlOverridesInverseMap {
return Object.keys(pageUrlOverrides).reduce((acc, uri) => {
const pageId = pageUrlOverrides[uri]!
return {
...acc,
[pageId]: uri
}
}, {})
}