Skip to content
4th April 2025: This is a preview, whilst production-ready, it means some APIs might change

Documents

In RedwoodSDK, Document components give you complete control over the HTML structure of each route. Unlike many frameworks that use a fixed HTML document structure, Redwood lets you define custom documents per route, controlling everything from the doctype to scripts and hydration strategy.

A Basic Document

  1. Within our starter kits, you already have a Document component.

    src/app/Document.tsx
    export const Document: React.FC<{ children: React.ReactNode }> = ({
    children,
    }) => (
    <html lang="en">
    <head>
    <meta charSet="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>@redwoodjs/starter-standard</title>
    <link rel="modulepreload" href="/src/client.tsx" />
    </head>
    <body>
    <div id="root">{children}</div>
    <script>import("/src/client.tsx")</script>
    </body>
    </html>
    );
  2. Use the Document component in your routes:

    src/worker.tsx
    import { defineApp } from '@redwoodjs/sdk/worker'
    import { render, route } from '@redwoodjs/sdk/router'
    import { Document } from '@/app/Document.tsx'
    import { HomePage } from '@/app/pages/HomePage.tsx'
    export default defineApp([
    render(Document, [
    route('/', HomePage),
    ])
    ])

Multiple Document Types

One of the most powerful features of RedwoodSDK is the ability to use different Document components for different routes.

You can create a specialized Document component for a static document, a realtime document, or an application document.

Then, use different Documents for different routes:

src/worker.tsx
import { defineApp } from '@redwoodjs/sdk/worker'
import { render, route, prefix } from '@redwoodjs/sdk/router'
import { StaticDocument } from '@/app/StaticDocument.tsx'
import { ApplicationDocument } from '@/app/ApplicationDocument.tsx'
import { RealtimeDocument } from '@/app/RealtimeDocument.tsx'
4 collapsed lines
import { HomePage } from '@/app/pages/HomePage.tsx'
import { blogRoutes } from '@/app/routes/blog.tsx'
import { userRoutes } from '@/app/routes/user.tsx'
import { dashboardRoutes } from '@/app/routes/dashboard.tsx'
export default defineApp([
render(StaticDocument, [
route('/', HomePage),
prefix('/blog', blogRoutes),
]),
render(ApplicationDocument, [
prefix('/app/user', userRoutes),
]),
render(RealtimeDocument, [
prefix('/app/dashboard', dashboardRoutes),
])
])

Further Reading