Getting Started
Vango is optimized for full-stack Go apps with server-owned UI state. The normal app flow is:
create the app
register routes and layouts
keep page handlers thin
push stateful logic into vango.Setup components
let the browser connect to the runtime and apply patches
Canonical project structure
1myapp/
2|- cmd/
3| `- server/
4| `- main.go
5|- app/
6| |- routes/
7| |- components/
8| |- stores/
9| `- middleware/
10|- internal/
11| |- services/
12| |- db/
13| `- config/
14|- public/
15|- vango.json
16|- vango_state_manifest.json
17|- vango_state_schema.json
18`- go.mod
Use this layout consistently:
app/routes owns route files
app/components owns shared UI
app/stores owns session keys and durable store-like surfaces
internal/services owns business logic and I/O
public owns static assets
Typical server entry point
1package main
2
3import (
4 "context"
5 "log"
6 "os"
7 "time"
8
9 "github.com/vango-go/vango"
10 "myapp/app/routes"
11)
12
13func main() {
14 app, err := vango.New(vango.Config{
15 Session: vango.SessionConfig{
16 ResumeWindow: vango.ResumeWindow(30 * time.Second),
17 },
18 Static: vango.StaticConfig{
19 Dir: "public",
20 Prefix: "/",
21 },
22 DevMode: os.Getenv("VANGO_DEV") == "1",
23 })
24 if err != nil {
25 log.Fatal(err)
26 }
27
28 routes.Register(app)
29
30 if err := app.Run(context.Background(), ":3000"); err != nil {
31 log.Fatal(err)
32 }
33}
At startup, the usual sequence is:
load configuration
build dependencies
create the Vango app
wire auth or session hooks if needed
register routes
run the server
Basic layout
Layouts are pure wrappers. Keep them responsible for shell structure and bootstrap only.
1func Layout(ctx vango.Ctx, children vango.Slot) *vango.VNode {
2 return Html(
3 Head(
4 Meta(Charset("utf-8")),
5 Meta(Name("viewport"), Content("width=device-width, initial-scale=1")),
6 LinkEl(Rel("stylesheet"), Href(ctx.Asset("styles.css"))),
7 ),
8 Body(
9 Main(children),
10 RuntimeScripts(ctx),
11 ),
12 )
13}
Good layout responsibilities:
navigation
asset tags
shell structure
persistent banners
runtime scripts
If you need state in the layout, embed a Setup component inside it. Do not make the layout function itself imperative.
Basic page
Page handlers should stay thin.
1func IndexPage(ctx vango.Ctx) *vango.VNode {
2 return Div(Text("Hello from Vango"))
3}
That handler is a render-time function, not an imperative route-entry callback. Treat it like view selection.
File-based routing
Vango scans app/routes.
Common mappings:
app/routes/index.go -> /
app/routes/about.go -> /about
app/routes/projects/index.go -> /projects
app/routes/projects/id_/index.go -> /projects/:id
app/routes/docs/path___/index.go -> /docs/*path
app/routes/layout.go -> root layout
app/routes/api/*.go -> API endpoints
Prefer Go-friendly parameter directories like id_ and path___ instead of bracketed names.
Recommended mental model for a new app
route handlers choose the view
Setup components own state and lifecycle
Resources own reads
Actions own mutations
render computes UI from current state only
If you need the core contracts before you write more app code, read Mental Model next.