Web Development with veb
veb is V's built-in web framework (the successor to vweb, renamed and reworked in 0.4.x). It compiles routes and templates at compile time.
35.1 Minimal App
module main
import veb
pub struct Context {
veb.Context
pub mut:
user_id int
}
pub struct App {
veb.StaticHandler
pub mut:
visits int
}
@['/']
pub fn (mut app App) index(mut ctx Context) veb.Result {
app.visits++
return ctx.text('Hello, veb! Visits: ${app.visits}')
}
@['/users/:id'; get]
pub fn (app &App) user(mut ctx Context, id int) veb.Result {
return ctx.json({'id': id})
}
@['/users'; post]
pub fn (app &App) create_user(mut ctx Context) veb.Result {
name := ctx.form['name'] or { return ctx.request_error('name required') }
return ctx.json({'created': name})
}
@['/page']
pub fn (app &App) page(mut ctx Context) veb.Result {
title := 'My Page'
items := ['a', 'b', 'c']
return $veb.html() // renders templates/page.html with local variables
}
fn main() {
mut app := &App{}
app.handle_static('static', true) or {}
veb.run[App, Context](mut app, 8080)
}35.2 Templates (templates/page.html)
Templates are compiled into the binary and type-checked.
<h1>@title</h1>
<ul>
@for item in items
<li>@item</li>
@end
</ul>
@if items.len == 0
<p>No items</p>
@end
@include 'partials/footer.html'
@css '/static/style.css'35.3 Middleware, Sessions, Auth
Built-in pieces: veb.auth, veb.csrf, veb.sse (server-sent events), cookies (ctx.set_cookie, ctx.get_cookie), redirects, file responses, CORS middleware (veb.cors), and static files.
Combine with the ORM for full-stack apps (see gitly for a real-world example).
Deploy as a single binary behind nginx/Caddy, or in Docker (FROM thevlang/vlang:alpine for builds, then a scratch/alpine runtime image).
pub fn (app &App) before_request(mut ctx Context) { // runs before each request
println('${ctx.req.method} ${ctx.req.url}')
}
// veb.Middleware[Context]: app.use(handler: auth_middleware)
fn auth_middleware(mut ctx Context) bool {
token := ctx.get_header(.authorization) or { '' }
if token == '' {
ctx.res.set_status(.unauthorized)
ctx.text('unauthorized')
return false
}
return true
}