Views
Views are svelte components exported by app/exports.server.ts and/or app/exports.client.ts .


Server Exports
Views that are meant to be rendered on the server should be exported by app/exports.server.ts .
import Welcome from '$lib/views/welcome.svelte'
import Profile from '$lib/views/profile.svelte'
export const views = {
    "Welcome": Welcome,
    "Profile": Profile,
}
Note
The $lib/ path is an alias for app/lib/


Client Exports
Views that are meant to be rendered on the client should be exported by app/exports.client.ts .
export const views = {
    "Welcome": () => import('$lib/views/welcome.svelte'),
    "Profile": () => import('$lib/views/profile.svelte'),
}
Note
The $lib/ path is an alias for app/lib/
Note
These views are being imported asynchronously in order to split them in different bundles, however you can simply create fake promises in order to bundle them all together and eliminate network latency when transitioning between views.
import Welcome from '$lib/views/welcome.svelte'
import Profile from '$lib/views/profile.svelte'
export const views = {
    "Welcome": () => Promise.resolve(Welcome),
    "Profile": () => Promise.resolve(Profile),
}
Note
Keys in app/exports.server.ts and app/exports.client.ts are not mutually exclusive.
You can render the same component on both the server and the client at the same time.


Send Views
In order to send a view you need to create a new render function using either ssr.New() or csr.New() then pass that render function to send.View() along with your embedded file system.
package main

import (
    "embed"
    "main/lib/core/routes"
    "main/lib/core/scopes"
    "main/lib/core/send"
    "main/lib/core/ssr"
    "main/lib/core/views"
    "net/http"
)

//go:embed app/dist
var efs embed.FS
var render = ssr.New(ssr.Options{Efs: efs, Limit: 1})

func View(_ scopes.Scope, request *http.Request, writer http.ResponseWriter) {
    send.View(writer, request, render, views.View{Name: "Welcome"}) // Sends view "Welcome".
}
Note
The embedded file system (efs ) must point to the app/dist directory.
The Name of the view will be used to lookup the view component exported by app/exports.server.ts and/or app/exports.client.ts .

Default View
There is no way to specify a "default view”. However, you can use send.RequestedFile() in order to send the requested file or run custom logic if it doesn’t exist.
package main

import (
    "embed"
    "main/lib/core/routes"
    "main/lib/core/scopes"
    "main/lib/core/send"
    "main/lib/core/ssr"
    "main/lib/core/views"
    "net/http"
)

//go:embed app/dist
var efs embed.FS
var render = ssr.New(ssr.Options{Efs: efs, Limit: 1})

func View(_ scopes.Scope, request *http.Request, writer http.ResponseWriter) {
    // Tries to send the requested file, or else...
    if found, err := send.RequestedFile(writer, request, efs, "/"); err != nil || !found {
        // ...sends the "Default" view.
        send.View(writer, request, render, views.View{Name: "Default"})
    }
}
Tip
Usually you would map this handler to the default GET / pattern, which automatically captures all unmatched requests.


View Properties
Optionally, you can specify properties for your View with the Props field.
package main

import (
    "embed"
    "main/lib/core/routes"
    "main/lib/core/scopes"
    "main/lib/core/send"
    "main/lib/core/ssr"
    "main/lib/core/views"
    "net/http"
)

//go:embed app/dist
var efs embed.FS
var render = ssr.New(ssr.Options{Efs: efs, Limit: 1})

func View(_ scopes.Scope, request *http.Request, writer http.ResponseWriter) {
    send.View(writer, request, render, views.View{
        Name: "Welcome",
        Props: map[string]string{
            "name": "world", // ---> Props go here. <---
        },
    })
}
These properties are passed down to your view component.
<script lang="ts">
    type Props = { name: string }
    let {name}:Props = $props() // Retrieves view props.
</script>

<Title  text="Hello {name}"/>
Note
View properties are initialized with $state() and thus are reactive by default.


Render Modes
You can choose how to render views by setting one of 3 values for the RenderMode field in your View .

1
views.RenderModeFull
Using views.RenderModeFull , the view is rendered on both the server and the client.
This is the default mode.
package main

import (
    "embed"
    "main/lib/core/routes"
    "main/lib/core/scopes"
    "main/lib/core/send"
    "main/lib/core/ssr"
    "main/lib/core/views"
    "net/http"
)

//go:embed app/dist
var efs embed.FS
var render = ssr.New(ssr.Options{Efs: efs, Limit: 1})

func View(_ scopes.Scope, request *http.Request, writer http.ResponseWriter) {
    send.View(writer, request, render, views.View{
        Name:       "Welcome",
        RenderMode: views.RenderModeFull, // Configures render mode
                                          // to "both server and client".
    })
}
2
views.RenderModeServer
Using views.RenderModeServer , the view is rendered only on the server.
You’ll have to deal away with apis such as fetch; your new best friend is form.
package main

import (
    "embed"
    "main/lib/core/routes"
    "main/lib/core/scopes"
    "main/lib/core/send"
    "main/lib/core/ssr"
    "main/lib/core/views"
    "net/http"
)

//go:embed app/dist
var efs embed.FS
var render = ssr.New(ssr.Options{Efs: efs, Limit: 1})

func View(_ scopes.Scope, request *http.Request, writer http.ResponseWriter) {
    send.View(writer, request, render, views.View{
        Name:       "Welcome",
        RenderMode: views.RenderModeServer, // Configures render mode
                                            // to "server only".
    })
}
Tip
While using views.RenderModeServer the view won’t serve a JavaScript bundle, but you can still use the <svelte:head> special tag in order to load scripts dynamically.
Caution
A csr function will always render blank page when the view is configured to use views.RenderModeServer .
package main

import (
    "embed"
    "main/lib/core/csr"
    "main/lib/core/routes"
    "main/lib/core/scopes"
    "main/lib/core/send"
    "main/lib/core/views"
    "net/http"
)

//go:embed app/dist
var efs embed.FS
var render = csr.New(csr.Options{Efs: efs}) // Using csr function.

func View(_ scopes.Scope, request *http.Request, writer http.ResponseWriter) {
    send.View(writer, request, render, views.View{
        Name:       "Welcome",
        RenderMode: views.RenderModeServer, // Because this mode attempts to
                                            // render exclusively on the server,
                                            // and the csr function cannot render on the
                                            // server, this handler will send an
                                            // empty response to the client.
    })
}
3
views.RenderModeClient
Using views.RenderModeClient , the view is rendered only on the client by loading a JavaScript bundle asynchronously.
package main

import (
    "embed"
    "main/lib/core/routes"
    "main/lib/core/scopes"
    "main/lib/core/send"
    "main/lib/core/ssr"
    "main/lib/core/views"
    "net/http"
)

//go:embed app/dist
var efs embed.FS
var render = ssr.New(ssr.Options{Efs: efs, Limit: 1})

func View(_ scopes.Scope, request *http.Request, writer http.ResponseWriter) {
    send.View(writer, request, render, views.View{
        Name:       "Welcome",
        RenderMode: views.RenderModeClient, // Configures render mode
                                            // to "client only".
    })
}
Tip
You can combine any of these render modes with adaptive hyperlinks and forms.
Read more about web standards.