Project Structure
Document: 05-project-structure.md
Version: 1.0.0
Purpose
This document defines the standard project structure used across all Rundown web development projects.
A consistent project structure improves maintainability, reduces onboarding time, and allows developers to navigate any project without first learning its layout.
Unless project requirements dictate otherwise, all Rundown projects should follow the structure outlined below.
Standard Project Layout
project-name/
├── app/
├── components/
├── features/
├── hooks/
├── lib/
├── payload/
├── public/
├── styles/
├── types/
├── utils/
├── scripts/
├── tests/
├── docs/
├── .github/
├── .vscode/
├── .env.example
├── .gitignore
├── docker-compose.yml
├── Dockerfile
├── next.config.ts
├── package.json
├── pnpm-lock.yaml
├── README.md
├── tsconfig.json
└── eslint.config.js
Directory Standards
/app
Contains the application's routing, layouts, pages, API routes, and server components.
Rules:
-
Organize by route.
-
Keep pages lightweight.
-
Move business logic into
featuresorlib.
/components
Contains reusable UI components shared across the application.
Examples:
Button/
Navbar/
Footer/
Card/
Hero/
Modal/
Rules:
-
Components should be reusable.
-
Avoid project-specific business logic.
-
Keep components focused on presentation.
/features
Contains feature-specific logic and components.
Examples:
Blog/
Portfolio/
Contact/
Products/
Authentication/
Each feature should contain its own:
-
Components
-
Hooks
-
Services
-
Validation
-
Utilities
Features should be isolated wherever practical.
/hooks
Contains reusable React hooks.
Examples:
useScroll.ts
useMediaQuery.ts
useTheme.ts
Rules:
-
Hooks should perform one responsibility.
-
Avoid feature-specific hooks unless they remain inside the corresponding feature directory.
/lib
Contains shared libraries and application services.
Examples:
database.ts
payload.ts
redis.ts
email.ts
analytics.ts
The lib directory should contain integrations rather than business logic.
/payload
Contains all Payload CMS configuration.
Typical structure:
payload/
collections/
globals/
blocks/
fields/
access/
hooks/
This directory should remain isolated from frontend code wherever possible.
/public
Contains publicly accessible static assets.
Examples:
-
Images
-
Icons
-
Fonts
-
Favicon
-
Robots.txt
Do not store client-managed content here.
Client uploads belong in Cloudflare R2.
/styles
Contains global styling resources.
Examples:
globals.css
variables.css
Tailwind configuration should remain outside this directory.
/types
Contains shared TypeScript types.
Examples:
product.ts
user.ts
navigation.ts
Shared interfaces should not be duplicated across features.
/utils
Contains pure utility functions.
Examples:
slugify.ts
formatDate.ts
capitalize.ts
Utility functions should remain framework-independent whenever possible.
/scripts
Contains project automation scripts.
Examples:
-
Database Seed
-
Data Import
-
Cache Clearing
-
Image Optimization
Scripts should be executable independently of the application.
/tests
Contains automated tests.
Project structure should mirror the application where practical.
/docs
Contains project-specific documentation.
Examples:
-
Deployment Notes
-
API Documentation
-
Client Handover Notes
-
Architecture Diagrams
This directory complements Rundown OS and should only include documentation specific to the project.
Root Files
Every Rundown project should include:
| File | Purpose |
|---|---|
| README.md | Project overview and setup instructions |
| .env.example | Required environment variables |
| Dockerfile | Container configuration |
| docker-compose.yml | Local development services |
| package.json | Project dependencies |
| pnpm-lock.yaml | Dependency lock file |
| tsconfig.json | TypeScript configuration |
| eslint.config.js | Linting rules |
Best Practices
-
Keep directories focused on a single responsibility.
-
Avoid deeply nested folder structures.
-
Prefer feature-based organization over file-type organization for complex functionality.
-
Remove unused files and directories.
-
Document non-obvious architectural decisions.
Engineering Decision
Feature-Based Organization
Status: Accepted
Decision
Projects should primarily organize business logic by feature rather than by file type.
Reasoning
Feature-based organization:
-
Improves scalability.
-
Groups related files together.
-
Reduces context switching.
-
Makes ownership clearer.
-
Simplifies future maintenance.
Alternatives Considered
-
Layer-based architecture
-
MVC structure
-
Flat directory structure
Feature-based organization provides the best balance between maintainability and scalability for the types of projects developed by Rundown.
Summary
A standardized project structure ensures every Rundown application follows the same architectural conventions.
Consistency improves collaboration, simplifies maintenance, and allows reusable tooling, documentation, and development practices to be applied across all projects.