App Repo Layout#

This page describes the directory structure of an APX app repository β€” where files live, what each configuration file does, and how generated code and overlays fit into the tree.

Complete Directory Structure#

<app-repo>/
β”œβ”€β”€ go.mod                          # your application module
β”œβ”€β”€ go.sum                          # Go checksum database
β”œβ”€β”€ go.work                         # managed by apx sync β€” overlays canonical β†’ local
β”œβ”€β”€ apx.yaml                       # APX configuration (identity, release, policy)
β”œβ”€β”€ apx.lock                       # pinned toolchain and dependency versions
β”œβ”€β”€ buf.yaml                       # Buf lint and breaking-change policy
β”œβ”€β”€ buf.gen.yaml                   # Buf code generation plugin config
β”œβ”€β”€ buf.work.yaml                  # Buf workspace β€” aggregates version dirs
β”œβ”€β”€ .gitignore                     # must exclude internal/gen/ and .apx-tools/
β”œβ”€β”€ .github/
β”‚   └── workflows/
β”‚       └── apx-release.yml        # CI workflow for tag-triggered releasing
β”œβ”€β”€ internal/
β”‚   β”œβ”€β”€ apis/                      # schema source files (committed)
β”‚   β”‚   └── proto/
β”‚   β”‚       └── payments/
β”‚   β”‚           └── ledger/
β”‚   β”‚               β”œβ”€β”€ v1/
β”‚   β”‚               β”‚   └── ledger.proto
β”‚   β”‚               └── v2/        # future breaking version line
β”‚   β”‚                   └── ledger.proto
β”‚   β”œβ”€β”€ gen/                       # generated code (git-ignored, never committed)
β”‚   β”‚   β”œβ”€β”€ go/
β”‚   β”‚   β”‚   └── proto/payments/ledger@v1.2.3/
β”‚   β”‚   β”‚       β”œβ”€β”€ go.mod         # module github.com/<org>/apis/proto/payments/ledger
β”‚   β”‚   β”‚       └── v1/
β”‚   β”‚   β”‚           β”œβ”€β”€ ledger.pb.go
β”‚   β”‚   β”‚           └── ledger_grpc.pb.go
β”‚   β”‚   β”œβ”€β”€ python/
β”‚   β”‚   β”‚   └── proto/payments/ledger/
β”‚   β”‚   β”‚       └── ledger_pb2.py
β”‚   β”‚   └── java/
β”‚   β”‚       └── proto/payments/ledger/
β”‚   β”‚           └── LedgerServiceGrpc.java
β”‚   └── service/                   # your application code
β”‚       └── payment_service.go     # imports canonical paths
β”œβ”€β”€ cmd/
β”‚   └── server/
β”‚       └── main.go                # imports github.com/<org>/apis/proto/payments/ledger/v1
β”œβ”€β”€ .apx-tools/                    # cached toolchain binaries (git-ignored)
β”‚   β”œβ”€β”€ buf
β”‚   └── protoc-gen-go
└── Makefile                       # optional β€” can wrap apx commands

Top-Level Files#

apx.yaml#

The primary APX configuration file. Created by apx init app and committed to the repo.

version: 1
org: <org>
repo: <app-repo>
# import_root: go.<org>.dev/apis   # optional: custom Go import prefix
module_roots:
  - internal/apis/proto

api:
  id: proto/payments/ledger/v1
  format: proto
  domain: payments
  name: ledger
  line: v1
  lifecycle: beta              # experimental β†’ beta β†’ stable β†’ deprecated β†’ sunset

source:
  repo: github.com/<org>/apis
  path: proto/payments/ledger/v1

releases:
  current: v1.0.0-beta.1

languages:
  go:
    module: github.com/<org>/apis/proto/payments/ledger
    import: github.com/<org>/apis/proto/payments/ledger/v1

language_targets:
  go:
    enabled: true
    plugins:
      - name: protoc-gen-go
        version: v1.64.0
      - name: protoc-gen-go-grpc
        version: v1.5.0

release:
  tag_format: "{subdir}/v{version}"
  ci_only: true

Most fields after api.id, source.repo, and api.lifecycle are derived automatically by apx init app or apx identity. They are shown here for reference. When import_root is set, Go module and import paths use the custom root instead of source.repo.

apx.lock#

Pins exact versions and checksums for every tool and dependency. Created on first apx fetch or apx add, and should be committed.

version: 1
toolchains:
  buf:
    version: v1.50.0
    checksum: sha256:abc123...
  protoc-gen-go:
    version: v1.64.0
    checksum: sha256:def456...
dependencies:
  proto/users/profile/v1:
    repo: github.com/<org>/apis
    ref: proto/users/profile/v1/v1.0.1
    modules:
      - proto/users/profile

buf.yaml#

Buf linting and breaking-change policy for protobuf schemas:

version: v1
name: buf.build/<org>/<app-repo>
lint:
  use:
    - DEFAULT
  except:
    - UNARY_RPC
breaking:
  use:
    - FILE

buf.gen.yaml#

Buf code generation plugin configuration:

