Skip to Content

gofasta new

Creates a brand-new Gofasta project from scratch. By default, this generates a REST-only Postgres-backed project with database migrations, authentication, dependency injection, background jobs, email support, Docker configuration, and CI/CD pipelines. Two flags adjust what gets generated: --driver picks the database engine, and --graphql adds a GraphQL layer alongside REST.

Usage

gofasta new <name> [flags]

The <name> can be a simple name like myapp or a full Go module path like github.com/myorg/myapp. When a simple name is used (no / in the argument), the module path defaults to the project name. When a full path is provided, it is used as the Go module path and the last segment becomes the project directory name.

Flags

FlagDefaultDescription
--driverpostgresDatabase driver: postgres | mysql | sqlite | sqlserver | clickhouse. See --driver for the full per-driver breakdown.
--graphqlfalseInclude GraphQL support (gqlgen schema, resolvers, /graphql endpoint, playground). See --graphql / --gql.
--gqlfalseAlias for --graphql
--layoutlayeredProject layout: layered | feature. Persisted to config.yaml’s project.layout; read by every subsequent gofasta g * and gofasta refactor command. See --layout below.

--layout

Picks the project layout the scaffold writes — layered (the historical default) or feature (the feature-package layout). The choice is persisted to config.yaml’s project.layout field so every subsequent generator emits files in the right shape automatically.

gofasta new my-app # layered (default) gofasta new my-app --layout=layered # same as above, explicit gofasta new my-app --layout=feature # feature-package

Both produce a project that compiles, runs, and passes its tests out of the box. The two ship the same packages, the same wire bindings, the same HTTP routes — they differ only in how files are organized on disk.

Layered (--layout=layered) puts each layer in its own directory. All controllers under app/rest/controllers/, all services under app/services/, all models under app/models/. Adding a Subscription resource touches one file in each of those directories.

app/ ├── models/user.model.go ├── dtos/{aliases.go, user.dtos.go} ├── repositories/{interfaces/, user.repository.go} ├── services/{interfaces/, user.service.go, user_errors.go, user_inputs.go, password_generator.go} ├── rest/{controllers/user.controller.go, routes/user.routes.go, routes/index.routes.go} ├── validators/{app_validator.go, user.validators.go, register.go, ...} ├── di/{container.go, wire.go, providers/{core.go, user.go}} ├── jobs/ └── tasks/

Feature-package (--layout=feature) groups files by business domain. Everything the User feature needs is in app/user/. Adding a Subscription resource creates one directory.

app/ ├── models/user.model.go # ← stays layered (model never moves) ├── shared/dtos/aliases.go # ← shared envelopes relocated here ├── user/ # ← per-feature directory │ ├── dtos.go │ ├── repository.go + repository_iface.go │ ├── service.go + service_iface.go │ ├── errors.go │ ├── inputs.go │ ├── controller.go │ ├── routes.go # exports RegisterRoutes(...) │ ├── wire.go # exports UserSet │ └── password_generator.go # only consumer is User ├── validators/ # ← per-resource validators stay (shared infra) ├── di/{container.go, wire.go, providers/core.go} ├── rest/routes/index.routes.go ├── jobs/ └── tasks/

The feature-package layout is a hybrid — most per-resource files collapse into the feature directory, but a few categories stay in their layered locations for technical reasons (models, shared validator infrastructure, cross-cutting wiring). See Project structure → What moves and what doesn’t for the full breakdown.

Picking a layout

Use layered if…Use feature if…
Your project has <10 resourcesYour project has 15+ resources
Team comes from layered MVC backgroundsYou’re planning to extract microservices later
You haven’t felt pain from the current shapeMultiple teams step on each other in shared layer dirs
You prefer dense, flat directory listingsYou want ls app/ to read like a domain model

Both layouts are legitimate. You can switch later with gofasta refactor — it works bidirectionally.

What the scaffold persists

Both --layout values write a project section to the generated config.yaml:

project: layout: layered # or: feature

Don’t edit this field by hand after creation. It must agree with the filesystem shape. The CLI reads it on every gofasta g * invocation to know how to emit new resources, and gofasta refactor is the only command that should write to it (the refactor changes both the value and the on-disk shape together).

After scaffolding

Every generator is layout-aware — you never specify --layout again:

# In a layered project gofasta g scaffold Product name:string price:float # → app/models/product.model.go # → app/services/product.service.go # → app/repositories/product.repository.go # → app/rest/controllers/product.controller.go # → ... etc. # In a feature project — same command, different output shape gofasta g scaffold Product name:string price:float # → app/models/product.model.go (model stays layered) # → app/product/service.go # → app/product/repository.go # → app/product/controller.go # → app/product/routes.go # → app/product/wire.go # → ... etc.

