Skip to main content

Custom Document Component

If you have a custom <html> document component, or want to inject your own providers in the render lifecyle, you can pass your component to the RequestRouter:

worker/components/AppHTMLDocument.tsx
import { KeyworkHTMLDocumentAppRoot } from 'keywork/react'
import React from 'react'

export interface AppHTMLDocumentProps {
children: React.ReactNode
}

export const AppHTMLDocument: React.FC<AppHTMLDocumentProps> = ({ children }) => {
return (
<html>
<head>
<title>My Keywork App</title>
<link href="/static/main.css" rel="stylesheet" />
</head>
<body>
<div id={KeyworkHTMLDocumentAppRoot}>{children}</div>
<script src="/static/main.js"></script>
</body>
</html>
)
}
worker/routers/app.tsx
import { AppHTMLDocument } from '@local/worker/components/Document'
import { RequestRouter } from 'keywork/router'

export const app = new RequestRouter({
displayName: 'My App',
DocumentComponent: AppHTMLDocument,
})

all.get('/', async ({ request }) => {
return <div>Hello world!</div>
})

Example: Using React with URL params

worker/routers/users.ts
export const usersRouter = new RequestRouter({
displayName: 'Users Router',
DocumentComponent: AppHTMLDocument,
session: true,
})

interface GetUserParams {
username: string
}

// Declaring a route that returns a React element...
users.get<GetUserParams>('/profile/:username', async ({ session, params }) => {
const user = database.fetchBy({ username })
let isFriends: boolean

if (!user) {
return new KeyworkResourceError(`${username} not found`, 404)
}

if (session) {
const currentUser = database.fetchBy({ sessionID: session.sessionID })
isFriends = currentUser && user.friendsList.includes(currentUser.id)
}

return <UserProfile user={user} isFriends={isFriends} />
})