Shape: Single Repo
A single-repo project has one language, one deployable unit, and one directory of source code. This is the simplest project shape and needs the least configuration.
When this shape applies
Use the single-repo shape when your project is:
- A backend service in one language (Python, Go, Java, Rust, etc.).
- A command-line tool.
- A library or SDK published to a package registry.
- A web application built with a server-rendered framework (Rails, Django, Laravel, Phoenix).
- A mobile app in a single framework (Flutter, React Native, SwiftUI, Kotlin).
If your project has a separate frontend and backend, see Shape: Full-Stack instead.
Folder layout
A typical single-repo project looks like this:
my-project/
.gaia/
config/
project-config.yaml
docs/
planning-artifacts/
implementation-artifacts/
src/ # (or lib/, app/, cmd/ -- depends on the language)
tests/ # (or test/, spec/, __tests__/)
package.json # (or pyproject.toml, go.mod, Cargo.toml, etc.)
README.md
The key point: there is one source directory and one test directory.
GAIA's stacks configuration has a single entry.
Configuration
Here is a complete project-config.yaml for a single-repo
project. This example uses a Node.js service, but the structure is
the same for any language.
# .gaia/config/project-config.yaml
project:
name: my-service
description: A REST API for managing widgets
stacks:
- name: api
language: typescript
framework: express
path: .
test_command: npm test
build_command: npm run build
lint_command: npm run lint
platforms:
- web
ci_cd:
platform: github-actions
preset: small-team
promotion_chain:
- staging
- production
environments:
staging:
url: https://staging.my-service.example.com
auto_deploy: true
production:
url: https://my-service.example.com
auto_deploy: false
requires_approval: true
test_execution:
default_command: npm test
timeout_seconds: 120
coverage:
enabled: true
threshold: 80
Key points:
stackshas exactly one entry.path: .means the stack lives at the repository root. No path-based CI filters needed.platformshas one entry. For a CLI tool, usecli. For a mobile app, useios,android, ormobile.
Edit the stacks section with
/gaia-config-stack
and the platforms section with
/gaia-config-platform.
CI setup
With a single stack and no path filters, CI is straightforward. Every change triggers the same test suite.
/gaia-ci-setup
For a solo developer, the solo preset generates a single
workflow that runs on push to main. For a small team,
the small-team preset generates a PR-triggered workflow
with concurrency cancellation.
Because there is only one stack, you do not need path filters, parallel jobs, or matrix builds. One job runs lint, tests, and build in sequence.
Language-specific examples
Python service
stacks:
- name: api
language: python
framework: fastapi
path: .
test_command: pytest --cov=src --cov-report=term-missing
build_command: docker build -t my-service .
lint_command: ruff check src/
Go CLI tool
stacks:
- name: cli
language: go
path: .
test_command: go test ./...
build_command: go build -o bin/mytool cmd/mytool/main.go
lint_command: golangci-lint run
Rails web application
stacks:
- name: web
language: ruby
framework: rails
path: .
test_command: bundle exec rspec
build_command: bundle exec rails assets:precompile
lint_command: bundle exec rubocop
Flutter mobile app
stacks:
- name: mobile
language: dart
framework: flutter
path: .
test_command: flutter test
build_command: flutter build apk
lint_command: flutter analyze
platforms:
- android
- ios
For mobile apps, list each target platform separately. This tells
GAIA to include platform-specific testing (device matrix, responsive
testing) in your test strategy. See
/gaia-config-device-target
for device matrix configuration.
What to read next
- Configuring CI Pipelines -- setting up triggers and concurrency for your single-stack CI.
- Test Strategy Configuration -- configuring test execution and the Test Execution Bridge.
- Environments and Promotion -- setting up dev, staging, and production.
- Project Shapes Overview -- comparing all shapes.