Introduces Field, Rule, ValidateAll, ResetFields, and AddError for
declarative input validation. Includes built-in rules (Required,
MinLen, MaxLen, Min, Max, Email, Pattern, Custom) and a signup
example exercising the full API surface.
* feat: add middleware example demonstrating route groups
Self-contained example covering v.Use(), v.Group(), nested groups,
Group.Use(), and middleware chaining with role-based access control.
* feat: add per-action middleware via WithMiddleware ActionOption
Reuses the existing Middleware type so the same auth/logging functions
work at both page and action level. Middleware runs after CSRF and
rate-limit checks, with full access to session and signals.
* feat: add RedirectView helper and refactor session example to use middleware
RedirectView lets middleware abort and redirect in one step. The session
example now uses an authRequired middleware on a route group instead of
an inline check inside the view.
* fix: remove dead code, fix double Load and extractParams mismatch
- Remove componentRegistry (written, never read)
- Remove unused signal methods: Bytes, Int64, Float
- Remove unreachable nil check in registerCtx
- Simplify injectRouteParams (extractParams already returns fresh map)
- Fix double sync.Map.Load in injectSignals
- Merge Shutdown/shutdown into single method
- Inline currSessionNum
- Fix extractParams: mismatched literal segment now returns nil
- Minor: new(bytes.Buffer), go c.Sync(), genRandID reads 4 bytes
One-liner static file serving: v.Static("/assets/", "./public") for
filesystem directories and v.StaticFS("/assets/", fsys) for embed.FS.
Both auto-normalize the URL prefix and disable directory listings.
Add per-context and per-action rate limiting using golang.org/x/time/rate.
Configure globally via Options.ActionRateLimit or per-action with
WithRateLimit(). Defaults to 10 req/s with burst of 20.
Generate a per-context CSRF token (128-bit, crypto/rand) and inject it
as a Datastar signal (via-csrf) alongside via-ctx. Validate with
constant-time comparison on /_action/{id} before executing, returning
403 on mismatch. Transparent to users since Datastar sends all signals
automatically.
Closes#9
Add typed Publish[T] and Subscribe[T] generic helpers that handle
JSON marshaling, along with vianats.EnsureStream and ReplayHistory
helpers. Refactor nats-chatroom to use the new APIs.
Add pubsub-crud example demonstrating CRUD operations with DaisyUI
toast notifications broadcast to all connected clients via NATS.
Add window-scoped keydown dispatching with per-key signal and
preventDefault options. Use comma operator instead of semicolons
in generated ternary expressions to produce valid JavaScript.
OnKeyDownMap merges multiple key bindings into a single
data-on:keydown__window attribute via a JS ternary chain,
avoiding HTML attribute deduplication. WithWindow scopes
any keydown listener to the window object.
Handle SIGINT/SIGTERM in Start() to cleanly drain all contexts,
stop goroutines, close SSE connections, and tear down PubSub.
Fix stopAllRoutines() to close() the channel instead of sending a
single value, so all listening goroutines are notified.
Switch from the standard library log package to rs/zerolog with
ConsoleWriter for colorful terminal output in dev mode and JSON
output in production. Users can now provide their own logger via
Options.Logger or set the level via Options.LogLevel.
Define PubSub and Subscription interfaces in the core via package with
a vianats sub-package providing the embedded NATS + JetStream
implementation. Expose c.Publish() and c.Subscribe() on Context with
automatic subscription cleanup on session close. Refactor the NATS
chatroom example to use the built-in methods instead of manual
subscription tracking.
Demonstrates pub/sub messaging as an alternative to custom Rooms
implementation. Uses delaneyj/toolbelt/embeddednats to run NATS
with JetStream inside the binary - no external server required.
Add NewSQLiteSessionManager helper that creates an SCS session manager
backed by SQLite, allowing sessions to persist across server restarts.
The function handles table creation automatically.
Previously only called Sync() on SSE reconnect (detected via last-event-id
header). This caused issues when application code registered contexts for
updates before the SSE connection was established - patches sent to
patchChan could be dropped.
Now always call Sync() when SSE connects, ensuring clients receive the
full current state regardless of what happened before the connection
was established.
Fixes#2
Flatten DatastarConfig struct into Options (DatastarContent, DatastarPath)
and replace datastarHandlerRegistered bool with sync.Once for thread safety.
Allow users to provide their own Datastar.js script (e.g., Datastar Pro
or custom builds) via Via's Options configuration. Adds DatastarConfig
struct with Content ([]byte) and Path (string) fields.
Add SSE-based navigation methods to Context:
- Redirect(url) / Redirectf() - navigate to new page
- ReplaceURL(url) / ReplaceURLf() - update URL without navigation
Update session example to demonstrate full login flow with redirects.
* feat: add Handler() method for testing and custom server integration
Exposes the underlying http.Handler to enable:
- Integration testing with gost-dom/browser for SSE/Datastar testing
- Custom server setups (e.g., embedding Via in existing applications)
- Standard Go httptest patterns
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: Suppress closed pipe errors when SSE connection closes
Don't log error when SSE fails to send patches if the connection was
already closed. This reduces noise in logs during shutdown and testing,
where browsers/clients close connections before server handlers finish.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: joeblew999 <joeblew999@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Remove unused method. Don't panic if unknown room.
* Need a Connected() check for rooms publishing - don't do the work of rendering for a dead connection
* Make vars private.
* Linter issues
* Remove Connected()
* Mutation observer. Publish 4x / second.
---------
Co-authored-by: João Gonçalves <joao.goncalves01@gmail.com>