# golang-standards/project-layout — Content Guide

> `golang-standards/project-layout` is the community-maintained reference for conventional Go project directory structure. It defines a set of directory names — each with a `README.md` explaining its purpose and when to use it — that Go developers can treat as a template when starting a new application, service, or library. No application code is prescribed; the repository IS the documentation. It ships in the canonical English `README.md` plus 19 translations, making the conventions accessible to the global Go community.

---

## What's in This Collection

| Item | Path(s) | Description |
|------|---------|-------------|
| Canonical English reference | `README.md` | Primary layout guide — describes every directory, its purpose, real-world usage notes, and when to skip |
| Translations | `README_be.md`, `README_bn.md`, `README_es.md`, `README_fa.md`, `README_fr.md`, `README_hi.md`, `README_id.md`, `README_it.md`, `README_ja.md`, `README_ko.md`, `README_ptBR.md`, `README_ro.md`, `README_ru.md`, `README_tr.md`, `README_ua.md`, `README_vi.md`, `README_zh-CN.md`, `README_zh-TW.md`, `README_zh.md` | 19 community-maintained translations of the main guide |
| Directory stub READMEs | `api/README.md`, `assets/README.md`, `cmd/README.md`, `configs/README.md`, `deployments/README.md`, `docs/README.md`, `examples/README.md`, `githooks/README.md`, `init/README.md`, `internal/README.md`, `pkg/README.md`, `scripts/README.md`, `test/README.md`, `tools/README.md`, `web/README.md`, `website/README.md` | Per-directory descriptions; each explains that directory's role and links to real-world examples in major Go projects |
| Placeholder module file | `go.mod` | Declares `module github.com/YOUR-USER-OR-ORG-NAME/YOUR-REPO-NAME` with `go 1.19` — a copy/paste starting point |
| Placeholder directory stubs | `cmd/_your_app_/`, `internal/app/_your_app_/`, `internal/pkg/_your_private_lib_/`, `pkg/_your_public_lib_/` | `.keep` files holding the directory shape; rename or delete in actual projects |
| Root config starters | `Makefile`, `.editorconfig`, `.gitignore`, `.gitattributes` | Minimal top-level files included as a starter; not prescriptive |
| License | `LICENSE.md` | Informal one-line "Hacker license!" — not a standard OSI license |

> [!NOTE]
> This repository contains **zero application source code** — `total_source_chars: 0`. Every file is documentation, configuration metadata, or an empty directory placeholder. When you clone it as a template, you replace the stubs with your own code.

---

## How to Read / Use This

### Intended audience

Go developers starting a new project (application, service, library) who want a community-backed directory convention rather than inventing structure from scratch. Architects reviewing an existing codebase against common Go conventions also use this as a benchmark.

### How to navigate

The collection is **not linear**. Read the canonical `README.md` top to bottom once to understand the full layout and the rationale for each directory. After that, treat the per-directory `README.md` files as reference cards — jump to whichever directory you're deciding about.

**Entry points by reader type:**

| Reader | Start here |
|--------|-----------|
| Starting a new Go application | `README.md` — read the "Go App Directories" section first (`/cmd`, `/internal`, `/pkg`) |
| Adding a service API | `api/README.md` |
| Setting up CI/CD or container deployments | `deployments/README.md` |
| Adding scripts or a build system | `scripts/README.md` and `Makefile` at repo root |
| Hosting project documentation | `docs/README.md` and `website/README.md` |
| Non-English readers | The matching `README_*.md` translation at repo root |

> [!TIP]
> You do not need to use every directory in the layout. The README explicitly calls out which directories are optional and which are used only by specific project types (e.g., `/web` is only for web applications, `/init` only for projects that ship service manager configs).

### Using the repo as a project template

The repository is designed to be cloned and stripped down:

```bash
git clone https://github.com/golang-standards/project-layout.git my-new-project
cd my-new-project
rm -rf .git
git init
```

