The Anatomy of a Production Repository
Stop treating your root directory like a junk drawer. Here is what actually happens inside a high-scale GitHub repo.
By git11 Engineering · Mon Feb 16 2026 · 7 min read
Most production repositories are a mess. We see it every day at git11 while we're parsing thousands of internal codebases. The difference between a repo that scales and one that rots is usually visible in the first five seconds of looking at the tree.
A great repository isn't just a place to store code. It is an automated factory floor. If your root directory has 40 files in it, you've already lost. If you don't have a .github folder that does the heavy lifting, you aren't ship-ready.
Let’s walk through what’s actually happening behind the scenes in a modern, high-velocity setup.
The Root is for Humans, Not Files
The root of your repo should be sparse. If I see webpack.config.js, postcss.config.js, and jest.setup.js all sitting in the root, I know your team spends four hours a week debugging configuration drift.
Keep the root for the essentials: README.md, LICENSE, and your package manifests like package.json or go.mod. Everything else belongs in /config, /scripts, or deep inside your build tooling.
We favor a /tools directory for any custom CLI scripts or maintenance tasks. If it isn't part of the core product logic, move it out of the way. Clutter creates cognitive load, and cognitive load kills speed.
The .github Folder is the Brain
In a production repo, the .github directory is more important than your index.ts. This is where the automation lives. If your CI/CD isn't aggressive, your main branch is probably broken right now and you just don't know it yet.
We use Workflows for more than just testing. We use them for stale-issue management, dependency updates via Renovate, and automated labels based on file changes.
You should have a CODEOWNERS file here. If you don’t, you’re relying on tribal knowledge to figure out who reviews what. That doesn't work once you hit 10 engineers. It certainly doesn't work at 100.
Internal Tooling and /scripts
Every great repo has a graveyard of shell scripts. The difference is that the good ones have a /scripts folder that is actually maintained.
Stop telling new hires to copy-paste five commands to seed their database. Write a scripts/seed-db.sh. Or better yet, a Makefile.
Yes, make is 50 years old. It is still the best tool for the job because it is installed on every machine. A simple make setup should be the only command a new developer needs to run to get to a green state.
Source Code vs. The World
Your actual application should live in /src or /app. Never put business logic in the root. Inside that directory, structure should follow domain, not technical type.
Group by billing, auth, and dashboard, not controllers, models, and views. When you need to fix a bug in the checkout flow, you shouldn't have to jump across three different top-level folders.
We see teams struggle with this because their frameworks dictate a flat structure. Ignore the framework's default if it's bad. Good architecture makes the easy things easy and the hard things possible.
The Secret Life of PR Templates
If your PRs just say "fixed bug," your repository is a black hole. We use .github/PULL_REQUEST_TEMPLATE.md to force engineers to explain why something changed, not just what changed.
Include a checklist. Did they add tests? Did they update the docs? Did they check for breaking migrations?
You can't automate everything, but you can automate the reminder to be a professional. If an engineer complains about the friction, they're usually the one whose code needs the most review.
Governance and Documentation
Documentation belongs next to the code. If your docs live in a separate Wiki or a Notion page that hasn't been updated since 2022, they are useless.
Use a /docs folder. Use Markdown. This ensures that when a feature changes in a PR, the documentation update is part of the same diff.
We also recommend a CONTRIBUTING.md. This isn't just for open source. It’s for the engineer on the other team who needs to touch your service. Tell them how to run tests and where the logs go so they don't have to DM you on Slack.
The CI Pipeline as a Gatekeeper
A production repo treats the main branch as sacred. No one pushes to it directly. Ever.
Your GitHub Actions should be running more than just linting. You need unit tests, integration tests, and a security scanner like Snyk or Trivy.
If a PR takes more than 10 minutes to run CI, your engineers will start context-switching. If it takes less than 2 minutes, your tests are probably too shallow. Find the middle ground where the feedback loop is fast but meaningful.
Dependency Management
Production repos don't let dependencies rot. If you aren't using Renovate or Dependabot, you are accumulating security debt every single day.
We prefer Renovate because it allows for better grouping. You don't want 50 separate PRs for 50 small npm updates. Group non-breaking devDependencies into a single weekly PR.
Keep your lockfile clean. If you see people manually editing package-lock.json or yarn.lock, stop them. They are inviting non-deterministic builds and misery.
Tracking Metadata
Modern repos use custom labels and metadata. Use a labeler.yml to automatically tag PRs based on which files were modified.
If someone touches /infra, the SRE team should be tagged automatically via CODEOWNERS. If someone touches /public, the design team should be alerted.
This isn't about bureaucracy. It's about ensuring the right people see the right changes without chasing them down. Automation handles the boring stuff so you can actually write code.
Forget the Magic
There is no magic in a great repository. It is just a series of boring, disciplined choices made consistently over time.
Clean up your root. Automate your linting. Write a PR template. Put your business logic in domain-specific folders.
If you do these things, your repo becomes a tool. If you don't, it becomes a liability. Pick one.