Skip to content
← Public packages

@kentcdodds/package-app-kit

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

FollowFork

starter-tanstack/app/ui/document.tsx

75 lines · 2.1 KB · TypeScript
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>
	)
}