NextFs 0.1.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package NextFs --version 0.1.0
                    
NuGet\Install-Package NextFs -Version 0.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="NextFs" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="NextFs" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="NextFs" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add NextFs --version 0.1.0
                    
#r "nuget: NextFs, 0.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package NextFs@0.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=NextFs&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=NextFs&version=0.1.0
                    
Install as a Cake Tool

NextFs

CI NuGet Publish License: MIT

NextFs is a Fable-first binding layer for building Next.js applications with F#.

Status: experimental, but already usable as a bootstrap layer for App Router projects.

What It Covers

  • Next.js components: next/link, next/image, next/script, next/form, next/head
  • App Router hooks and helpers from next/navigation
  • Async server request APIs from next/headers and next/server
  • NextRequest / NextResponse baseline for route handlers
  • Inline Directive.useServer() support for F# server actions
  • Wrapper generation for file-level 'use client' / 'use server' entry files

The current package is aimed at Next.js 15/16 style App Router usage, including async headers() and cookies().

Repository Layout

  • src/NextFs contains the bindings package
  • samples/NextFs.Smoke contains a compile-smoke consumer project
  • tools/nextfs-entry.mjs generates thin Next.js wrapper files with file-level directives
  • samples/nextfs.entries.json shows the wrapper manifest format

Install

dotnet add package NextFs

Runtime dependencies are expected to come from the consuming Next.js app:

  • next
  • react
  • react-dom

Example

module App.Page

open Fable.Core
open Feliz
open NextFs

[<ReactComponent>]
let NavLink() =
    Link.create [
        Link.href "/dashboard"
        prop.className "nav-link"
        prop.text "Dashboard"
    ]

[<ExportDefault>]
let Page() =
    Html.main [
        prop.children [
            Html.h1 "Hello from Fable + Next.js"
            NavLink()
        ]
    ]

Typed object href values can be built with Href.create:

open Fable.Core.JsInterop

Link.create [
    Link.hrefObject (
        Href.create [
            Href.pathname "/search"
            Href.query (createObj [ "q" ==> "fable" ])
        ]
    )
    prop.text "Search"
]

Server-side request data is exposed as async APIs:

module App.ServerPage

open Fable.Core
open Feliz
open NextFs

[<ExportDefault>]
let Page() =
    async {
        let! headers = Async.AwaitPromise(Server.headers())
        let userAgent = headers.get("user-agent") |> Option.defaultValue "unknown"

        return
            Html.pre [
                prop.text userAgent
            ]
    }
    |> Async.StartAsPromise

Route handlers can use NextRequest, async route params, and NextResponse:

module App.Api.Posts

open Fable.Core
open Fable.Core.JsInterop
open NextFs

[<CompiledName("GET")>]
let get (request: NextRequest, ctx: RouteHandlerContext<{| slug: string |}>) =
    async {
        let! routeParams = Async.AwaitPromise ctx.``params``

        return
            ServerResponse.jsonWithInit
                (createObj [
                    "slug" ==> routeParams.slug
                    "pathname" ==> request.nextUrl.pathname
                ])
                (ResponseInit.create [
                    ResponseInit.status 200
                ])
    }
    |> Async.StartAsPromise

Inline server actions can emit 'use server' from F#:

let saveSearch (formData: obj) =
    Directive.useServer()
    ()

File Directives

Next.js requires 'use client' and 'use server' to appear at the top of the generated JavaScript file.

Directive.useServer() covers the inline function-level case. File-level directives are different: Fable-generated ESM imports appear before emitted statements, so client/server entry modules still need a thin wrapper file.

The repository includes a wrapper generator:

node tools/nextfs-entry.mjs samples/nextfs.entries.json

Example config:

{
  "entries": [
    {
      "directive": "use client",
      "from": "./.fable/App.Page.js",
      "to": "./app/page.js",
      "default": true
    },
    {
      "directive": "use server",
      "from": "./.fable/App.Actions.js",
      "to": "./app/actions.js",
      "named": ["createPost", "deletePost"]
    },
    {
      "from": "./.fable/App.Api.Posts.js",
      "to": "./app/api/posts/route.js",
      "named": ["GET", "POST"]
    }
  ]
}

For 'use server' wrapper entries, only named exports are allowed. This matches Next.js expectations and avoids invalid export shapes.

Interop Notes

  • Route handlers should be exported with JavaScript-shaped signatures: let get (request, ctx) = ...
  • Multi-argument server actions should also be uncurried: let update (prevState, formData) = ...
  • Use [<CompiledName("GET")>], [<CompiledName("POST")>], and similar attributes for route handler exports

Local Validation

dotnet build NextFs.slnx -v minimal
dotnet pack src/NextFs/NextFs.fsproj -c Release -o artifacts
node tools/nextfs-entry.mjs samples/nextfs.entries.json

NuGet Publishing

The repository includes publish-nuget.yml, which publishes NextFs to nuget.org on:

  • manual workflow_dispatch
  • git tag pushes matching v*

It is configured for NuGet Trusted Publishing via GitHub OIDC, not a long-lived API key.

Before the first publish, create a trusted publishing policy on nuget.org with:

  • Repository Owner: Neftedollar
  • Repository: Next.fs
  • Workflow File: publish-nuget.yml
  • Environment: release

Roadmap

  • automate wrapper generation in the consumer workflow
  • expand next/server coverage beyond the current NextResponse baseline
  • add stronger typing for metadata, route config, and server action conventions

Contributing

Contribution workflow and commit conventions are documented in CONTRIBUTING.md.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on NextFs:

Package Downloads
NextFs.Dsl

High-level F# DSL for NextFs — computation expressions and async helpers for Next.js App Router.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 164 3/26/2026
0.9.0 109 3/21/2026
0.8.0 110 3/21/2026
0.7.0 109 3/21/2026
0.6.0 102 3/21/2026
0.5.0 106 3/21/2026
0.4.0 105 3/21/2026
0.3.0 102 3/21/2026
0.2.0 107 3/21/2026
0.1.0 107 3/21/2026