On this page
How to Structure a Python or Node.js Project From Scratch
A clean project structure for Python and Node.js: separate source, tests, and config, with a layout that scales and that AI agents can navigate.
Quick answer
- Separate source code, tests, and configuration instead of dumping everything in one file.
- Python: a package directory plus a
tests/directory, with dependencies pinned inrequirements.txtorpyproject.toml.- Node.js:
src/for code,test/for tests, withpackage.jsonand a lockfile committed.
Why structure matters
A project’s layout is its first interface — for you, for collaborators, and for AI agents that must navigate it. A clear structure means a new file has an obvious home, a reader finds things by convention rather than search, and an agent knows where code, tests, and config live. The layout is the cheapest documentation you’ll ever write.
Python
myapp/
pyproject.toml # deps and config
README.md
src/
myapp/
__init__.py
main.py
api.py
models.py
tests/
test_api.py
test_models.py
.env.exampleUse the src/ layout (code under src/myapp/) so tests run against the installed package, not the source tree. Keep one module per concern, and mirror the structure in tests/.
Node.js
myapp/
package.json
package-lock.json # committed
README.md
src/
index.js
routes/
users.js
services/
userService.js
test/
users.test.js
.env.exampleKeep src/ for application code, test/ for tests, and commit the lockfile so installs are reproducible. Split routes and business logic so each file has one job.
The rules that generalize
- Separate concerns — code, tests, and config each get their own place.
- Pin dependencies — lockfiles make builds reproducible and supply-chain-safer.
- Ignore secrets —
.envfiles stay out of git; commit a.env.exampleinstead. - One obvious home per file — when a reader guesses where something lives, they should be right.
Where this bites vibecoders
The AI-generated “one file” project works until the third feature, at which point the file is 1,000 lines and every prompt risks breaking something. The structure isn’t ceremony — it’s how you and the agent both stay able to find and change things. Split early; it’s cheaper than splitting a grown-together monolith later.
Where AI coding assistants get this wrong
- Dumping everything into one file, since “it works” satisfies the ask.
- Not committing lockfiles, so installs drift.
- Ignoring
.gitignorefor.envand build artifacts. - Inventing a slightly different layout per project with no convention.
Checklist
- Separate source, tests, and configuration.
- Pin dependencies and commit lockfiles.
- Use one obvious home for each kind of file.
- Add
.env.exampleand gitignore.envand artifacts. - Document the layout in the README.
FAQ
Why use a src/ layout in Python?
The src/ layout prevents an accidental import of the package from the working directory, forcing tests to run against the installed package — which catches packaging mistakes early. It also keeps the root clean of code.
Should I commit the lockfile?
Yes, for applications. The lockfile pins exact dependency versions so every install is reproducible, which matters for builds and for supply-chain security. Libraries sometimes omit it, but apps should commit it.
Does structure matter for small scripts?
Less — a single-file script is fine for a single-file job. The structure matters once the project grows past one concern. The skill is recognizing when you’ve crossed that line and splitting before the file becomes unmanageable.
Related topics
- What Makes a Codebase “AI-Friendly”?
- How to Manage Secrets and Environment Variables Properly
- What Is the Twelve-Factor App Methodology?