npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@nakedev/go-scaffold

v0.1.0

Published

Scaffold Gin + GORM + Postgres Go backend projects with a consistent domain-module standard

Readme

@nakedev/go-scaffold

A CLI that scaffolds a Gin + GORM + PostgreSQL Go backend, then keeps generating consistent domain modules into that project as it grows — the Go counterpart to nest-scaffold.

You don't hand-wire a new domain into cmd/api/main.go, write the handler/service/repository boilerplate, or decide error-handling conventions each time — the CLI does that, and every module it generates follows the same shape as the last one.

Install

pnpm install
pnpm run build

npm link / pnpm link --global may not put the binary on your PATH depending on your machine's npm/pnpm global-bin config — rather than fight that, run the CLI directly, or add a shell alias once:

node bin/go-scaffold.js create my-api --defaults
# or: alias go-scaffold="node $(pwd)/bin/go-scaffold.js"

The rest of this README uses the bare go-scaffold ... form for brevity — substitute the node bin/go-scaffold.js ... form or your alias if you haven't linked it.

Quick start

go-scaffold create my-api
cd my-api
make docker-up   # if you kept Docker + PostgreSQL
go mod tidy
make run

Then grow the project without leaving the CLI:

go-scaffold generate module orders
go-scaffold generate method orders approve --type patch

Commands

create <name> — scaffold a new project

go-scaffold create my-api                                   # interactive wizard
go-scaffold create my-api --defaults                        # no prompts, CI-friendly
go-scaffold create my-api --defaults --no-docker --api-prefix beta

Produces a bare skeleton onlycmd/api, the shared platform packages (config/apperror/dberr/httpx/id/middleware/pagination), Docker+Postgres, migrations folder, and the standards docs (docs/architect/, AGENTS.md, CLAUDE.md, .claude/skills/go-scaffold/). No domain modules — add those with generate module.

| Option | Effect | |---|---| | --defaults | Skip the wizard, use defaults (Docker on, OpenAPI docs on, prefix v1) | | --no-docker | Skip docker-compose.yml (with --defaults) | | --no-openapi-docs | Skip docs/openapi.yaml (with --defaults) | | --api-prefix <prefix> | URL prefix every route is grouped under (with --defaults; default v1, "" for none, /-separated segments like api/v1 are fine) |

Without --defaults, an interactive wizard asks the same three questions. The prefix is a single project-wide choice made once at create time — there's no per-domain versioning (a domain that needs a real breaking change gets a new domain package or a new DTO field, not a duplicated model pointed at the same table under a different URL — see "Why no per-domain versioning" below).

Config file — every create writes go-scaffold.config.json to the project root; generate reads it back (or auto-detects from go.mod / directory layout if missing).

generate module <name> (alias m) — add a domain module

go-scaffold generate module orders                  # full CRUD (default)
go-scaffold generate module orders --no-full         # minimal skeleton — add endpoints with `generate method`

Full CRUD (default) scaffolds:

internal/app/orders/
├── model/model.go      # domain model + GORM table (id/created_at/updated_at — add real fields yourself; a folder so multi-table domains can add more files)
├── dto.go               # request/response structs (empty stubs — add real fields yourself)
├── errors.go             # ORDERS_NOT_FOUND / ORDERS_CONFLICT / ORDERS_HAS_REFERENCES
├── repository.go         # GORM data access
├── service.go            # business logic + repository interface (mockable)
├── handler.go            # Gin routes, registered under the project's API prefix
├── service_test.go       # unit test, fake repo
└── handler_test.go       # integration test, real Postgres, tx rollback

--no-full scaffolds the same model/errors/repository (so generate method always has a full data-access surface to call), but dto/service/ handler start empty — no default CRUD, no routes, just the plumbing (Register(), the repository interface, wrapFindErr) that generate method patches into. Use it when a domain doesn't need the full REST surface, or you'd rather add endpoints one at a time.