After cloning, delete every directory you don't need and rename the `_your_app_` / `_your_public_lib_` / `_your_private_lib_` placeholder stubs to match your actual package names.

> [!IMPORTANT]
> Update `go.mod` immediately after cloning. The placeholder `module github.com/YOUR-USER-OR-ORG-NAME/YOUR-REPO-NAME` will cause build failures if left unchanged. Replace it with your real module path before writing any Go code.

---

## Section Walkthroughs

### Go Application Directories

These are the most important directories in the layout — the directories any Go application is likely to need.

#### `/cmd`

The entry point for each binary in the repository. Each subdirectory of `/cmd` maps 1:1 to an executable name (e.g., `cmd/myapp/` produces the `myapp` binary). The `cmd/_your_app_/` stub in this repo is a `.keep` placeholder — rename it to your binary name.

The code inside each `/cmd` subdirectory should be minimal: import and call functions from `/internal` and `/pkg`, but avoid putting significant logic here. This keeps the entry point thin and testable business logic in proper packages.

> [!TIP]
> It is common to have multiple binaries in one repo (e.g., `cmd/server/`, `cmd/cli/`, `cmd/worker/`). Each gets its own subdirectory under `/cmd` and its own `main.go`.

#### `/internal`

Private application and library code. The Go compiler enforces this privacy: no external module can import from your `/internal` packages. This is the primary location for business logic, domain models, and application-specific code that should not become a public API.

The layout further subdivides `/internal`:

- `internal/app/_your_app_/` — application-specific logic that is not shared across binaries
- `internal/pkg/_your_private_lib_/` — shared private library code reused across multiple binaries in the same repo

#### `/pkg`

Library code that is safe and intentional to share with external applications. Packages placed here declare "this is a public API — other repos may import and depend on it." Use this directory only for code you want to be importable externally. The `pkg/_your_public_lib_/` stub is a `.keep` placeholder.

> [!WARNING]
> Do not put everything in `/pkg` just to avoid importing from `/internal`. If code is internal to your application, put it in `/internal` and let the compiler enforce the boundary. Misusing `/pkg` as a catch-all makes API guarantees meaningless.

---

### Service Application Directories

#### `/api`

Protocol and schema definitions: OpenAPI/Swagger specs, JSON Schema files, Protocol Buffer definitions (`.proto`), Thrift IDL files. The descriptions for the API live here, not the server implementation.

---

### Web Application Directories

#### `/web`

Web application specific components, divided into three conventional subdirectories:

- `web/app/` — single-page application (SPA) JavaScript frontend; the `.keep` stub marks the directory
- `web/static/` — static assets served directly (CSS, images, fonts); the `.keep` stub marks the directory
- `web/template/` — server-side Go templates (`html/template`, `text/template`); the `.keep` stub marks the directory

The `web/README.md` describes the purpose of this top-level grouping.

---

### Common Application Directories

#### `/configs`

Configuration file templates or default configuration files. Specifically, this is where `confd` or `consul-template` template files live. For projects shipping a default `config.yaml` or environment-specific overrides, put them here.

#### `/init`

System init (`systemd`, `upstart`, `sysv`) and process manager/supervisor (`runit`, `supervisord`) configuration files. Used only when a project ships service definitions intended to be installed on a server.

#### `/scripts`

Scripts that perform build, install, analysis, and other operations. The directory keeps the root-level `Makefile` small and simple by delegating longer operations to scripts.

```text
scripts/
├── build.sh
├── test.sh
└── lint.sh
```

Real-world examples cited in `scripts/README.md`:
- `kubernetes/helm` — `scripts/`
- `cockroachdb/cockroach` — `scripts/`
- `hashicorp/terraform` — `scripts/`

#### `/build`

Not represented by a stub in this repo, but described in the main README: packaging and Continuous Integration. Put cloud, container, OS packaging configs (`Dockerfile`, RPM specs, `.deb` manifests) in `/build/package/`. Put CI configs for Travis CI, CircleCI, Drone, etc. in `/build/ci/`.