version: v1
plugins:
  - plugin: buf.build/protocolbuffers/go
    out: gen/go
    opt: paths=source_relative
  - plugin: buf.build/grpc/go
    out: gen/go
    opt: paths=source_relative

Note

During apx gen go, APX uses the overlay manager rather than raw buf generate to ensure the generated code has canonical module paths and go.mod files. The buf.gen.yaml configuration is used as input but the output location is managed by APX.

buf.work.yaml#

Buf workspace that aggregates all version directories:

version: v1
directories:
  - internal/apis/proto/**/v1
  - internal/apis/proto/**/v2

go.work#

Managed by apx sync. Maps canonical module paths to local overlay directories:

go 1.22
use .
use ./internal/gen/go/proto/payments/ledger@v1.2.3
use ./internal/gen/go/proto/users/profile@v1.0.1

Warning

Do not edit go.work manually. Use apx sync to regenerate it. CI environments regenerate it from apx.lock via apx gen go && apx sync.

.gitignore#

Must exclude generated code and cached tools:

# APX generated code β€” regenerated from apx.lock
internal/gen/

# APX toolchain cache
.apx-tools/

# Go workspace β€” regenerated by apx sync
go.work
go.work.sum

Source Schemas β€” internal/apis/#

Schema source files are the only files you author directly. They live under internal/apis/ organized by format, domain, name, and version line:

internal/apis/
└── proto/
    └── payments/
        └── ledger/
            β”œβ”€β”€ v1/
            β”‚   β”œβ”€β”€ ledger.proto         # service + messages
            β”‚   └── types.proto          # shared types
            └── v2/                      # separate version line
                └── ledger.proto

Convention:

  • internal/ prevents Go from vendoring schema directories

  • Format directories (proto/, openapi/, avro/, etc.) match the canonical repo layout

  • Version directories (v1/, v2/) separate breaking API lines

  • Schema files set go_package to the canonical import path

Supported Formats#

Format

Directory

File Extensions

Protocol Buffers

proto/

.proto

OpenAPI

openapi/

.yaml, .json

Avro

avro/

.avsc

JSON Schema

jsonschema/

.json

Parquet

parquet/

.parquet


Generated Code β€” internal/gen/#

Generated code lives under internal/gen/, organized by language. This entire directory is git-ignored β€” it is regenerated from apx.lock by running apx gen <lang>.

Go Overlays#

Go overlays include a synthesized go.mod with the canonical module path, enabling go.work resolution:

internal/gen/go/
└── proto/payments/ledger@v1.2.3/
    β”œβ”€β”€ go.mod                       # module github.com/<org>/apis/proto/payments/ledger
    └── v1/
        β”œβ”€β”€ ledger.pb.go             # package ledgerv1
        └── ledger_grpc.pb.go        # gRPC stubs

The @v1.2.3 suffix in the directory name is the pinned version from apx.lock. It ensures that different versions of the same API don’t collide.

Other Languages#

Non-Go languages use their own resolution mechanisms and don’t need go.mod or go.work entries:

internal/gen/python/proto/payments/ledger/
└── ledger_pb2.py

internal/gen/java/proto/payments/ledger/
└── LedgerServiceGrpc.java

Toolchain Cache β€” .apx-tools/#

apx fetch downloads pinned tool versions into .apx-tools/. This directory is git-ignored:

.apx-tools/
β”œβ”€β”€ buf                    # Buf CLI
β”œβ”€β”€ protoc-gen-go          # Go protobuf plugin
└── protoc-gen-go-grpc     # Go gRPC plugin

Versions and checksums are recorded in apx.lock, ensuring all team members and CI use identical toolchains.


CI Workflows β€” .github/workflows/#

apx-release.yml#

Generated by apx workflows sync. Triggered when you push a tag matching the configured tag_format:

.github/workflows/
└── apx-release.yml        # tag-triggered: validates β†’ opens PR to canonical repo

See CI Integration for details on the workflow contents and triggers.


Comparison with Canonical Repo#

Aspect

App Repo

Canonical Repo

Schemas

internal/apis/proto/...

proto/... (top-level)

go.mod

App module (go.mod) + overlays (internal/gen/)

Per-API go.mod at each module root

go.work

Yes β€” maps overlays to canonical paths

Not used

Generated code

internal/gen/ (git-ignored)

Not present β€” consumers generate from released schemas

Config

apx.yaml + apx.lock

apx.yaml + catalog/catalog.yaml

CI

apx-release.yml

ci.yml + on-merge.yml

Buf config

buf.yaml + buf.gen.yaml + buf.work.yaml

buf.yaml + buf.work.yaml


Bootstrapping#

To create this layout from scratch:

cd /path/to/your-app-repo

# Initialize β€” creates apx.yaml, buf configs, schema dirs, .gitignore entries
apx init app --org=<org> --repo=<app-repo> internal/apis/proto/payments/ledger

# Download pinned toolchain
apx fetch

# Generate code and sync overlays
apx gen go && apx sync

See Quickstart for a complete walkthrough.

Next Steps#