Jesse A. Green / notebook

Live demo: the DocCompiler guide library as a static, read-only snapshot (October 2026). No backend, no accounts, nothing to submit.

golang-standards/project-layout — Content Guide

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.

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:

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.

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.


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. For documentation generation from Go source comments, see godoc.