On this page
  1. Why structure matters
  2. Python
  3. Node.js
  4. The rules that generalize
  5. Where AI coding assistants get this wrong
  6. Checklist
  7. FAQ
    1. Why use a src/ layout in Python?
    2. Should I commit the lockfile?
    3. Does structure matter for small scripts?
  8. Related topics
  9. Sources
tutorial

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 in requirements.txt or pyproject.toml.
  • Node.js: src/ for code, test/ for tests, with package.json and 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.example

Use 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.example

Keep 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.env files stay out of git; commit a .env.example instead.
  • 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 .gitignore for .env and 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.example and gitignore .env and 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.

Sources

Share: