Frank.JsonHome 7.3.3

dotnet add package Frank.JsonHome --version 7.3.3
                    
NuGet\Install-Package Frank.JsonHome -Version 7.3.3
                    
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="Frank.JsonHome" Version="7.3.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Frank.JsonHome" Version="7.3.3" />
                    
Directory.Packages.props
<PackageReference Include="Frank.JsonHome" />
                    
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 Frank.JsonHome --version 7.3.3
                    
#r "nuget: Frank.JsonHome, 7.3.3"
                    
#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 Frank.JsonHome@7.3.3
                    
#: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=Frank.JsonHome&version=7.3.3
                    
Install as a Cake Addin
#tool nuget:?package=Frank.JsonHome&version=7.3.3
                    
Install as a Cake Tool

Frank.JsonHome

NuGet Version

Serves a JSON Home document describing a Frank application's entry-point resources — a machine-readable directory a client can discover once and use to find everything else, instead of hardcoding URLs. It has no dependency on Frank.Auth or Frank.OpenApi, and adds no NuGet dependency of its own.

Installation

dotnet add package Frank.JsonHome

Declaring Discoverable Resources

Resources opt in with rel; anything without one is omitted, so the document stays a curated entry point rather than a sitemap of everything the app happens to serve:

open Frank.Builder
open Frank.JsonHome

let products =
    resource "/products" {
        rel "tag:example.com,2026:products"
        docs "https://example.com/docs/products"
        get listProducts
        post createProduct
    }

let productById =
    resource "/products/{id}" {
        rel "tag:example.com,2026:product"
        hrefVar "id" "https://example.com/param/product-id"
        get getProduct
        put updateProduct
    }

// Signals a resource is on its way out, or already gone
let legacyExport =
    resource "/legacy/export" {
        rel "tag:example.com,2026:legacy-export"
        deprecated
        get legacyExportHandler
    }

Application Wiring

[<EntryPoint>]
let main args =
    webHost args {
        useDefaults
        useJsonHome  // Serves /.well-known/home.json, advertises it via a Link header on every response

        resource products
        resource productById
        resource legacyExport
    }
    0

Configure the path, relation type, and api metadata with the overload that takes a function:

useJsonHome (fun options ->
    { options with
        Path = "/discovery.json"
        Rel = "discovery"
        Title = Some "Example API"
        Links = [ "author", "mailto:api-admin@example.com" ] })

Discovery Operations

Operation Description
rel "..." Link relation type keying this resource in the document — required for the resource to appear at all
hrefVar "name" "uri" Absolute URI identifying a route variable's semantics, for templated resources
docs "uri" Documentation link for this resource's relation type
deprecated Marks status: "deprecated"
gone Marks status: "gone"
acceptRanges [ "bytes" ] HTTP range-specifiers this resource accepts
acceptPrefer [ "return=minimal" ] RFC 7240 preferences this resource supports
preconditionRequired [ Precondition.ETag ] Preconditions required on state-changing requests
authScheme "Basic" [ "private" ] An HTTP authentication scheme this resource accepts, with its protection spaces

Authorization Filtering

If Frank.Auth is in use, guard a resource the same way you would anywhere else — Frank.JsonHome reads the stock IAuthorizeData/AuthorizationPolicy metadata Frank.Auth attaches, with no reference between the two packages:

let adminReports =
    resource "/admin/reports" {
        rel "tag:example.com,2026:admin-reports"
        requireRole "admin"  // Frank.Auth
        get getAdminReports
    }

An anonymous request's /.well-known/home.json omits tag:example.com,2026:admin-reports entirely; an authenticated admin's includes it. This also works with a plain ASP.NET Core [<Authorize>]-equivalent, without Frank.Auth at all.

Filtering is per HTTP method, not per whole resource — a handler-level requirement only hides the method it's on, not the resource:

let widgets =
    resource "/widgets" {
        rel "tag:example.com,2026:widgets"
        get listWidgets                                    // public
        delete (handler { requireRole "admin"; handle deleteWidget })
    }

An anonymous request's hints.allow for tag:example.com,2026:widgets shows ["GET"]; an authenticated admin's shows ["GET", "DELETE"]. A resource left with no visible methods for the current principal is omitted entirely, same as before. Whenever any resource is guarded, every response carries Cache-Control: private, no-cache and Vary: Authorization, so a shared cache can never serve one principal's document to another.

See sample/Frank.JsonHome.Sample for a runnable demonstration, including curl output for both cases.

Requires Frank. Optionally combines with Frank.Auth for authorization-filtered discovery.

See the project repository for the complete guide and sample applications.

License

MIT

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  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 is compatible.  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 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
7.3.3 91 8/11/2026
7.3.2 90 8/10/2026

### New in 7.3.3 (Released 2026-08-10)
**Frank.Rdf - Async IBufferWriter Streaming**
- **New: `Doc.writeJsonLdAsync doc bufferWriter`** — async overload that writes JSON-LD expanded-form directly to an `IBufferWriter<byte>` (e.g. `HttpResponse.BodyWriter`/`PipeWriter`), without intermediate string allocation or copying. Encodes UTF8 directly to the buffer for maximum efficiency in response streaming. Completes after serialization and flushing to the buffer.
- **Recommended for response streaming:** `writeJsonLdAsync` is the preferred method when serving JSON-LD from a Frank handler over HTTP. Streaming directly to `PipeWriter` avoids `AllowSynchronousIO` requirements and eliminates intermediate buffering layers that `StreamWriter` would introduce.
- **Three serialization options now available:** Use `writeJsonLdAsync` for HTTP responses (most efficient), `writeJsonLd` for flexibility with any `TextWriter`, and `toJsonLd` for testing/debugging.
- **Sample updated:** `sample/Frank.Rdf.Sample` demonstrates `Doc.writeJsonLdAsync` streaming the `application/ld+json` representation directly to the response body via `negotiate { }` content negotiation.
- **Test coverage:** comprehensive test cases for `writeJsonLdAsync` including single and multi-subject documents, language-tagged strings, and round-trip parsing.