Data Fetching And Route Config
This page covers two parts of App Router work that are easy to lose when translating examples from TypeScript to F#:
- server
fetch()options - route segment config exports
Server Fetch
Next.js extends server fetch() with cache-aware options:
cachenext.revalidatenext.tags
NextFs exposes those through:
ServerFetch.fetchServerFetch.fetchWithInitServerFetch.fetchFromServerFetch.fetchFromWithInitServerFetchInitNextFetchOptionsServerFetchCacheRevalidate
Example:
let loadPosts() =
async {
let! response =
Async.AwaitPromise(
ServerFetch.fetchWithInit "https://example.com/api/posts" (
ServerFetchInit.create [
ServerFetchInit.cache ServerFetchCache.ForceCache
ServerFetchInit.next (
NextFetchOptions.create [
NextFetchOptions.revalidate (Revalidate.seconds 900)
NextFetchOptions.tags [ "posts"; "homepage" ]
]
)
]
)
)
return! Async.AwaitPromise(response.json<{| items: obj array |}>())
}
|> Async.StartAsPromise
Current semantics are based on the official fetch reference for Next.js 16.2.1:
cache: "force-cache"reads and populates the server-side cachecache: "no-store"opts the request out of persistencenext.revalidateacceptsfalse,0, or a number of secondsnext.tagsattaches cache tags used byrevalidateTag
Source: Next.js fetch API reference
Route Segment Config
For current App Router route segment exports, plain F# values are usually enough:
let runtime = RouteRuntime.Edge
let preferredRegion = PreferredRegion.home
let dynamicParams = true
let maxDuration = 30
Those values can be exported from:
layoutfilespagefilesroutehandlers
Current documented config surface in Next.js 16.2.1:
dynamicParamsruntimepreferredRegionmaxDuration
Source: Next.js route segment config reference
Route Handlers And Wrappers
If a route handler is wrapped through nextfs.entries.json, remember that the generated wrapper must re-export the config values too:
{
"from": "./.fable/App/Api/Posts.js",
"to": "./app/api/posts/route.js",
"named": ["GET", "POST", "runtime", "preferredRegion", "maxDuration"]
}
Without those names in the wrapper manifest, Next.js will only see the HTTP verb exports.
Multiple Sitemaps
generateSitemaps() returns an array of objects with an id property. NextFs provides a small helper for that shape:
let generateSitemaps() =
[|
GenerateSitemapsEntry.create [
GenerateSitemapsEntry.id 0
]
GenerateSitemapsEntry.create [
GenerateSitemapsEntry.id "archive"
]
|]
The corresponding sitemap file can read the promised id through SitemapProps:
let sitemap (props: SitemapProps) =
async {
let! sitemapId = Async.AwaitPromise props.id
return
[|
MetadataRoute.SitemapEntry.create [
MetadataRoute.SitemapEntry.url (sprintf "https://example.com/%s" sitemapId)
]
|]
}
|> Async.StartAsPromise
Source: Next.js generateSitemaps reference
Notes
SitemapProps.idis a promise ofstringin current Next.js 16 behavior.- Route handler
fetchrequests are not memoized as part of the React tree render pass. - Wrapper files remain a packaging layer only; they do not replace the underlying Next.js conventions.