A lightweight Go + SQLite + SQLC backend starter. Clone it, build on it.
- Single binary: Go compiles to one binary. SQLite is embedded. No external database servers.
- Type-safe SQL: SQLC generates Go code from your SQL — no ORMs, no magic, just SQL.
- Concurrency-safe: Pre-configured WAL mode + busy timeout so SQLite won't choke under load.
- JWT auth included: Register, login, and protected routes out of the box.
- Container-ready: Multi-stage Containerfile produces a minimal
scratchimage.
git clone https://github.com/Stan-breaks/nimble.git
cd nimble
# Start developing — auto-generates SQLC code and rebuilds on file changes
just watchThe server starts on :8080 and auto-rebuilds when you edit .go or .sql files.
nimble/
├── main.go # Entry point, DB init, server start
├── database/ # Generated SQLC code (gitignored)
├── sqlc/
│ ├── schema.sql # Table definitions
│ └── query.sql # SQL queries → Go functions
├── router/
│ ├── router.go # Route definitions
│ ├── apis/ # JSON API handlers
│ └── middleware/ # Auth middleware
├── example/ # Advanced patterns & reference code
├── sqlc.yaml # SQLC config
├── justfile # Task runner
└── Containerfile # Multi-stage container build
| Method | Path | Auth | Description |
|---|---|---|---|
POST |
/api/register |
✗ | Create a new user |
POST |
/api/login |
✗ | Login, get JWT cookie |
GET |
/api/me |
✓ | Get current user |
# Register
curl -X POST http://localhost:8080/api/register \
-H "Content-Type: application/json" \
-d '{"email":"you@example.com", "password":"secret123"}'
# Login
curl -X POST http://localhost:8080/api/login \
-H "Content-Type: application/json" \
-d '{"email":"you@example.com", "password":"secret123"}'The example/ directory contains advanced patterns extracted from a real project built with Nimble:
| File | What It Shows |
|---|---|
schema.sql |
Role-based tables, foreign keys, status tracking with defaults |
query.sql |
FK assignment updates, filtered queries (IS NULL), bulk fetch |
api_patterns.go |
Role-based auth switch, safe response types, dashboard aggregation, nullable FKs, duplicate-check pattern |
Use these as reference when building your own features.
CREATE TABLE IF NOT EXISTS posts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
title TEXT NOT NULL,
body TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);-- name: CreatePost :one
INSERT INTO posts (user_id, title, body)
VALUES (?, ?, ?)
RETURNING *;
-- name: GetPostsByUser :many
SELECT * FROM posts WHERE user_id = ?;just watch picks up your .sql changes automatically and regenerates the Go code. The generated functions are ready to use in your API handlers.
# Build
podman build -t nimble .
# Run
podman run -p 8080:8080 nimbleWorks with Docker too — just swap podman for docker.
Nimble configures SQLite for safe concurrent access:
- WAL mode: Readers don't block writers (and vice versa)
- Busy timeout: 5s retry instead of immediate
SQLITE_BUSYerrors - Single connection pool: Prevents Go's
database/sqlfrom opening multiple writers
This handles most web app workloads. For very high write throughput, consider PostgreSQL.
MIT © [Stan-breaks]