# express_code_structure: grouping Express code by coupling, not by function

> express_code_structure is a scaffolding example for a medium-sized Express application, and its real content is a set of arguments about how to organise code: group by coupling instead of by function, keep first-party code in one directory, name files predictably, and resist directory depth that the files do not justify. It is not a working application.

**focusaurus/express_code_structure** — Example of how to organize a medium-size express.js web application

- Repository: https://github.com/focusaurus/express_code_structure
- Stars: 1,351 · Forks: 146
- Language: JavaScript
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/focusaurus-express-code-structure

## It is scaffolding, and the author says so

The repository description is unusually precise about what it is: an example of how to organize a medium-size Express.js web application, and the package description calls it scaffolding explaining a method for organizing files. The README removes any doubt, stating that for the purposes of this example it is just scaffolding and not a fully working app. The tree confirms the minimalism. There is an app/ directory, a bin/ directory, a wwwroot/ directory for static assets, a package.json, a package-lock.json, an .nvmrc and a .semaphore/ directory for CI. The application it assumes is a car dealership. The architecture it assumes is a site with traditional static pages and templates, the application portion developed in a single page application style, a REST and JSON style API to the browser, and a simple business domain. The runtime dependencies are correspondingly small: Express, the pug template engine and bole for logging. Dev dependencies cover the test and lint story, with tape, supertest, tap-dot, standard and bistre. This is a document you read and then delete, not a codebase you adopt.

## Group by coupling, not by function

The central argument is the one the author calls a major departure from the Ruby on Rails convention of app/views, app/controllers and app/models. The rule is grouping by coupling rather than by function. The reasoning is about attention. A feature in this model is a full stack, and a developer adding a telephone number field to the user model does not care about any controller other than the user controller and does not care about any model other than the user model. Under a function-grouped layout, that change means editing six files that are each in their own directory while ignoring dozens of unrelated files in those directories. Under a coupling-grouped layout, the feature's files sit together. The second consequence is searchability, and it is stated as a first-party rule: all first-party source code lives in the app directory, so you can cd there and run find, grep, xargs, ag or ack without being distracted by third party matches. That single rule is what makes the layout work as a layout rather than a set of conventions, because it means a text search over the project returns only your own code.

## The principles, including the one about not nesting too deep

The README lists the underlying principles, and they read as a working philosophy rather than a style guide. Being mentally manageable comes first, on the grounds that the brain can only deal with a small number of related things at once and directories help by focusing on small portions. Being size-appropriate is the rule that will save you the most time, and it is stated with an example: do not create mansion directories where there is just one file sitting alone three directories down. The author points at the Ansible Best Practices documentation as a source of this same tendency, shaming small projects into creating ten or more directories to hold ten or more files when one directory with three files would be more appropriate, and puts it as you do not drive a bus to work, so do not create filesystem structures that are not justified by the actual files inside them. Being easy to locate code means that given a feature to build or a bug to fix, a developer has no struggle finding the relevant source files, which is supported by meaningful and accurate names and by crufty code being fully removed rather than left in an orphan file or commented out. These are judgements, and they are the part of the repository that is still worth reading years later.

## Kebab-case files, camelCase variables, matching names

The naming rules are specific and consistent with the searchability goal. npm now seems to require all-lowercase package names, and the author finds that mostly terrible but follows the herd, so filenames use kebab-case even though the variable name for that in JavaScript must be camelCase, because a hyphen is a minus sign in JavaScript. The rule that follows is that a variable name matches the basename of the module path, with kebab-case transformed to camelCase. That is a small decision with a large payoff in a codebase: you can see where a symbol comes from by looking at its name, and you can search for a file knowing roughly what it is called. The README frames simple and obvious naming as one of the principles rather than a cosmetic preference, which is consistent with everything else in the document. The linter is standard, with the standard style badge in the README, and the lint script runs it over the project, so the naming rules are at least partly enforced rather than merely described.

## Proto-modules, and when to reach for npm

