Feliz.ViewEngine 1.0.3

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

Feliz.ViewEngine

Build and Test NuGet

Scalable HTML/XML rendering for F# - render the Feliz DSL to strings

Feliz.ViewEngine lets you render Feliz DSL to plain HTML (or XML). Use with e.g Giraffe for handling Server Side Rendering (SSR), returning HTML or XML. You can use it for e.g generating HTML emails or any other use-case where you need to generate HTML output.

Feliz.ViewEngine have no dependencies, is Fable compatible, and can thus be used with both servers (e.g Node.js) or clients.

Installation

Feliz.ViewEngine is available as a NuGet package. To install:

Using Package Manager:

Install-Package Feliz.ViewEngine

Using .NET CLI:

dotnet add package Feliz.ViewEngine

Development

This project uses just as a command runner. Install it and run just to see available commands:

just          # List available commands
just restore  # Restore dependencies
just build    # Build all projects
just test     # Run tests
just check    # Build and run tests
just bench    # Run benchmarks

Contributing

This project uses Conventional Commits. Please format your PR titles and commit messages accordingly:

  • feat: add new feature - for new features
  • fix: resolve bug - for bug fixes
  • perf: improve performance - for performance improvements
  • docs: update readme - for documentation
  • chore: update dependencies - for maintenance tasks

Releases are automated via release-please.

Getting started

open Feliz.ViewEngine

let html =
    Html.h1 [
        prop.style [ style.fontSize(100); style.color("#137373") ]
        prop.text "Hello, world!"
    ]
    |> Render.htmlView

printfn "Output: %s" html
// Will output "<h1 style=\"font-size:100px;color:#137373\">Hello, world!</h1>"

Giraffe example at https://github.com/dbrattli/Feliz.ViewEngine/blob/master/examples/giraffe/Program.fs

Sharing views between client and server

Feliz.ViewEngine re-implements Feliz DSL for server-side so you will need to choose Feliz for client side rendering and Feliz.ViewEngine for server side rendering:

#if FABLE_COMPILER
open Feliz
#else
open Feliz.ViewEngine
#endif

let view = ...

Documentation

The following API is available for converting a ReactElement view into a string that you can return from e.g a Giraffe HTTP handler.

type Render
  /// Create HTML document view with <!DOCTYPE html>
  static member htmlDocument: document: ReactElement -> string
  /// Create HTML view
  static member htmlView: node: ReactElement -> string (+ 1 overloads)
  /// Create XML document view with <?xml version="1.0" encoding="utf-8"?>
  static member xmlDocument: document: ReactElement -> string
  /// Create XML view
  static member xmlView: node: ReactElement -> string (+ 1 overloads)

Feliz has extensive documentation at https://zaid-ajaj.github.io/Feliz with live examples along side code samples, check them out and if you have any question, let us know!

Extensions

Common Pitfalls

Feliz.ViewEngine (ReactElement) is not compatible with GiraffeViewEngine (XmlNode) so you cannot mix the two as you can with Feliz and Fable.React. Thus when you convert your existing server side rendering code, then all the elements must be converted to Feliz.

Projects and Examples

Projects and examples using Feliz.ViewEngine:

  • Felizia - Uses Feliz.ViewEngine server-side for SSR and Feliz client-side
  • Giraffe server - simple example

Porting an Existing Feliz Library to Feliz.ViewEngine

To port an existing Feliz library to Feliz.ViewEngine you basically need to reimplement everything from the library you want to port. However this is usually not a lot of work since you can reuse most of the files from the existing library, and you can do the work incrementally and add support for more elements and properties as needed.

Start with the file that generates the HTML elements, comment out the whole file using (* ... *) and start enabling element by element. Then port properties, styles, colors, etc.

The Feliz.ViewEngine types are different from ReactElement:

type IReactProperty =
    | KeyValue of string * obj
    | Children of ReactElement list
    | Text of string

and ReactElement =
    | Element of string * IReactProperty list
    | VoidElement of string * IReactProperty list
    | TextElement of string

However you usually don't have to care about the difference since the Interop interface is very similar:

