The Pitch

What if your backend
shipped with the frontend
already wired?

Every full-stack app starts the same way: weeks of plumbing before a single feature ships. Grit asks a different question — what is the smallest set of commands that takes you from idea to a production-ready Go + React app?

If you are evaluating Grit, or just curious how we think about building a full-stack framework, this page explains the why behind the decisions — including the ones we know are not for everyone.

Grit brings coherence and speed to Go + React development without hiding the platform underneath it. Everything it generates is ordinary code in your repo, which means the framework can never become the thing standing between you and a fix.

It is MIT licensed, developed in the open, and supported by sponsors rather than a sales team. Releases are public, versioned, and shipped weekly.

For the longer story — why Go, why React, and what Grit borrows from Laravel and Rails — read the philosophy doc.

The boilerplate tax

The first month is rarely about your product

Before you write the feature that matters, you re-solve the same problems you solved on the last project — and the one before that. None of it is hard. All of it is slow.

Auth: JWT, refresh, OAuth, 2FA, password reset
An admin panel with tables, forms, and filters
File uploads to S3 / R2 with presigned URLs
Background jobs, queues, and a scheduler
Email templates and a transactional sender
Rate limiting, CORS, security headers, audit logs
Type-safe API clients and React Query hooks
Docker, migrations, seeders, CI, deploy scripts

That is months of work that produces zero product differentiation. Grit treats all of it as solved — generated, wired, and hardened the moment you scaffold.

Compress the work

The same outcome, two timelines

Without a framework
  • Pick a router, ORM, auth lib, queue, mailer
  • Glue them together; debug the seams
  • Hand-roll an admin UI per resource
  • Wire types between Go and TypeScript by hand
  • Stand up Docker, CI, and a deploy story
Time to first feature~3–6 weeks
With Grit
Two commands
$grit new my-app --triple
$grit generate resource Product \
$ --fields "name:string,price:float,stock:int"
Time to first feature~5 minutes

What Grit stands for

Six trades, stated plainly

Every one of these costs something. A preference that costs nothing is not a principle, it is a feature list — so each one below names what you give up.

1.

Generated over hidden

Grit writes real files into your repo — the model, service, handler, routes, hooks and admin page. Not a runtime dependency that does it invisibly at boot.

You give up a small repo. You get code you can read, edit, delete, and debug with a stack trace that points at your own file. There is no "fighting the framework" because there is no framework in the way — just Go and TypeScript you own.

2.

Boring over clever

Gin, GORM, Next.js, Postgres, Redis. Every one has years of production behind it and its answers already written down somewhere.

You give up novelty. We are not going to invent a router. The interesting part of your project should be your product, not the stack underneath it.

3.

Opinionated over configurable

One way to do auth. One queue. One storage layer. Escape hatches where you need them, not a menu where you do not.

You give up the pleasure of choosing. You get a codebase where every Grit project looks the same, onboarding takes an afternoon, and an AI agent never has to guess which of six patterns you picked.

4.

Whole-stack over layer-by-layer

A resource is not a Go model or a TypeScript type. It is both — plus the handler, the Zod schema, the React Query hook and the admin page — generated together from one definition.

You give up picking your own frontend and backend languages. You get two halves that cannot drift apart, because one command writes both.

5.

Secure on day one over hardened on day ninety

CSRF, strict CSP, rate limiting, SSRF defence, IDOR-safe ownership checks, field-level encryption, server-side sessions and a tamper-evident audit log — in the scaffold.

You give up the option to skip it. That is the point: security is the work that never wins a prioritisation meeting against a feature, so it ships before the meeting happens.

6.

Verified over asserted

Every release runs a 73-check matrix across 13 project shapes — scaffold, install, build, typecheck, test — then gets re-verified by downloading the published binary and building a fresh project with it.

You give up a faster release cadence. Claims in a changelog are cheap; we would rather find the bug than describe the feature.

One command, full stack

Generate the backend and the frontend in the same breath

grit generate resource emits the Go model, service, handler, routes, Zod schema, TypeScript types, React Query hooks, and an admin page — all consistent, all type-safe.

generated · one command
func (h *ProductHandler) List(c *gin.Context) {
var products []models.Product
h.DB.
Where("user_id = ?", c.GetString("user_id")).
Order("created_at desc").
Find(&products)
c.JSON(http.StatusOK, gin.H{"data": products})
}
export function useProducts() {
return useQuery({
queryKey: ['products'],
queryFn: async () => {
const res = await api.get('/api/products')
return res.data.data as Product[]
},
})
}
Both files written by grit generate resource Product

What the trades buy you

The compounding return on a narrow set of opinions

Agents work, not guess

Because there is one way to do each thing, an AI assistant has nothing to guess. Grit ships a SKILL.md, and grit mcp serve hands an agent the real route table and model definitions over MCP — parsed from your source, read-only.

Security you did not schedule

The hardening in every scaffold is work no one budgets for: SSRF defence, IDOR-safe ownership checks, GDPR export and erasure, SSO with SAML, field-level encryption. Already there, already tested.

One set of patterns, five shapes

Embed a SPA in the Go binary, split web / admin / API into a monorepo, go API-only, or add mobile and desktop. The generators and conventions do not change — only the shape does.

Honest limits

When Grit is the wrong choice

A framework that fits everything fits nothing. Here is where Grit does not fit — better to find out on this page than three weeks into a rewrite.

Your team does not want to write Go

Grit is Go on the backend, and that is not configurable. If you are TypeScript end to end, AdonisJS or Nest will make you happier, and we would rather you were happy than converted.

You want to pick your own ORM and router

You can swap them — it is your code. But you would be working against the generators, and that cost compounds with every resource you add.

You are building one small service with no UI

The batteries become weight you never use. `--api` trims a lot of it, but a plain Gin binary may genuinely be the simpler answer.

You need a decade-old ecosystem

Grit is young. Fewer Stack Overflow answers, fewer third-party plugins, fewer people who have hit your exact bug. What you get instead is a maintainer who ships weekly and answers questions directly.

If none of those describe you, the rest of the decisions on this page were made with your project in mind.

Community

Build alongside other Grit developers

Join the WhatsApp community for questions, tutorials, and guidance from people shipping Grit apps, and from the person who builds it. No question is too small.

Join the community

Your next project is one
command away

Install the CLI and scaffold a production-ready Go + React app in minutes.

Install — macOS / Linux
$curl -fsSL https://gritframework.dev/install.sh | sh

Grit v3.170.0 · MIT licensed · Go + React