Skip to content

Kody is live

Watch the launch video — what Kody is, and why it exists.

← Public packages

@kentcdodds/package-app-kit

Design tokens, PWA install/update, About/version, cache helpers, and optional realtime notes sync for Kody package apps.

app/ui/document.tsx

69 lines · 2.4 KB · TypeScript
/** @jsxRuntime automatic */
/** @jsxImportSource remix/ui */
import type { Handle, RemixNode } from 'remix/ui'

export type DocumentProps = {
	title: string
	appBasePath: string
	assetBasePath: string
	clientModuleUrl: string | null
	runningSha?: string
	page?: string
	children?: RemixNode
}

export function Document(handle: Handle<DocumentProps>) {
	return () => {
		const appBase = handle.props.appBasePath.replace(/\/$/, '')
		const assetBase = handle.props.assetBasePath.replace(/\/$/, '')
		const icon192 = `${appBase}/icons/icon-192.png?v=6`
		const manifest = `${appBase}/manifest.webmanifest`
		const swUrl = assetBase ? `${assetBase}/sw.js` : `${appBase}/sw.js`
		const pakConfig = JSON.stringify({
			appName: 'Package App Kit',
			appLabel: 'App Kit',
			hintDismissKey: 'package-app-kit-demo-install-hint-dismissed',
			versionPath: '/api/version',
			appBase,
			assetBase: assetBase || undefined,
			clientModuleUrl: handle.props.clientModuleUrl || undefined,
			swUrl,
		})

		return (
			<html
				lang="en"
				data-app-base={appBase}
				data-asset-base={assetBase || undefined}
				data-client-module={handle.props.clientModuleUrl || undefined}
				data-sw-url={swUrl}
				data-running-sha={handle.props.runningSha || ''}
				data-page={handle.props.page || ''}
				data-app-name="Package App Kit"
				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="light dark" />
					<meta name="theme-color" media="(prefers-color-scheme: light)" content="#fafafa" />
					<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#0a0a0a" />
					<meta name="apple-mobile-web-app-capable" content="yes" />
					<meta name="mobile-web-app-capable" content="yes" />
					<title>{handle.props.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>
					{handle.props.children}
					<div class="pak-toast-host" data-toast-host aria-live="polite" />
					{handle.props.clientModuleUrl ? (
						<script type="module" src={handle.props.clientModuleUrl}></script>
					) : null}
				</body>
			</html>
		)
	}
}