module Interop =
    /// Output a string where the content has been HTML encoded.
    val mkText: content : 'a -> IReactProperty
    val mkChildren: props: #seq<ReactElement> -> IReactProperty
    val reactElementWithChildren: name: string -> children: #seq<ReactElement> -> ReactElement
    val reactElementWithChild: name: string -> child: 'a -> ReactElement
    val createElement: name: string -> props: IReactProperty list -> ReactElement
    val createVoidElement: name: string -> props: IReactProperty list -> ReactElement
    val createTextElement: content : string -> ReactElement
    val createRawTextElement: content : string -> ReactElement
    let mkAttr: key: string -> value: obj -> IReactProperty
    val mkStyle: key: string -> value: obj -> IStyleAttribute

Using the Interop module, many elements is exactly the same for Feliz and Feliz.ViewEngine. E.g Feliz code such as:

module Html =
    static member inline div xs = Interop.createElement "div" xs

For Feliz.ViewEngine it will be exactly the same:

module Html =
    static member inline div xs = Interop.createElement "div" xs

However other elements may require some work. E.g all elements that use unboxing such as:

    static member inline none : ReactElement = unbox null
    static member inline text (value: int) : ReactElement = unbox value

For Feliz.ViewEngine this needs to be rewritten as:

    static member inline none : ReactElement = Interop.createTextElement ""
    static member inline text (value: int) : ReactElement = Interop.createTextElement (value.ToString ())

Properties may also require some work, e.g:

[<Erase>]
type prop =
    static member inline dangerouslySetInnerHTML (content: string) = Interop.mkAttr "dangerouslySetInnerHTML" (createObj [ "__html" ==> content ])

For Feliz.ViewEngine this needs to be rewritten as:

type prop =
    static member inline dangerouslySetInnerHTML (content: string) = Interop.mkChildren [ Interop.createRawTextElement content ]

As you go along, always remember that Feliz.ViewEngine and SSR is about generating HTML that will become text. You just need to make sure that the elements and properties you add generate the expected text output when rendered. Thus you can add unit-tests to check the output is as expected by calling Render.htmlView:

[<Fact>]
let ``h1 element with text and style property with css unit is Ok``() =
    // Arrange / Act
    let result =
        Html.h1 [
            prop.style [ style.fontSize(length.em(100)) ]
            prop.text "examples"
        ]
        |> Render.htmlView

    // Assert
    test <@ result = "<h1 style=\"font-size:100em\">examples</h1>" @>

License

This work is dual-licensed under Apache 2.0 and MIT. You can choose between one of them if you use this work.

SPDX-License-Identifier: Apache-2.0 OR MIT

Duplication of Code

Yes, Feliz.ViewEngine duplicates a lot of code and violates the DRY principle. This is currently by design.

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 (6)

Showing the top 5 NuGet packages that depend on Feliz.ViewEngine:

Package Downloads
Feliz.Bulma.ViewEngine

Package Description

Feliz.ViewEngine.Htmx

A library that allows using Htmx attributes with Feliz.ViewEngine

Felizia.Arctic.ViewEngine

Bulma Hero theme for Felizia.ViewEngine

Feliz.Isomorphic

Polymorphic Type aliases for Server-Side Rendering development with Feliz

Felizia.ViewEngine

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.3 622 12/2/2025
1.0.2 621 12/2/2025
1.0.1 618 12/2/2025
0.27.0 784 6/10/2025
0.24.0 49,921 8/31/2020
0.23.0 2,158 7/7/2020
0.22.0 6,075 6/14/2020
0.21.0 1,080 6/5/2020
0.20.0 1,153 5/11/2020
0.19.0 1,411 4/29/2020
0.18.0 2,260 4/28/2020
0.17.0 1,030 4/27/2020
0.16.0 1,035 4/26/2020
0.15.0 1,646 4/26/2020
0.14.0 1,047 4/26/2020
0.13.0 1,036 4/26/2020
0.12.0 1,088 4/24/2020
0.11.0 1,059 4/23/2020
0.10.0 1,063 4/22/2020
0.9.0 1,068 4/21/2020
0.8.0 1,020 4/21/2020
0.7.0 1,058 4/21/2020
0.6.0 1,127 4/21/2020
0.5.0 1,063 4/21/2020
0.4.0 1,031 4/20/2020
0.3.0 1,103 4/20/2020
0.2.0 1,078 4/20/2020
0.1.1 1,104 4/19/2020