grit new: what lands, and the shape of a project
One command, and the answers to most of chapter twenty six are already in your directory.
One command, and the answers to most of chapter twenty six are already in your directory. This chapter is a tour of what arrives, so that nothing in part five is a surprise.
Installing
curl -fsSL https://gritframework.dev/install.sh | sh # macOS, Linux# Windows PowerShellirm https://gritframework.dev/install.ps1 | iexgo install github.com/MUKE-coder/grit/v3/cmd/grit@latest
grit version
Creating a project
grit new clinic
It asks a few questions, or you can answer them up front:
grit new clinic --api # API only, no frontendgrit new clinic --architecture triple
The architecture decides how many frontends you get. It is a word this framework uses in a specific way, and it is worth pinning down now because it is not the same thing as an architecture style:
triple- Web app, admin panel and API, as three applications
double- Web app and API, with admin as role-protected routes in the web app
single- One binary serving an embedded SPA
api- The Go API alone
mobile- API plus an Expo application
Watch out
In Grit, architecture means that choice and nothing else. The arrangement of the code inside, the modular monolith with its layers, is called the architecture style, and the two are documented separately for exactly this reason. When someone asks "which architecture does Grit use", find out which question they are asking.
What arrives
clinic/โโโ grit.json the project's own descriptionโโโ docker-compose.yml Postgres, Redis, MinIO, Mailhogโโโ docker-compose.prod.ymlโโโ apps/โ โโโ api/ the Go backendโ โโโ web/ the public Next.js appโ โโโ admin/ the admin panelโโโ packages/โ โโโ shared/ Zod schemas and TypeScript typesโโโ tests/
The Go side is where this book's attention goes:
apps/api/โโโ go.modโโโ Dockerfileโโโ cmd/โ โโโ server/ the APIโ โโโ migrate/ schema changesโ โโโ seed/ realistic dataโ โโโ backup/ andโ โโโ restore/ the half that mattersโโโ internal/ about fifty packages
Five commands rather than one. cmd/restore existing beside cmd/backup is B5 from the last chapter answered honestly: a backup you have never restored is a rumour, so the restore is a first-class command rather than a runbook.
The internal packages
Around fifty, and the names tell you what has already been decided for you. Grouped by what they answer:
- Your layers
models,services,handlers,routes,policies- Identity
authz,password,totp,access,crypto- Data
database,migrate,paginate,concurrency,money,ids- Work
jobs,cron,outbox,saga,workflow,events- Outside
storage,files,media,mail,sms,webhooks,safefetch- Operations
audit,appendonly,backup,health,tracing,flags- Compliance
erasure,gdpr-adjacent pieces,settings- Delivery
respond,sanitize,imports,export,pdf,realtime,sync
You will not read all of these. The point of listing them is that each one is a thing you did not write, and most of them correspond to a lettered problem from chapter twenty six.
Running it
cd clinicgrit migrate # create the schemagrit seed # realistic data to develop againstgrit start # everything, together
grit start brings up the API, the frontends and the infrastructure at once, which is D2 gone. What is now listening:
:8080- The Go API
:3000- The web app
:3001- The admin panel
/studio- A database browser: tables, queries, the ERD
/docs- The API reference, generated from the registered routes
/pulse- Latency, query counts, profiles
/sentinel- Errors, with the request attached
The second group is the interesting one. /studio is D6, /docs is D7 and/pulse is D5, and all three are paths that were already there rather than tools you installed.
If you know JavaScript
/docs deserves a note because it is the kind of thing that is usually a lie. It is assembled from the routes actually registered at runtime, not from comments or a hand-written specification. It cannot drift, because there is no second description to drift from. That is the only way an API document stays true, and it is why Grit generates one rather than asking you to maintain one.
grit.json, and the seeding that matters
grit.json records what the project is: its architecture, its module toggles, its name. The CLI reads it so that later commands know the shape of the thing they are editing.
The seed is worth insisting on, because it is the habit people skip:
grit seed Patient --count 50000
Fifty thousand rows is where you discover whether the list page works. At ten rows the sort is instant, pagination has one page, and an N+1 costs ten queries instead of ten thousand. That is D9, and the seeder is built as the pipeline from chapter fourteen: rows built in chunks, written in batches, with the number in flight bounded by a channel, so a million rows runs in about a minute with the heap flat.
Modules you can switch off
Eleven subsystems are toggles rather than permanent fixtures:
MODULE_AI=falseMODULE_AUDIT=falseMODULE_BACKUP=falseMODULE_CRON=falseMODULE_FILES=falseMODULE_FLAGS=falseMODULE_JOBS=falseMODULE_MAIL=falseMODULE_REALTIME=falseMODULE_TWOFACTOR=falseMODULE_WEBHOOKS=false
Set one to false in .env and that subsystem does not start. Delete its package and the rest still builds. This is the "batteries included, individually removable" claim, and it is checkable: the packages are separate and the seams are real.
Watch out
The default project is the hardened one. Auth, sessions, the audit chain, backups and the upload pipeline are present before you write a line, rather than being plugins you remember to enable.
That is deliberate and it is worth stating as a principle: an opt-in security feature is a security feature most projects do not have. The cost is a bigger project on day one, which is a real cost and the trade this framework makes on purpose.
It is still just Go
Open apps/api/internal/services/user.go. It is a struct with a *gorm.DBfield and methods on it. Open a handler: it reads a request, calls one service method and writes a response. There is no framework type in your code and nothing to learn before you can read it.
// The shape of every generated service.type ContactService struct {DB *gorm.DB}
That is the whole dependency. If Grit disappeared tonight, this project compiles tomorrow, because there is nothing of Grit inside it. Everything you learned in parts one to three applies directly, which was the reason for putting those parts first.
Project 24: make a project and look around
No code to write. Make one and read it, because the rest of part four assumes you have seen these files.
grit new bookshop --apicd bookshopgrit migrategrit seedgrit start
Then answer these by reading, not by searching the documentation.
One. Open apps/api/internal/handlers/user.go and find where it calls the service. How many lines of that handler are about HTTP, and how many are about users? That ratio is the thin-handler rule from chapter eleven, enforced by the generator.
Two. Open apps/api/internal/services/user.go and find paginate.Config. It lists which columns a client may search, sort and filter by. Why is that a whitelist rather than passing the client's column name through? The answer is in chapter twenty two, under placeholders.
Three. Visit /studio and look at the tables. Then visit /docs and find the route for listing users. Compare the parameters it documents with thepaginate.Config you just read: they are the same list, because one is derived from the other.
Four. Count the entries in apps/api/go.mod. Then count what a comparable Express project needs in package.json. Neither number is a virtue on its own, and the comparison is worth seeing.
Five. Set MODULE_MAIL=false in .env, restart, and confirm the API still starts. Then look at what disappeared from the startup log.
Your turn
Run grit new twice with the same name into different directories and compare the two trees byte for byte. They should be identical: the generator is deterministic, which is the property chapter twenty six said a model cannot give you. Then run grit version and note it, because the next chapters describe this version and the framework moves quickly.
Assignment
Commit your work with the message Grit New - Assignment One, exactly as written, so the leaderboard can score it.
Try it
Create the project you described in the last chapter, and read what arrived.
grit new fieldbook
One. Run it, open the admin panel, log in, and confirm the three apps are up. Record the commands that did it in part4-grit/27-new/RUN.md.
Two. Walk apps/api/internal/ and write one line per package saying what it is for. Guess first, then check. The guesses you get wrong are the conventions worth knowing.
Three. Count what landed:
git -C fieldbook ls-files | wc -l
Put the number in RUN.md next to the time it took.
Four. Switch one module off in grit.json, restart, and say what stopped working. Commit the project itself: it is the thing the rest of Part IV edits.
Spot a typo? Have an idea?
Help us improve this lesson. One click opens a GitHub issue with the lesson URL pre-filled, suggest clearer wording, report a bug, or request more depth. The course keeps improving thanks to learners like you.
Suggest an improvement on GitHub