Real-World Examples
Podfiles from the podspawn project itself -- Go, Node.js, and YAML repos.
Podspawn uses its own tool for development. These are the actual Podfiles committed to each repository in the project. They cover three common setups: a Go backend, a Next.js docs site, and a simple YAML-only repo.
The Podfiles
The main podspawn repo is a Go CLI with golangci-lint, integration tests that need Docker, and a pre-commit hook.
extends: ubuntu-dev
packages:
- go@1.25
resources:
cpus: 2.0
memory: 4g
on_create: |
go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest
go install github.com/go-delve/delve/cmd/dlv@latest
go mod download
make hooks
on_start: |
echo "podspawn dev: Go $(go version | awk '{print $3}')"
echo "run 'make test' to verify, 'make lint' to check style"What this does:
extends: ubuntu-devpulls in git, curl, ripgrep, fzf, neovim, jq, htop, makego@1.25installs from the official tarball (handled by podspawn's package resolver)on_createdownloads Go tools and project dependencies once, then installs the pre-commit hookon_startprints the version on every attach so you know what you're working with- No ports exposed -- podspawn is a CLI tool, not a server
golangci-lint and delve are installed via go install in on_create rather than as packages. This is because they're Go tools that need the Go toolchain to install, and podspawn's package resolver doesn't handle them natively.
The docs site uses Fumadocs (Next.js) with bun as the package manager.
extends: ubuntu-dev
packages:
- nodejs@22
ports:
expose: [3000]
strategy: auto
resources:
cpus: 1.0
memory: 2g
on_create: |
npm install -g bun
bun install
on_start: |
echo "podspawn-docs: Node $(node --version), bun $(bun --version)"
echo "run 'bun run dev' to start on port 3000"What this does:
nodejs@22installs Node via the NodeSource PPA- Port 3000 exposed with
autostrategy -- if another project uses 3000, podspawn picks the next available on_createinstalls bun globally, then runsbun installfor project deps- Lower resources (1 CPU, 2GB) -- docs sites don't need much
bun is installed via npm in on_create rather than as a package. This keeps the Podfile simple and avoids needing a custom package entry for bun.
The podfiles registry is just YAML files and a CI workflow. It needs yq for local validation but almost nothing else.
extends: minimal
on_create: |
curl -sSfL https://github.com/mikefarah/yq/releases/download/v4.44.1/yq_linux_amd64 \
-o /usr/local/bin/yq
chmod +x /usr/local/bin/yq
on_start: |
echo "podfiles registry: $(ls templates/*.yaml bases/*.yaml | wc -l) files"What this does:
extends: minimal-- only git, curl, ca-certificates. No dev tools needed for editing YAML.on_createfetches a specific version of yq. Pinned version avoids surprises.- No packages, no ports, no services, no resources override. The simplest possible Podfile.
Patterns to take away
Use extends to avoid repeating yourself. All three repos extend a base instead of listing git, curl, etc. individually.
Put slow things in on_create. go mod download, bun install, and binary downloads only run once. Fast things like version prints go in on_start.
Don't over-specify. The podfiles repo doesn't declare resources, ports, or shell. Defaults are fine for simple projects.
Pin tool versions. yq is pinned to v4.44.1, Go to 1.25. Pinning prevents "works on my machine" drift between contributors.
Match your CI. These Podfiles mirror what the CI workflows install. If CI uses golangci-lint, so does the Podfile. A contributor's podspawn dev environment matches what CI will test against.
How is this guide?