The modularity advice is the most interesting part of the argument because it argues against both extremes. The node community overall favours small modules, and the author agrees with the principle, saying that anything which can cleanly be separated out from the app entirely should be extracted into a module for internal use or published on npm. But the medium-sized application is the scope here, and the overhead of a separate package can add tedium without commensurate value. The resolution is a proto-module: code that is factored out but not yet worth a completely separate npm module, kept with the expectation that when it crosses a size threshold it will be extracted. The author notes that some developers, naming hij1nx, go further and include an app/node_modules directory with package.json files inside the proto-module directories to make that transition easy and to act as a reminder. The size question is answered in the same document, at both ends. A small application needs a handful of .js files in the repository root and nothing more. A huge application should be broken into distinct npm packages, and the node approach seems to favour many small packages, at least for libraries, so a portion of code that becomes clearly reusable or a clear subsystem should move to its own git repository and become a standalone npm package.

## Why Rails conventions were rejected on principle

The document devotes a section to what it calls the Ruby on Rails question, and the position is more interesting than a rejection. It is a theme that many of the ideas embodied in Ruby on Rails and the convention over configuration decisions they have adopted, though widely accepted and used, are not actually very helpful and are sometimes the opposite of what this repository recommends. The author's point is that there are underlying principles to organizing code, and based on those principles the Rails conventions make sense, mostly, for the Rails community. The failure mode is thoughtlessly aping those conventions, which misses the point. The conclusion is a formula: principles over convention over configuration. The argument for the server-side JavaScript world is that the overall ethos is far more wild west, and that Express is a close kin of Sinatra rather than Rails, so taking conventions from Rails is usually not helping. The list of approaches considered includes server-side MVC, single page application style MEAN, a basic site with forms, and a Models/Operations/Views/Events style with a link to the writing that introduced it.

## Running what is there

There are three scripts, and they describe the shape of the project. The test script runs a shell script in bin, the start script pipes the server entrypoint through bistre for coloured output, and the lint script runs standard:

```json
"test": "./bin/test.sh",
"start": "./app/server.js | bistre",
"lint": "standard"
```

The main entrypoint is declared as ./app/server, which is consistent with the rule that all first-party code lives under app. The engines field says node 6, and the README describes itself as current to at least Express v4.14 from December 2016, while the dependency list now pins Express at 5.2.1, pug at 3.0.4 and bole at 6.0.7. That gap between the stated compatibility and the actual manifest is worth noticing before anyone treats this as a starting point to copy, since the version metadata has drifted from the prose. The last push to the repository was on 2026-07-23 and there are no GitHub releases, so the commit history is the only version marker for an example that was never meant to be versioned as a product.

## Conclusion

Adopt express_code_structure if you are starting a medium-sized Express application and want a defensible answer to where a file goes, since the principles transfer even though the scaffolding itself is not an application. Do not copy the tree into a small project, because the project explicitly argues the opposite, and do not treat the manifest as a template, since it still declares node as the engine while depending on Express 5. Before you start, read the principles list in full and apply it to your own code rather than to a directory template, and check the dependency versions yourself, since the README text still describes itself as current only to Express 4.14 from December 2016.

## FAQ

### Is express_code_structure a working Express application?

No. The README states that for the purposes of this example it is just scaffolding and not a fully working app. It illustrates a directory layout and a set of principles for a medium-sized Express application.

### What is the main organizing idea in express_code_structure?

Group by coupling, not by function. The author calls it a major departure from the Rails convention of separate app/views, app/controllers and app/models directories, on the grounds that a feature's files should sit together rather than being scattered across per-type directories.

### What is a proto-module in this project?

Code that has been factored out of the application but is not yet large enough to justify a separate npm package. The expectation is that when it crosses a size threshold it will be extracted into its own module, and some developers place package.json files inside proto-module directories to make that transition easier.

### What naming rules does the project recommend?

Filenames use kebab-case and the matching JavaScript variable names use camelCase, because a hyphen is a minus sign in JavaScript. A variable name matches the basename of its module path, with kebab-case transformed to camelCase.

### What licence is express_code_structure released under?

The project is licensed under the MIT Licence, with the LICENSE file at the repository root. The last push was on 2026-07-23 and the repository publishes no GitHub releases.

## Sources

- [focusaurus/express_code_structure on GitHub](https://github.com/focusaurus/express_code_structure)
- [Issues](https://github.com/focusaurus/express_code_structure/issues)
- [License: MIT](https://github.com/focusaurus/express_code_structure/blob/main/LICENSE)
- [README](https://github.com/focusaurus/express_code_structure/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/focusaurus-express-code-structure