See Code Generation for the per-generator path matrix.

Flag references

Each flag has a dedicated reference page with examples, edge cases, and per-driver details:

  • --driver — pick the database engine (5 supported drivers; default postgres)
  • --graphql / --gql — add GraphQL alongside REST

Without --graphql, the generated project is REST-only — no GraphQL files, no gqlgen dependency, and no /graphql routes. Without --driver, the project is wired for Postgres — compose.yaml ships postgres:18-alpine, config.yaml is preset to driver: postgres, and db/migrations/ contains the Postgres-flavored foundational migrations.

Examples

Create a project with a simple name:

gofasta new myapp

Create a project with a full Go module path:

gofasta new github.com/myorg/myapp

Create a project with GraphQL support:

gofasta new myapp --graphql

Create a MySQL-backed project:

gofasta new myapp --driver mysql

Combine flags (a SQLite + GraphQL project):

gofasta new myapp --driver sqlite --graphql

What It Does

When you run gofasta new myapp, the CLI performs the following steps in order:

  1. Create project directory — creates the myapp/ directory
  2. Initialize Go module — runs go mod init with the appropriate module path
  3. Copy skeleton files — writes template files into the project, including a starter User resource
  4. Install Gofasta and Cobra — runs go get for the gofasta library at the exact version pinned by the CLI release (the version its templates were tested against) and go get github.com/spf13/cobra@latest to add them to go.mod
  5. Install tools — runs go get to add tool dependencies (wire, air, swag) and go mod edit -tool for each. If --graphql is passed, gqlgen is also installed.
  6. Tidy modules — runs go mod tidy to synchronize dependencies
  7. Generate Wire DI code — runs go tool wire ./app/di/ to generate the dependency injection container
  8. Generate GraphQL code (only with --graphql) — runs go tool gqlgen generate to create Go types and resolvers from the GraphQL schema
  9. Initialize Git — runs git init and creates an initial commit

What It Generates

Running gofasta new myapp produces the following project structure. Items marked (—graphql only) are only included when the --graphql flag is passed:

myapp/ cmd/ serve.go # HTTP server entry point app/ models/ # GORM database models user.model.go repositories/ # Data access layer interfaces/ user_repository.go user.repository.go services/ # Business logic layer interfaces/ user_service.go auth_service.go user.service.go auth.service.go rest/ controllers/ # REST API controllers user.controller.go auth.controller.go routes/ # Route definitions index.routes.go user.routes.go auth.routes.go middlewares/ # HTTP middlewares auth.middleware.go casbin.middleware.go dtos/ # Request/response DTOs user.dtos.go auth.dtos.go di/ # Dependency injection (Google Wire) container.go wire.go providers/ user.go auth.go graphql/ # GraphQL schema and resolvers (--graphql only) schema/ # .gql schema files (common, user, server.health) resolvers/ # resolver.go + per-schema *.resolvers.go + helpers jobs/ # Background jobs tasks/ # Scheduled tasks (cron) emails/ # Email templates db/ migrations/ # SQL migration files (up/down) seeders/ # Database seed files config/ config.yaml # Application configuration docker-compose.yml # Docker Compose for app + database Dockerfile # Multi-stage Docker build Makefile # Common development commands .github/ workflows/ # CI/CD pipeline definitions .air.toml # Air hot reload configuration .env.example # Environment variable template gqlgen.yml # gqlgen GraphQL configuration (--graphql only) go.mod go.sum

Architecture

The generated project’s request flow is identical regardless of --layout — every request travels the same chain of objects:

Controller --> Service --> Repository --> Database
  • Controllers parse the HTTP request, validate input, delegate to services, and shape the response.
  • Services hold business logic, translate between wire DTOs and domain inputs, and call repositories.
  • Repositories handle data access via GORM with optimistic locking baked into update operations.
  • DI Container wires the dependencies at compile time via Google Wire — there are no runtime reflection-based DI lookups.

The two --layout values differ in how the per-resource Go files are organized on disk, not in the request flow:

  • --layout=layered (default) — files grouped by technical role. app/models/, app/services/, app/repositories/, app/rest/controllers/, app/rest/routes/, etc. One file per resource in each directory.
  • --layout=feature — files grouped by business domain. app/user/ contains the user feature’s service, repository, controller, routes, DTOs, and Wire provider. Per Project structure → What stays put in feature-package layout, four categories stay in their layered locations even in feature mode (models, per-resource validators, validator infrastructure, the Validator interface) — see that section for the full rationale.

Both layouts ship the same Wire dependency graph, the same HTTP middleware stack, the same migration model, and the same generated tests. You can switch between them at any time with gofasta refactor feature or gofasta refactor layered.

Last updated on