Full-stack Go that doesn't get in the way of you or your agents.
GoFastr is a full-stack Go framework. Declare your domain in Go and get server-rendered screens, REST endpoints, MCP tools, migrations, and typed queries. It stays plain Go on disk that you own.
During development, gofastr dev gives Claude Code or Codex the app's routes, config, and logs over MCP. In production, user agents call the same data under the same permissions.
core only
framework
full-stack app
package mainimport ( "context" "net/http" "github.com/DonaldMurillo/gofastr/core/handler" "github.com/DonaldMurillo/gofastr/core/render" "github.com/DonaldMurillo/gofastr/core/router")type Pong struct { Status string `json:"status"`}func main() { r := router.New() // A server-rendered page. r.Get("/", render.HTMLHandler(func(req *http.Request) render.HTML { return render.Tag("h1", nil, render.Text("Hello from core.")) })) // A typed JSON route — the adapter binds input and serializes output. r.Get("/api/ping", handler.HandlerAdapter(func(ctx context.Context, _ struct{}) (Pong, error) { return Pong{Status: "ok"}, nil })) http.ListenAndServe(":8080", r)}
package mainimport ( "database/sql" "log" "github.com/DonaldMurillo/gofastr/core/schema" "github.com/DonaldMurillo/gofastr/framework" _ "github.com/DonaldMurillo/gofastr/sqlite/stdlib")func main() { db, _ := sql.Open("sqlite3", "app.db") app := framework.NewApp(framework.WithDB(db), framework.WithMCP()) // WithMCP serves the tools at /mcp // CRUD is auto-on when a DB is set (CRUD *bool: nil = auto). app.Entity("posts", framework.EntityConfig{ Exposure: &framework.ExposureConfig{ Public: true, // anonymous read AND write; omit it and CRUD requires a session (secure by default) MCP: true, // emit posts_list/get/create/update/delete MCP tools }, Fields: []schema.Field{{Name: "title", Type: schema.String, Required: true}}, }) log.Fatal(app.Start(":8080")) // GET/POST /posts, /openapi.json, MCP — all live}
package mainimport ( "database/sql" "log" "github.com/DonaldMurillo/gofastr/battery/auth" "github.com/DonaldMurillo/gofastr/core-ui/app" "github.com/DonaldMurillo/gofastr/core-ui/html" "github.com/DonaldMurillo/gofastr/core/render" "github.com/DonaldMurillo/gofastr/core/schema" "github.com/DonaldMurillo/gofastr/framework" "github.com/DonaldMurillo/gofastr/framework/uihost" _ "github.com/DonaldMurillo/gofastr/sqlite/stdlib")// A screen is plain Go: Render returns server-rendered HTML.type HomeScreen struct{}func (s *HomeScreen) ScreenTitle() string { return "Notes" }func (s *HomeScreen) Render() render.HTML { return html.Heading(html.HeadingConfig{Level: 1}, render.Text("My notes"))}func main() { db, _ := sql.Open("sqlite3", "notes.db") // Server-rendered screens. Each also serves an auto llm.md. ui := app.NewApp("Notes") ui.Register("/", &HomeScreen{}, nil) // SEO for those pages. host := uihost.New(ui, uihost.WithDescription("A tiny notes app."), uihost.WithOpenGraph(uihost.OG{Title: "Notes", Type: "website"}), uihost.WithSitemap(uihost.SitemapConfig{BaseURL: "https://notes.example"}), ) // MCP for agents. fwApp := framework.NewUIHostApp(host, framework.WithDB(db), framework.WithAPIPrefix("/api"), framework.WithMCP(), ) // Scope.OwnerField scopes rows per user: anonymous → 401, cross-user → 404. fwApp.Entity("notes", framework.EntityConfig{ Scope: &framework.ScopeConfig{OwnerField: "user_id"}, Exposure: &framework.ExposureConfig{MCP: true}, Fields: []schema.Field{{Name: "title", Type: schema.String, Required: true}}, }) // Login + sessions. authMgr := auth.New(auth.AuthConfig{ DevMode: true, // dev only: mints a per-process JWT secret; set JWTSecret in prod UserStore: auth.NewEntityUserStore(db, "auth_users"), SessionStore: auth.NewEntitySessionStore(db, "auth_sessions"), }) authMgr.Use(auth.NewCorePlugin()) if err := authMgr.Init(fwApp); err != nil { log.Fatal(err) } fwApp.Use(auth.SessionMiddleware(authMgr)) log.Fatal(fwApp.Start(":8080"))}
Numbers you can check.
Each value is measured by this running binary or enforced by a test in the repo. Nothing here is an adjective.
The core runtime, measured from this running binary. Feature modules load on demand; a size-budget test fails the build if any of them grows.
gofastr docs reads them offline. This site serves the same files under /docs and /llms.txt; agents query them over MCP.
list, get, create, update, delete. Each dispatches through the app router, so the caller's login and permissions apply.
SQLite and Postgres. No MySQL, no Mongo.
go build emits it. No Node, no platform, no telemetry.
There is no package.json in the repo. The client runtime is checked-in JS the binary serves.
Server-rendered screens, not just an API.
Below is the shape of a server-rendered screen: a data table with status badges and a create button, built from framework/ui components and served as plain HTML.
Most Go frameworks stop at the API. GoFastr renders the pages too: on the server, in Go, with no React or Vue on the client.
- Every page is full HTML on first load: fast and readable by crawlers and agents.
- A small JS runtime hydrates that HTML in place with no re-render. Cross-page nav swaps content client-side with a route cache; you never write the router.
- In-page changes such as sort, paginate, or add a row are island calls. The server returns new HTML and the runtime swaps one part.
- You write screens in Go, composed from framework/ui components.
Customers
+ New customer| Name | Plan | MRR | Status |
|---|---|---|---|
| Acme Corp | pro | $1,240 | active |
| Globex | enterprise | $8,900 | active |
| Initech | free | $0 | churned |
| Umbrella | pro | $2,150 | active |
/customers: a server-rendered screen from framework/ui, in plain Go you own.
Explore the framework.
Six ways in. Pick the one that matches what you're building.
The primitives
Router, query builder, schema, render, the MCP server, HTML primitives, and signals. These are stdlib-first Go packages you can use on their own.
Framework
The opinionated layer: entities and CRUD, auth, access control, migrations, framework/ui components, and theming.
mcp · llm.md · well-knownAgent-ready
Per-entity MCP tools, auto llm.md, tools that read the running app, and the agent-discovery endpoints your app serves.
Interactivity
The server-driven model: full SSR, island RPC, optimistic UI, and signals + SSE. There is no client framework to ship.
generateThe code generator
Scaffold a Go app from a declaration when you want a head start. It writes plain Go you own and edit.
examples/The example apps
Runnable reference apps include a blog, a SaaS console, an API tour, semantic search, and this site. Each starts with one command.
Built with GoFastr.
A real app in production, and the flagship the framework is proven against.
Barcode & QR Code Maker
A live tool, no signup required, to generate and read barcodes and QR codes as PNG, SVG, or PDF, with CSV/Excel batch export, a REST API, and an MCP server.
examples/meridianMeridian: SaaS console
The flagship is a billing console with customers, subscriptions, invoices, MRR, and charts, plus its marketing site, auth, and admin. It was seeded from one gofastr.yml and has been hand-evolved since.