Special Files
NextFs can drive App Router special files from F# source modules, but the rules are not identical for every file.
Use this page as the file-convention map for:
error.jsglobal-error.jsloading.jsnot-found.jsglobal-not-found.jstemplate.jsdefault.jsforbidden.jsunauthorized.js
Convention Matrix
| Next.js file | F# pattern | Wrapper | Notes |
|---|---|---|---|
app/error.js | client component with ErrorBoundaryProps | required | file must start with 'use client' |
app/global-error.js | client component with ErrorBoundaryProps | required | must render its own <html> and <body> |
app/loading.js | plain default-export component | optional | Suspense fallback, no special props |
app/not-found.js | plain default-export component | optional | rendered by Navigation.notFound() |
app/global-not-found.js | plain default-export component, usually with metadata | optional | bypasses layouts entirely |
app/template.js | default-export component with TemplateProps | optional | remounts children on navigation |
app/default.js | default-export component with DefaultProps<'T> | optional | intended for parallel routes |
app/forbidden.js | plain default-export component | optional | requires experimental.authInterrupts |
app/unauthorized.js | plain default-export component | optional | requires experimental.authInterrupts |
Typed Helpers
NextFs includes a small helper surface for the special files that have non-trivial props:
ErrorBoundaryPropsErrorWithDigestTemplatePropsDefaultProps<'T>
Example error.js source:
module App.Error
open Fable.Core
open Feliz
open NextFs
[<ExportDefault>]
[<ReactComponent>]
let Error(props: ErrorBoundaryProps) =
Html.main [
prop.children [
Html.h1 "Segment error"
Html.p props.error.message
Html.button [
prop.type'.button
prop.onClick (fun _ -> props.``unstable_retry``())
prop.text "Retry"
]
]
]
error.js and global-error.js are Client Components in Next.js, so they still need generated wrappers with "use client".
Config Flags
Some special files require explicit Next.js config:
global-not-found.jsrequiresexperimental.globalNotFound: trueforbidden.jsandunauthorized.jsrequireexperimental.authInterrupts: true
Example:
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
authInterrupts: true,
globalNotFound: true,
},
}
export default nextConfig
These APIs are version-sensitive. authInterrupts, forbidden.js, and unauthorized.js are still documented by Next.js as experimental. Treat them as supported by current Next.js, but not frozen.
Important Differences
global-error.jscannot exportmetadataorgenerateMetadata; use HTML elements such as<title>inside the component when needed.global-error.jsmust render its own<html>and<body>.global-not-found.jsalso bypasses layouts, so it must bring its own fonts, styles, and document shell.default.jsis primarily for parallel-route recovery. Do not treat it as a generic fallback page.template.jsis different fromlayout.js: it remounts its children when the segment changes.
Wrapper Example
{
"entries": [
{
"directive": "use client",
"from": "./.fable/App.Error.js",
"to": "./app/error.js",
"default": true
},
{
"from": "./.fable/App.GlobalNotFound.js",
"to": "./app/global-not-found.js",
"default": true,
"named": ["metadata"]
}
]
}
For the exact generator rules, see Directives and wrappers. For a concrete layout of these files in a real project, see the starter example.