Faq
Why doesn’t Frizzante have middleware?
Frizzante intentionally uses guards instead of middleware because of the following reasons
  • All middleware handlers must be invoked for each request
  • It's difficult to understand which middleware handler checks which route
  • Managing middleware execution order across different routes is complex

Instead, it favours guards because
  • Guards are applied only to specific routes, they don't check every single incoming request
  • They are more explicit, you can see which guards protect which route just by looking at the route definition
  • It's easy to compose and ensure a specific order of guards execution for each individual route
For more details see the guards page.

Middleware Implementation
If you really want middleware-like behavior, you can easily implement it in your own project.
package middlewares

import "main/lib/core/clients"

type Hook func(client *clients.Client, next func()) // Defines a hook function type which will be used by the middleware.

type Middleware struct {                            // Defines a structure holding multiple hooks.
    Hooks []Hook                                    // Defines the actual hooks slice.
}
package middlewares

import (
    "main/lib/core/clients"
    "main/lib/core/routes"
)

func Apply(middleware *Middleware, routes []routes.Route) {
    for _, route := range routes {                               // For each route...
        handler := r.Handler                                     // ...saves the route handler for later use.
        route.Handler = func(client *clients.Client) {           // Assigns a new wrapper route handler.
            var quit bool                                        // Creates flag used to interrupt the chain.
            for _, hook := range middleware.Hooks {              // Iterate over hooks.
                quit = true                                      // Prepares to quit.
                if hook(client, func() { quit = false }); quit { // Invokes hook and checks if route should quit.
                    return                                       // Quits.
                }
            }
            handler(client)                                      // Invokes the actual route handler.
        }
    }
}
Note
Your implementation may vary.
This implementation doesn’t directly invoke the next hook, instead it use a flag to check when to stop.
This should reduce nesting in your stack trace and keep it a little more readable.


Middleware Usage
package main

import (
    "embed"
    "main/lib/core/clients"
    "main/lib/core/routes"
    "main/lib/core/servers"
    "main/lib/core/view/ssr"
    "main/lib/middlewares"
    "main/lib/routes/fallback"
    "main/lib/routes/todos"
    "main/lib/routes/welcome"
    "os"
)

//go:embed app/dist
var efs embed.FS
var server = servers.New()

var middleware = &middlewares.Middleware{
    Hooks: []middleware.Hook{
        func(client *clients.Client, next func()) {
            // Hook logic goes here.
        },
    },
}

func main() {
    defer servers.Start(server)
    defer middlewares.Apply(middleware, server.Routes) // Applies middleware to server routes.
                                                       // Remember that deferred functions are executed in reverse,
                                                       // so this line will execute before the server starts.
    server.Efs = efs                                   // Sets embedded file system.
    server.Routes = []routes.Route{
        {Pattern: "GET /", Handler: fallback.View},
        {Pattern: "GET /welcome", Handler: welcome.View},
        {Pattern: "GET /todos", Handler: todos.View},
        {Pattern: "GET /check", Handler: todos.Check},
        {Pattern: "GET /uncheck", Handler: todos.Uncheck},
        {Pattern: "GET /add", Handler: todos.Add},
        {Pattern: "GET /remove", Handler: todos.Remove},
    }
}


Can I use Frizzante with other frontend frameworks?
Yes you can, as long as Vite supports your framework.
All you need to do is configure your app/app.client.ts and app/app.server.ts to render your framework.
You can find an old Vue3 example here.