#### `/deployments`

IaaS, PaaS, system and container orchestration deployment configs. Includes `docker-compose`, Kubernetes/Helm charts, Mesos, Terraform, Bosh manifests. Some repos use `/deploy/` instead.

> [!NOTE]
> The community actively discusses where to place Helm charts (GitHub issue #137). The `/deployments` directory is the layout's answer, though some large projects use a dedicated `/charts` subdirectory within it.

#### `/test`

Additional external test apps and test data. You can structure `/test` freely. For larger projects it makes sense to use `/test/data` or `/test/testdata` — Go ignores any directory beginning with `.` or `_`, giving flexibility in naming test data.

Real-world example cited in `test/README.md`: `openshift/origin/test` (with test data in `/testdata` subdirectory).

---

### Other Directories

#### `/docs`

Design documents, user documentation, and architectural decision records — material beyond what `godoc` auto-generates from source comments. Place design specs, ADRs, user-facing guides, and diagrams here.

Real-world examples cited in `docs/README.md`:
- `gohugoio/hugo/docs`
- `openshift/origin/docs`
- `dapr/dapr/docs`

#### `/tools`

Supporting tools for the project that are not meant to be user-facing binaries. Tools here can import code from `/pkg` and `/internal`.

Real-world examples cited in `tools/README.md`:
- `istio/istio/tools`
- `openshift/origin/tools`
- `dapr/dapr/tools`

#### `/examples`

Example applications and usage demonstrations for public libraries or applications. Intended to show consumers of `/pkg` how to integrate with your library.

#### `/githooks`

Git hooks for the project — scripts invoked by Git before or after events (`pre-commit`, `pre-push`, etc.). Developers must install these manually or via a setup script; Git does not install hooks from a repo's `githooks/` directory automatically.

#### `/assets`

Other repository assets that accompany the code: images, logos, diagrams, and similar binary assets referenced by the README or documentation.

From `assets/README.md`:
> "Other assets to go along with your repository (images, logos, etc)."

#### `/website`

Project website data when GitHub Pages is not used. Place your project's static site source here.

#### `/vendor`

Not represented as a stub directory, but described in the main README as optional. Contains application dependencies managed with `go mod vendor`. Modern Go projects use the module cache (`GOPATH/pkg/mod`) rather than a local `/vendor` directory; use `/vendor` if your build environment requires offline or reproducible vendored builds.

---

### Root-Level Files

| File | Purpose |
|------|---------|
| `README.md` | Canonical English layout guide (the primary document) |
| `README_*.md` | 19 community translations |
| `go.mod` | Placeholder module declaration — `module github.com/YOUR-USER-OR-ORG-NAME/YOUR-REPO-NAME`, `go 1.19` |
| `Makefile` | Starter build targets; delegates to `scripts/` |
| `.editorconfig` | Code style settings for editors that support it |
| `.gitignore` | Standard Go gitignore |
| `.gitattributes` | Git attribute settings |
| `LICENSE.md` | Contains a single informal line, `Hacker license!` — not a standard OSI-approved license |

---

## Contributing / Extending

The repository accepts contributions primarily as: additions or corrections to the per-directory `README.md` files, new translation files (`README_*.md`), and updates to existing translations. Open issues are actively tracked for translation sync (e.g., issue #274 tracks Simplified Chinese), grammar corrections (issues #284, #271), and content debates (issue #278 on tone).

> [!NOTE]
> Translation contributions follow the naming convention `README_{language-code}.md`. Language codes used in the repository: `be` (Belarusian), `bn` (Bengali), `es` (Spanish), `fa` (Farsi), `fr` (French), `hi` (Hindi), `id` (Indonesian), `it` (Italian), `ja` (Japanese), `ko` (Korean), `ptBR` (Brazilian Portuguese), `ro` (Romanian), `ru` (Russian), `tr` (Turkish), `ua` (Ukrainian), `vi` (Vietnamese), `zh-CN` (Simplified Chinese), `zh-TW` (Traditional Chinese), `zh` (Chinese).

When proposing a **new directory name** or changing existing guidance, open a GitHub issue for community discussion first. The layout is intentionally stable; changes require broad consensus.

---

## FAQ

**Q: Do I have to use all these directories?**

No. Many of them are optional. Use only the directories your project actually needs. A small library might only need `/pkg` and a root `README.md`. A large microservice might use `/cmd`, `/internal`, `/api`, `/deployments`, and `/scripts`. Delete what you don't need when using this repo as a template.

**Q: Where do I put Helm charts?**

Community issue #137 discusses this. The conventional answer is `/deployments` (or a subdirectory like `/deployments/helm/`). Some large projects create a top-level `/charts` directory instead. Neither is wrong; pick one and stay consistent.

**Q: Where do I put generated code?**

Community issue #283 raises this. There is no single prescribed location. Common patterns are a `/gen` or `/generated` subdirectory, or keeping generated files alongside their templates. The layout does not mandate a specific location for generated code.

**Q: Where do I put SQL migrations, localization files, or mail templates?**

Community issue #11 covers this. The layout does not prescribe a specific location. Common practice is a top-level `/migrations` directory for SQL migrations, `/locales` for i18n files, and placing mail templates under `/internal` or `/assets` depending on whether they're app-specific or public-facing.

**Q: Why use a Makefile?**

Community issue #279 asks this. The Makefile at repo root serves as a task runner — `make build`, `make test`, `make lint` — with the actual logic delegated to `scripts/`. This avoids cross-platform incompatibilities in the root Makefile itself while keeping a single well-known entry point for common operations.

**Q: Why are some directories plural and some singular?**

Community issues #187 and #218 discuss this. Go's own standard library and most major Go projects use plural for directories containing multiple items (`/docs`, `/scripts`, `/tools`) and singular for those with special toolchain meaning (`/cmd`, `/pkg`, `/api`). The inconsistency reflects organic community convention rather than a deliberate rule.

**Q: Where do I put auxiliary tool configuration files (`.golangci.yml`, `buf.gen.yaml`, etc.)?**

Community issue #256 addresses this. The layout does not prescribe a location. Repository root and `/configs` are both commonly used. Putting toolchain config at root is most common because many tools look there by default.

**Q: How do I debug a project using this structure in VS Code?**

Community issue #215 covers this. For a project with binaries in `cmd/myapp/`, create a VS Code launch configuration in `.vscode/launch.json` that sets `"program": "${workspaceFolder}/cmd/myapp"`. The `.vscode/` directory sits at repo root (it is not prescribed by this layout) and is typically added to `.gitignore`.

> [!TIP]
> The `/.vscode` directory is not part of the golang-standards layout but is safely co-located with it. Add `.vscode/` to your `.gitignore` if the IDE config should not be tracked, or commit it if your team wants a shared debug configuration.

---

## Related Resources

The directory READMEs throughout this repo reference real-world examples from major Go projects. Frequently cited repositories:

| Project | Used as example for |
|---------|-------------------|
| `kubernetes/helm` | `/scripts` layout |
| `cockroachdb/cockroach` | `/scripts` layout |
| `hashicorp/terraform` | `/scripts` layout |
| `openshift/origin` | `/scripts`, `/test`, `/docs` layouts |
| `gohugoio/hugo` | `/docs` layout |
| `dapr/dapr` | `/docs`, `/tools` layouts |
| `istio/istio` | `/tools` layout |

For Go module conventions referenced by `go.mod`, see the official [Go Modules Reference](https://go.dev/ref/mod). For documentation generation from Go source comments, see [godoc](https://pkg.go.dev/golang.org/x/tools/cmd/godoc).

---

_Generated June 2026 from golang-standards/project-layout at a9d6fae. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
