Skip to content

Getting Started ​

This page walks through creating a craftgo project, defining one endpoint, and running it. About 5 minutes.

Prerequisites ​

  • Go 1.26 or later
  • A terminal

Install the CLI ​

bash
go install github.com/craftgodotdev/craftgo/cmd/craftgo@latest

Verify:

bash
craftgo --help

Create a project ​

bash
mkdir hello && cd hello
go mod init example.com/hello
go get github.com/craftgodotdev/craftgo

Scaffold the design folder ​

bash
craftgo init design

This creates design/craftgo.design.yaml with default settings. Then write a .craftgo file:

design/users/service.craftgo:

craftgo
package design

type CreateUserReq {
    name  string @length(1, 80)
    email string @format(email)
}

type User {
    id    string
    name  string
    email string
}

@prefix("/v1")
service UserService {
    post CreateUser /users {
        request  CreateUserReq
        response User
    }
}

Folder layout so far:

hello/
├── design/
│   ├── craftgo.design.yaml
│   └── users/
│       └── service.craftgo
├── go.mod
└── go.sum

Generate ​

bash
craftgo gen design
go mod tidy

The CLI walks up from the given path looking for craftgo.design.yaml, reads go.mod for the Go module path, then writes the files below; go mod tidy then adds the modules the generated code imports:

hello/
├── design/...                                  (your DSL, unchanged)
├── internal/
│   ├── types/design/                           generated structs + Validate()
│   │   ├── types.go
│   │   └── validate.go
│   ├── transport/user_service/                 generated HTTP handlers
│   │   └── create_user.go
│   ├── service/user_service/                   gen-once business logic stubs
│   │   └── create_user.go
│   ├── routes/                                 generated routing
│   │   ├── routes.go
│   │   └── user_service/routes.go
│   └── wiring/wiring.go                        the one call main.go makes
├── svccontext/
│   ├── svccontext.go                           gen-once dependency container
│   └── middlewares.go                          generated middleware fields
├── config/                                     gen-once runtime config
│   ├── config.go
│   ├── config.yaml
│   └── example.config.yaml
├── docs/openapi.yaml                           generated OpenAPI 3.1 spec
├── main.go                                     gen-once entry point
└── go.mod

Implement business logic ​

Open internal/service/user_service/create_user.go:

go
func (l *CreateUserService) CreateUser(req *types.CreateUserReq) (*types.User, error) {
    return &types.User{
        ID:    "u1",
        Name:  req.Name,
        Email: req.Email,
    }, nil
}

This is the only file you edit. Everything else under internal/ is regenerated - see Architecture for the split.

Run ​

bash
go run .
{"level":"info","ts":…,"caller":"hello/main.go:49","msg":"metrics scrape listening","url":"[::]:9090/metrics"}
{"level":"info","ts":…,"caller":"hello/main.go:128","msg":"listening","addr":"[::]:8080"}

In another terminal:

bash
curl -X POST http://localhost:8080/api/v1/users \
  -H "Content-Type: application/json" \
  -d '{"name":"alice","email":"alice@example.com"}'
json
{"id":"u1","name":"alice","email":"alice@example.com"}

(/api comes from openapi.basePath: /api in craftgo.design.yaml; /v1 from @prefix("/v1") in the DSL.)

Try a bad payload:

bash
curl -X POST http://localhost:8080/api/v1/users \
  -H "Content-Type: application/json" \
  -d '{"name":"","email":"not-an-email"}'
json
{"message":"name: length out of range [1, 80]"}

The status is 400. Validate() is fail-fast - it returns the first violation (here name), so fixing one surfaces the next. The validators run without you writing any code.

What just happened ​

One DSL file gives typed structs, an HTTP handler, a logic stub, route registration and an OpenAPI spec; you fill the stub, and the handler decodes, validates, dispatches and encodes around it.

No reflection-based binding or validation, no struct tags to write, no middleware boilerplate. The handler is a plain http.HandlerFunc registered on *http.ServeMux.

Designing with an LLM? ​

If you draft .craftgo files with Claude, ChatGPT, Cursor, or any other LLM, paste this URL into your prompt:

https://craftgodotdev.github.io/craftgo/llms

It is a single-page consolidated reference (every keyword, decorator, CLI flag, and generated layout) designed for AI ingestion. Your assistant will know the full spec and stop inventing non-existent decorators.

Next steps ​

  • Read Architecture for how the design, the generated code and the runtime fit together.
  • Read DSL Basics to learn the syntax in depth.
  • Browse Decorators to see every decorator with arguments and sites.
  • Install the VS Code extension (search "craftgo" in the Extensions panel) - or set up the LSP for another editor - for completion, hover, and live diagnostics.
  • See Configuration to relocate generated files or add custom config.

Released under the MIT License.