The Pitch

Build the product once.
Ship it to every screen.

Grit is the framework for building one business product across web, admin, mobile and desktop, with the API, background jobs, realtime, security and deployment underneath, without rebuilding the machinery for every client. You define a resource once, in Go, and it reaches every surface.

Why Grit exists

Every product rebuilt the same machinery

Every business product we built meant building the same things again: auth and sessions, roles, an admin panel, file uploads, background jobs, email, audit logs, realtime. Then a mobile app, and sometimes a desktop app, talking to the same API.

Each client needed the same model defined again: in Go, in TypeScript, in the validation, in the forms, in the tables. The copies drifted apart. A field added on the backend went missing on mobile; a rule enforced in the form was not enforced by the API. Most of the time went into plumbing, not the product.

Grit exists so that work is done once, correctly, and reaches every client from a single definition.

The machinery tax

The first month is rarely about your product

Before you write the feature that matters, you re-solve the problems you solved on the last project, and the one before that. None of it is hard. All of it is slow, and with every extra client you pay for it again.

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
The same model again in the mobile app
And again in the desktop app

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.

What sets it apart

One definition, every surface

One command writes the resource everywhere it needs to exist, and every piece agrees with every other, because they all come from the same fields. Add a field later with grit generate field and it reaches the model, the validation, the types and the admin form and table in one step.

One command
$grit generate resource Invoice \
$ --fields "number:string:unique,customer:belongs_to:Customer,total:money,due:date,status:select:draft=Draft|paid=Paid"

Go API

Model, service and handler with pagination, search, filters, soft delete and optimistic locking, routes registered.

Database

The model registered for migration, indexes from the field definitions, and a seeder that writes realistic data in batches.

Shared contract

Zod schemas and TypeScript types generated from the same fields, so the frontend and the API validate the same rules.

Data hooks

React Query hooks for list, detail, create, update and delete, typed end to end.

Admin panel

A table with sorting, filters and bulk actions, a form with the right input for each field, Excel export and bulk import.

Mobile app

Expo screens for the list, the detail and the form, talking to the same API with the same types.

Desktop app

Screens in the Wails desktop app, with the same relations, the same validation and the same API client.

API reference

The endpoints added to the interactive API docs, so the contract is published the moment it exists.

Where the database fits

Not a new ORM. What surrounds it.

Underneath, Grit uses GORM, like much of the Go world, and Postgres, MySQL or SQLite. We did not reinvent the data layer, and the database is not the headline. What Grit adds is everything that usually sits around it by hand:

Field types that mean something from the column to the form. money is stored as exact minor units, tel is checked as a real phone number, email, date, country, select and encrypted fields are validated the same way in Go, in Zod and in the input the form renders.

Constraints that answer properly. A duplicate in a unique field comes back as 409 naming the field, a stale edit as a version conflict, a broken rule as 422 with its message. Not a 500 the form cannot explain.

Seeding built for real volumes. Most frameworks assume a seeder writes a few rows. Real work means seeding a million to find where your infrastructure breaks, or loading years of records buried in Excel files. Grit generates batched seeders with realistic data, and bulk import in the admin.

The data layer is one example of the pattern, not the point of it. The point is that none of this is yours to rebuild, on any client.

How it compares

Batteries included, on every client

Go frameworks

Gin, Echo, Fiber, Chi

A router and your choice of ORM.

Auth, admin, uploads, jobs, email, the frontend and every client are yours to build and keep in step.

Laravel, Rails

batteries-included web frameworks

The batteries, conventions and generators.

For the web app. The mobile and desktop apps are separate projects with their own copy of the model.

Grit

Go + React, one monorepo

The batteries, across web, admin, mobile, desktop, jobs, realtime and deployment.

From one definition, in Go. You build the product; the machinery is already there, on every client.

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
  • Define the model again for mobile and desktop
  • Stand up Docker, CI, and a deploy story
Time to first feature~3–6 weeks
With Grit
Two commands
$grit new my-app --triple --desktop
$grit generate resource Product \
$ --fields "name:string,price:money,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 screens. 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 or an ORM. 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.

One definition over many copies

A resource is not a Go model or a TypeScript type. It is both, plus the handler, the Zod schema, the hooks, the admin page and the mobile and desktop screens, generated together from one definition.

You give up picking a different stack per client. You get surfaces that cannot drift apart, because one command writes all of them from the same fields.

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 scaffolds fresh projects in several shapes, including mobile and desktop, then installs, builds, type-checks, lints and tests them, and upgrades a project from the previous release.

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

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, every shape

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

Your next project

When to start it in Grit

Grit pays off when you are building a real business product, and most of all when it has more than one client.

A business product: CRM, ERP, POS, school management, inventory, a marketplace, a booking system
An admin panel the operations team lives in, next to the app customers use
A mobile app or a desktop app that has to agree with the web app on every field
Real data volumes: seeding a million rows to find the breaking point, importing years of records from Excel

Honest limits

When Grit is the wrong choice

A framework that fits everything fits nothing. 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 and GORM 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.

Everything Grit 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.

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 product is one
command away

Install the CLI and scaffold a production-ready Go + React product, web, admin, mobile and desktop, in minutes.

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

Grit v3.362.2 · MIT licensed · Go + React