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.
package main import ( "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 main import ( "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 main import ( "context" "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(ctx context.Context) 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.
- of client JavaScript, gzipped
- 16.2 KB
- 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.
- docs embedded in every binary
- 122
- gofastr docs reads them offline. This site serves the same files under /docs and /llms.txt; agents query them over MCP.
- MCP tools per entity
- 5
- list, get, create, update, delete. Each dispatches through the app router, so the caller's login and permissions apply.
- databases
- 2
- SQLite and Postgres. No MySQL, no Mongo.
- binary to deploy
- 1
- go build emits it. No Node, no platform, no telemetry.
- npm packages
- 0
- 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
meridian.local/customers
| Name | Plan | MRR | Status |
|---|---|---|---|
| Acme Corp | pro | $1,240 | active |
| Globex | enterprise | $8,900 | active |
| Initech | free | $0 | churned |
| Umbrella | pro | $2,150 | active |
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.
Agent-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.
The code generator
Scaffold a Go app from a declaration when you want a head start. It writes plain Go you own and edit.
The example apps
13 runnable reference apps, including a blog, a SaaS console, a storefront, an API tour, an entity admin, a process-isolated module, a WebMCP support console, 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.
Meridian: 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.