Both modes also:

  • Register the module in cmd/api/main.go (via marker comments — see // go-scaffold:* in that file) — full wires an actual route, minimal wires an empty route group
  • Add the model to the AutoMigrate(...) call
  • Append migrations/<seq>_create_<plural>.{up,down}.sql

What it does not do: invent your fields or wire foreign keys between domains — see docs/architect/patterns.md in the generated project for the conventions to follow by hand.

generate method <module> <name> (alias me) — add one endpoint

go-scaffold generate method orders approve --type patch
go-scaffold generate method orders findByStatus --type get --get-mode one --field status
go-scaffold g me orders findOverdue --type get --get-mode all

Patches an existing module's handler.go/service.go in place via the same marker-comment approach as main.go — never a whole new module. Never overwrites a method with the same name; picks a different one or errors.

| Option | Effect | |---|---| | --type <get\|post\|put\|patch\|delete> | HTTP verb | | --get-mode <all\|one> | For get only — list-style vs. single-record lookup | | --field <name> | For get --get-mode one — the lookup field (e.g. email, status); can't be id |

| --type | Route | What's generated | |---|---|---| | get --get-mode all | GET /<plural>/<kebab-name> | reuses FindAll — TODO to add real filtering | | get --get-mode one --field <f> | GET /<plural>/<f>/:<f> | a real FindBy<F> query added to the repository (+ its interface + fakeRepo test stub) | | post | POST /<plural>/<kebab-name> | adds a body DTO; service is a TODO stub | | put / patch | <VERB> /<plural>/:id/<kebab-name> | finds by id, TODO before saving (safe no-op until implemented) | | delete | DELETE /<plural>/:id/<kebab-name> | TODO stub |

Business logic is always left as a TODO-marked stub that compiles and returns a clean 500 rather than inventing behavior — see docs/architect/patterns.md in the generated project.

generate method prints the route it added but does not touch docs/openapi.yaml — endpoint-specific spec entries stay hand-written.

remove module <name> (alias rm m) — drop a domain

go-scaffold remove module orders          # confirms first
go-scaffold rm m orders --yes             # skip the confirm

The inverse of generate module: deletes internal/app/<name>/ and reverses everything that was wired up — the import/AutoMigrate/route in main.go, the paths/schemas in docs/openapi.yaml, the per-module docs folder, and the create_<plural> migration. Restores the _ = api placeholder if it was the last module, so the project still builds. Use this instead of hand-deleting the folder — a partial hand-delete leaves stale wiring that duplicates on the next generate module (which would panic gin at startup).

Why no per-domain versioning

Earlier versions of this CLI let a domain live in a v1//v2/ folder with its own route group and import alias, so the same domain name could exist twice with different behavior. It was cut: the migration (and usually the DB table) is shared between "versions" of the same domain, but each version got its own physically-copied model.go — nothing stopped the two structs from drifting apart. Verified against a real Postgres instance: AutoMigrate silently accepted a column typed int in one version's model and float64 in the other for the same column, converging it to numeric with no error — the two versions would then read/write the same data with different, silently incompatible interpretations.

Instead, every route in a project is grouped under a single project-wide --api-prefix (default v1) chosen once at create time. A domain that needs a real breaking change gets a new domain package, or a new field on the existing DTO — not a duplicated model pointed at a table it can drift out of sync with.

Project structure produced by create

cmd/api/main.go
internal/
├── platform/database/
├── shared/{config,apperror,dberr,httpx,id,middleware,pagination}/
└── app/                      # empty until you `generate module`
docs/
├── architect/{architecture,patterns,techstack}.md
└── openapi.yaml + common/ + health/   # if openapi docs enabled
migrations/
.github/workflows/ci.yml    # build, vet, gofmt check, golangci-lint, go test (with a Postgres service)
Makefile
.golangci.yml
.vscode/settings.json
AGENTS.md
CLAUDE.md
.claude/skills/go-scaffold/SKILL.md
go-scaffold.config.json

Supported stack

| Package | Version | |---|---| | Gin | v1.10.0 | | GORM + postgres driver | v1.25.12 / v1.5.9 | | validator/v10 | v10.20.0 | | google/uuid | v1.6.0 |

License

MIT