Everything, out of the box
Grit is batteries included — auth, storage, email, jobs, AI, security and observability are wired into every scaffolded project. No plugins to install, no glue to write. Here is the full set, each with the one line you actually call.
POST /api/auth/register
POST /api/auth/login
// -> { "token": "eyJ...", "user": {...} }Authentication
JWT register/login, bcrypt hashing and protected routes — /api/auth/* is live on day one.
Read the docsadmin := r.Group("/api/admin")
admin.Use(middleware.RequireRole("ADMIN"))
admin.GET("/users", h.ListUsers)RBAC & Roles
Uppercase roles and a RequireRole guard — lock any route to ADMIN, EDITOR or USER.
Read the docsurl, err := storage.PresignPut(ctx, "avatars/u1.png")
if err != nil {
return err
}
// client PUTs the file straight to the bucketFile Storage
S3-compatible storage across MinIO, R2 and AWS S3. Hand the client a presigned upload URL.
Read the docsmailer.Send(ctx, mail.Message{
To: user.Email,
Template: mail.Welcome,
Data: map[string]any{"Name": user.Name},
})Email (Resend)
Transactional email through Resend with typed HTML templates for welcome, reset and verify.
Read the docsjobs.Enqueue(ctx, jobs.SendEmail{
UserID: user.ID, // UUID string
Kind: "welcome",
})Background Jobs
Redis-backed async queue (asynq). Enqueue work off the request path and process it in a worker.
Read the docsscheduler.Register("0 * * * *", func(ctx context.Context) error {
return report.GenerateHourly(ctx)
})Cron Scheduler
Register recurring tasks with plain cron expressions — monitored from the admin dashboard.
Read the docsif v, ok := cache.Get(ctx, key); ok {
return v, nil
}
cache.Set(ctx, key, stats, 5*time.Minute)Redis Caching
A tiny cache service plus response middleware. Cache hot reads with a TTL, invalidate on write.
Read the docsstream, err := ai.Stream(ctx, ai.Request{
Model: "anthropic/claude-sonnet-4-6",
Prompt: "Summarise this ticket",
})AI
Stream completions through the Vercel AI Gateway — swap models with one string, no SDK churn.
Read the docsif err := sentinel.MountE(r, db, sentinel.Config{
RateLimit: 100, // req/min per IP
}); err != nil {
log.Fatal(err)
}Sentinel
WAF, rate limiting, brute-force and anomaly detection — one mount and every route is shielded.
Read the docspulse.Mount(ctx, r, db, pulse.Config{
Path: "/pulse",
})
// dashboard live at /pulsePulse
Self-hosted observability: request tracing, DB monitoring, runtime metrics and a live dashboard.
Read the docs$ grit studio ✓ GORM Studio running at http://localhost:8080/studio
GORM Studio
A visual database browser embedded in the API. Inspect and edit rows without leaving the app.
Read the docsif flags.IsEnabled(c, "new-checkout") {
return h.newCheckout(c)
}
return h.legacyCheckout(c)Feature Flags
Ship behind flags with percentage rollouts, allow/block lists and sticky per-user bucketing.
Read the docshooks.Register("stripe", webhook.StripeVerifier(secret))
// POST /webhooks/:provider -> verified & dedupedWebhooks
One inbound endpoint with built-in Stripe, GitHub and HMAC verifiers plus idempotent dedupe.
Read the docshub.SendToUser(user.ID, realtime.Event{
Type: "job.finished",
Data: map[string]any{"id": job.ID},
})Realtime
A WebSocket hub with JWT handshake auth. Push events to one user or broadcast to everyone.
Read the docsFrequently asked questions
Do I have to use all of these?
mailer.Send or mount Pulse, it simply does nothing. Nothing here forces a pattern on the rest of your app; unused batteries add no runtime cost and can be deleted outright.Can I swap the storage / email / AI provider?
anthropic/claude-sonnet-4-6 to another model is a one-string edit.Are these external services or built into Grit?
What do the batteries cost me in bundle size or dependencies?
Do the batteries work in every architecture mode?
Something wrong, unclear, or missing on this page?
Open an issue — your feedback shapes Grit, and we fix docs fast.
