← Public packages
@kentcdodds/package-app-kit
Design tokens, PWA install/update, About/version, cache helpers, and optional realtime notes sync for Kody package apps.
import type { ReactNode } from 'react'
import { createRoutes } from '../routes.ts'
export type DocumentProps = {
title: string
appBasePath: string
assetBasePath: string
clientModuleUrl: string | null
runningSha?: string
page?: string
children?: ReactNode
}
export function Document({
title,
appBasePath,
assetBasePath,
clientModuleUrl,
runningSha,
page,
children,
}: DocumentProps) {
const appBase = appBasePath.replace(/\/$/, '')
const assetBase = assetBasePath.replace(/\/$/, '')
const routes = createRoutes(appBase)
const icon192 = `${routes.icon192.href()}?v=4`
const manifest = routes.manifest.href()
const swUrl = assetBase ? `${assetBase}/sw.js` : `${appBase}/sw.js`
const pakConfig = JSON.stringify({
appName: '__APP_TITLE__',
appLabel: '__APP_TITLE__',
hintDismissKey: '__PACKAGE_ID__-install-hint-dismissed',
versionPath: '/api/version',
appBase,
assetBase: assetBase || undefined,
clientModuleUrl: clientModuleUrl || undefined,
swUrl,
})
return (
<html
lang="en"
data-app-base={appBase}
data-asset-base={assetBase || undefined}
data-client-module={clientModuleUrl || undefined}
data-sw-url={swUrl}
data-running-sha={runningSha || ''}
data-page={page || ''}
data-app-name="__APP_TITLE__"
data-pak-config={pakConfig}
>
<head>
<meta charSet="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, viewport-fit=cover"
/>
<meta name="color-scheme" content="dark" />
<meta name="theme-color" content="#0a0a0a" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="mobile-web-app-capable" content="yes" />
<title>{title}</title>
<link rel="manifest" href={manifest} crossOrigin="use-credentials" />
<link rel="icon" type="image/png" sizes="192x192" href={icon192} />
<link rel="apple-touch-icon" href={icon192} />
<link rel="stylesheet" href={`${assetBase}/styles.css`} />
</head>
<body>
{children}
<div className="pak-toast-host" data-toast-host aria-live="polite" />
{clientModuleUrl ? <script type="module" src={clientModuleUrl} /> : null}
</body>
</html>
)
}