Coding Structure
C'mon Man! Get Organized
General
- One File, One Purpose
- No Swiss Army components, util files or classes
- Keeps things nice and simple and, more importantly Easy to Test!
- If your file > say, 500 lines - Red Flag 🚩
Frontend
A web app really only has two kinds of components:
- Common – reused, well-traveled, and politely introduced everywhere.
- Single Use – page-specific, introverted, and perfectly happy never leaving their room.
Keeping these two groups separate makes your frontend calmer, clearer, and much easier to reason about.
Shared components live together in a shared or common folder and are exported intentionally.
Page-specific components live inside their page folder, stay private, and never get exported.
Think of it like public vs private in a class:
- Public APIs should be deliberate and stable
- Private details should stay cozy and out of sight
- Nobody should be importing a page-only component from three directories away
Your future self will appreciate the boundaries.
Shared Components
Shared components are:
- Reused across multiple pages
- Generic enough to earn their keep
- Exported from a central folder
They form the design vocabulary of your app.
Page Components
Page components are:
- Tightly coupled to one page
- Free to change without breaking the world
- Not exported outside their folder
If a page component wants to escape and be reused, that’s its audition for becoming shared.
Barrel Files: Clean Imports, No Spaghetti
Barrel files (index.ts) keep imports:
- Short
- Intentional
- Free from relative-path gymnastics
No spaghetti imports. Just linguine.
Tests should live right next to the file they validate—like a loyal sidekick who never gets lost wandering a separate tests/ kingdom.
Frontend Folder Structure
src/
app/
philosophy/
Philosophy.page.tsx
Philosophy.page.test.tsx
components/
PhilosophyHero.tsx
PhilosophyHero.test.tsx
PhilosophyGrid.tsx
PhilosophyGrid.test.tsx
index.ts
common/
Button/
Button.tsx
Button.scss
Button.test.tsx
index.ts
Card/
Card.tsx
Card.scss
Card.test.tsx
index.ts
index.ts
Backend: One Endpoint, One Foler
In an ExpressJS app, each endpoint deserves its own folder.
That means:
- One folder per logical endpoint
- One file per HTTP method
- One clear responsibility per file
Each endpoint exports an Express router, which gets composed together in server.ts like a tidy neighborhood association. No cul-de-sacs. No mystery routes.
Tests live beside their handlers so the evidence is always in the room with the crime.
Backend Rules of the Road
- Routes are public
- Helpers stay private
- No wandering endpoints after curfew
- If a file grows too large, it’s trying to do too much
Predictable structure beats clever abstractions every time.
Backend Folder Structure
src/
server.ts
server.test.ts
users/
index.ts
index.test.ts
user.get.ts
user.get.test.ts
user.post.ts
user.post.test.ts
posts/
index.ts
index.test.ts
post.get.ts
post.get.test.ts
post.post.ts
post.post.test.ts
General: TypeScript Path Aliases Are Tiny Teleporters
TypeScript path aliases turn long, brittle relative imports into calm, readable statements of intent.
Give each top-level folder its own shortcut and watch imports go from long-winded novel to snappy haiku.
This has the added bonus of making them much easier to move around.
Example tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@app/*": ["src/app/*"],
"@common/*": ["src/common/*"],
"@data/*": ["src/data/*"]
}
}
}
Used consistently, aliases:
- Reduce refactor pain
- Clarify ownership boundaries
- Make code easier to scan
Structure isn’t bureaucracy—it’s kindness to the next person who reads your code.