@activatus/code-standards 0.0.0-stage → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +200 -2
- package/docs/Guides/_category_.json +4 -0
- package/docs/Guides/component-library-workflow.md +182 -0
- package/docs/Guides/migrating.md +144 -0
- package/docs/Guides/setup.md +130 -0
- package/docs/Standards/_category_.json +4 -0
- package/docs/Standards/agent-skills.md +125 -0
- package/docs/Standards/agent-specs.md +89 -0
- package/docs/Standards/branch-naming.md +66 -0
- package/docs/Standards/conventional-commits.md +189 -0
- package/docs/Standards/direnv.mdx +249 -0
- package/docs/Standards/documentation.md +311 -0
- package/docs/Standards/editorconfig.md +72 -0
- package/docs/Standards/eslint.md +709 -0
- package/docs/Standards/human-readable-names.md +234 -0
- package/docs/Standards/lint-errors.md +139 -0
- package/docs/Standards/prettier.md +97 -0
- package/docs/Standards/readable-code.md +540 -0
- package/docs/Standards/stylelint.md +178 -0
- package/docs/Standards/styling.md +284 -0
- package/docs/Standards/tech-stack.md +156 -0
- package/docs/Structure/_category_.json +4 -0
- package/docs/Structure/api-routes.md +118 -0
- package/docs/Structure/component-organization.md +519 -0
- package/docs/Structure/folder-structure.md +353 -0
- package/docs/Structure/import-organization.md +158 -0
- package/docs/Structure/naming-conventions.md +336 -0
- package/docs/design-system-components.md +117 -0
- package/docs/intro.md +46 -0
- package/docs/ontology.md +132 -0
- package/docs/templates.mdx +419 -0
- package/docs/version-history.md +211 -0
- package/package.json +56 -3
- package/static/templates/.commitlintrc.json +3 -0
- package/static/templates/.editorconfig +28 -0
- package/static/templates/.envrc +25 -0
- package/static/templates/.nvmrc +1 -0
- package/static/templates/AGENTS.md +160 -0
- package/static/templates/decision-doc.md +19 -0
- package/static/templates/docs/ai/agent-harness.md +17 -0
- package/static/templates/docs/ai/agents.md +17 -0
- package/static/templates/docs/ai/architecture.md +17 -0
- package/static/templates/docs/ai/context.md +17 -0
- package/static/templates/docs/ai/model-routing.md +17 -0
- package/static/templates/docs/ai/models.md +17 -0
- package/static/templates/docs/ai/retrieval.md +17 -0
- package/static/templates/docs/ai/tools.md +17 -0
- package/static/templates/docs/architecture/authentication.md +17 -0
- package/static/templates/docs/architecture/backend.md +17 -0
- package/static/templates/docs/architecture/background-jobs.md +17 -0
- package/static/templates/docs/architecture/backups.md +17 -0
- package/static/templates/docs/architecture/caching.md +17 -0
- package/static/templates/docs/architecture/ci-cd.md +17 -0
- package/static/templates/docs/architecture/disaster-recovery.md +17 -0
- package/static/templates/docs/architecture/environments.md +17 -0
- package/static/templates/docs/architecture/frontend.md +17 -0
- package/static/templates/docs/architecture/hosting.md +17 -0
- package/static/templates/docs/architecture/observability.md +17 -0
- package/static/templates/docs/architecture/realtime.md +17 -0
- package/static/templates/docs/architecture/search.md +17 -0
- package/static/templates/docs/architecture/services.md +17 -0
- package/static/templates/docs/architecture/state-management.md +17 -0
- package/static/templates/docs/architecture/storage.md +17 -0
- package/static/templates/docs/architecture/system.md +17 -0
- package/static/templates/docs/business/buying-trigger.md +17 -0
- package/static/templates/docs/business/customer-value.md +17 -0
- package/static/templates/docs/business/customer.md +17 -0
- package/static/templates/docs/business/defensibility.md +17 -0
- package/static/templates/docs/business/growth.md +17 -0
- package/static/templates/docs/business/pricing.md +17 -0
- package/static/templates/docs/business/revenue-model.md +17 -0
- package/static/templates/docs/business/unit-economics.md +17 -0
- package/static/templates/docs/data/analytics.md +17 -0
- package/static/templates/docs/data/audit.md +17 -0
- package/static/templates/docs/data/database.md +17 -0
- package/static/templates/docs/data/indexing.md +17 -0
- package/static/templates/docs/data/migrations.md +17 -0
- package/static/templates/docs/data/model.md +17 -0
- package/static/templates/docs/data/retention.md +17 -0
- package/static/templates/docs/data/schema.md +17 -0
- package/static/templates/docs/deployment/approval.md +17 -0
- package/static/templates/docs/deployment/live-verification.md +17 -0
- package/static/templates/docs/deployment/process.md +17 -0
- package/static/templates/docs/deployment/rollback.md +17 -0
- package/static/templates/docs/design/design-system.md +17 -0
- package/static/templates/docs/design/errors.md +17 -0
- package/static/templates/docs/design/feedback.md +17 -0
- package/static/templates/docs/design/interactions.md +17 -0
- package/static/templates/docs/design/layout.md +17 -0
- package/static/templates/docs/design/navigation.md +17 -0
- package/static/templates/docs/design/principles.md +17 -0
- package/static/templates/docs/design/responsive.md +17 -0
- package/static/templates/docs/development/branching.md +17 -0
- package/static/templates/docs/development/code-quality.md +17 -0
- package/static/templates/docs/development/coding-standards.md +17 -0
- package/static/templates/docs/development/commits.md +17 -0
- package/static/templates/docs/development/merge-strategy.md +17 -0
- package/static/templates/docs/development/process.md +17 -0
- package/static/templates/docs/development/pull-requests.md +17 -0
- package/static/templates/docs/experience/accessibility.md +17 -0
- package/static/templates/docs/experience/aha-moment.md +17 -0
- package/static/templates/docs/experience/anti-experience.md +17 -0
- package/static/templates/docs/experience/friction.md +17 -0
- package/static/templates/docs/experience/outcomes.md +17 -0
- package/static/templates/docs/experience/principles.md +17 -0
- package/static/templates/docs/experience/retention.md +17 -0
- package/static/templates/docs/experience/sharing.md +17 -0
- package/static/templates/docs/overview/how-it-works.md +17 -0
- package/static/templates/docs/overview/what-is-it.md +17 -0
- package/static/templates/docs/overview/writing-docs.md +16 -0
- package/static/templates/docs/pitch/alternatives.md +17 -0
- package/static/templates/docs/pitch/assumptions.md +17 -0
- package/static/templates/docs/pitch/audience.md +17 -0
- package/static/templates/docs/pitch/concept.md +17 -0
- package/static/templates/docs/pitch/differentiators.md +17 -0
- package/static/templates/docs/pitch/outcomes.md +17 -0
- package/static/templates/docs/pitch/problem.md +17 -0
- package/static/templates/docs/pitch/product-market-fit.md +17 -0
- package/static/templates/docs/pitch/success-criteria.md +17 -0
- package/static/templates/docs/pitch/validation.md +17 -0
- package/static/templates/docs/pitch/value-proposition.md +17 -0
- package/static/templates/docs/pitch/vision.md +17 -0
- package/static/templates/docs/scope/core.md +17 -0
- package/static/templates/docs/scope/exclusions.md +17 -0
- package/static/templates/docs/scope/future.md +17 -0
- package/static/templates/docs/scope/launch.md +17 -0
- package/static/templates/docs/scope/post-launch.md +17 -0
- package/static/templates/docs/scope/priorities.md +17 -0
- package/static/templates/docs/scope/quality-bar.md +17 -0
- package/static/templates/docs/security/audit.md +17 -0
- package/static/templates/docs/security/data-access.md +17 -0
- package/static/templates/docs/security/logging.md +17 -0
- package/static/templates/docs/security/privacy.md +17 -0
- package/static/templates/docs/security/secrets.md +17 -0
- package/static/templates/docs/security/threat-model.md +17 -0
- package/static/templates/docs/testing/end-to-end.md +17 -0
- package/static/templates/docs/testing/integration.md +17 -0
- package/static/templates/docs/testing/regression.md +17 -0
- package/static/templates/docs/testing/security.md +17 -0
- package/static/templates/docs/testing/strategy.md +17 -0
- package/static/templates/docs/testing/test-data.md +17 -0
- package/static/templates/docs/testing/unit.md +17 -0
- package/static/templates/docs/uat/checks.md +17 -0
- package/static/templates/docs/uat/strategy.md +17 -0
- package/static/templates/docs/users/permissions.md +17 -0
- package/static/templates/docs/users/roles.md +17 -0
- package/static/templates/docs/users/user-types.md +17 -0
- package/static/templates/docs/workflows/assignment.md +17 -0
- package/static/templates/docs/workflows/bugfix.md +17 -0
- package/static/templates/docs/workflows/dependencies.md +17 -0
- package/static/templates/docs/workflows/deployment.md +17 -0
- package/static/templates/docs/workflows/development.md +17 -0
- package/static/templates/docs/workflows/planning.md +17 -0
- package/static/templates/docs/workflows/review.md +17 -0
- package/static/templates/docs/workflows/uat.md +17 -0
- package/static/templates/docsSite/docusaurus.config.ts +119 -0
- package/static/templates/docsSite/gitignore.txt +3 -0
- package/static/templates/docsSite/package.json.txt +42 -0
- package/static/templates/docsSite/pnpm-workspace.yaml +2 -0
- package/static/templates/docsSite/sidebars.ts +8 -0
- package/static/templates/docsSite/src/css/custom.css +1 -0
- package/static/templates/docsSite/src/pages/index.tsx +9 -0
- package/static/templates/docsSite/static/images/logo.svg +4 -0
- package/static/templates/docsSite/tsconfig.json +7 -0
- package/static/templates/eslint/base/eslint.config.mjs +79 -0
- package/static/templates/eslint/nextjs/eslint.config.mjs +137 -0
- package/static/templates/eslint/react/eslint.config.mjs +138 -0
- package/static/templates/eslint/typescript/eslint.config.mjs +126 -0
- package/static/templates/globals.css +16 -0
- package/static/templates/husky/commit-msg +1 -0
- package/static/templates/husky/pre-commit +1 -0
- package/static/templates/next.config.mjs +18 -0
- package/static/templates/prettier.config.js +17 -0
- package/static/templates/skills/codeReview.md +31 -0
- package/static/templates/skills/format.md +18 -0
- package/static/templates/skills/lint.md +21 -0
- package/static/templates/skills/lintFix.md +24 -0
- package/static/templates/skills/securityAudit.md +28 -0
- package/static/templates/skills/test.md +24 -0
- package/static/templates/skills/typescript.md +28 -0
- package/static/templates/skills/updateLayout.md +20 -0
- package/static/templates/stylelint/css/stylelint.config.mjs +28 -0
- package/static/templates/stylelint/scss/stylelint.config.mjs +10 -0
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 3
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Folder Structure
|
|
6
|
+
|
|
7
|
+
This guide defines standard folder organization patterns for Activatus projects.
|
|
8
|
+
|
|
9
|
+
## Principles
|
|
10
|
+
|
|
11
|
+
1. **Predictability** - Developers should know where to find things
|
|
12
|
+
2. **Scalability** - Structure should work for small and large projects
|
|
13
|
+
3. **Consistency** - Same patterns across all projects
|
|
14
|
+
4. **Clarity** - Folder names should describe their purpose
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 📁 Recommended Next.js Structure
|
|
19
|
+
|
|
20
|
+
For Next.js projects using App Router, use the **root-level `app/` directory**. This is the modern Next.js standard.
|
|
21
|
+
|
|
22
|
+
```text
|
|
23
|
+
project-root/
|
|
24
|
+
├── app/ # Next.js App Router pages & layouts
|
|
25
|
+
│ ├── (routes)/ # Route groups (kebab-case)
|
|
26
|
+
│ │ ├── account-settings/
|
|
27
|
+
│ │ │ ├── components/ # Route-specific components
|
|
28
|
+
│ │ │ │ └── accountForm/ # Example component structure
|
|
29
|
+
│ │ │ │ ├── AccountForm.tsx # Component implementation
|
|
30
|
+
│ │ │ │ ├── AccountForm.test.tsx # Unit tests
|
|
31
|
+
│ │ │ │ ├── types.ts # Component types
|
|
32
|
+
│ │ │ │ └── index.ts # Export file
|
|
33
|
+
│ │ │ └── page.tsx
|
|
34
|
+
│ │ └── page.tsx
|
|
35
|
+
│ ├── api/ # API routes (kebab-case)
|
|
36
|
+
│ │ ├── users/
|
|
37
|
+
│ │ │ └── route.ts
|
|
38
|
+
│ │ └── webhooks/
|
|
39
|
+
│ │ └── stripe/
|
|
40
|
+
│ │ └── route.ts
|
|
41
|
+
│ ├── layout.tsx
|
|
42
|
+
│ └── page.tsx
|
|
43
|
+
├── components/ # React components
|
|
44
|
+
│ ├── ui/ # Design System Components
|
|
45
|
+
│ │ └── button/ # Example component structure
|
|
46
|
+
│ │ ├── Button.tsx # Component implementation
|
|
47
|
+
│ │ ├── Button.test.tsx # Unit tests
|
|
48
|
+
│ │ ├── Button.stories.tsx # Storybook stories
|
|
49
|
+
│ │ ├── types.ts # Component types
|
|
50
|
+
│ │ └── index.ts # Export file
|
|
51
|
+
│ └── shared/ # Used by more than one page
|
|
52
|
+
├── library/ # Core libraries & integrations
|
|
53
|
+
│ ├── permissions/ # Permission files (grouped)
|
|
54
|
+
│ │ ├── index.ts # Main definitions
|
|
55
|
+
│ │ ├── api.ts # API permissions
|
|
56
|
+
│ │ ├── page.ts # Page permissions
|
|
57
|
+
│ │ └── plan.ts # Plan permissions
|
|
58
|
+
│ ├── integrations/ # External services (grouped)
|
|
59
|
+
│ │ ├── stripe.ts # Payment processing
|
|
60
|
+
│ │ └── supabase/ # Database integration
|
|
61
|
+
│ │ ├── client.ts
|
|
62
|
+
│ │ └── mock/
|
|
63
|
+
│ ├── middleware/ # Middleware concerns (grouped)
|
|
64
|
+
│ │ ├── cors.ts
|
|
65
|
+
│ │ ├── rateLimit.ts
|
|
66
|
+
│ │ └── session.ts
|
|
67
|
+
│ ├── validation/ # Validation schemas
|
|
68
|
+
│ ├── constants/ # Constants
|
|
69
|
+
│ ├── errors/ # Error handlers
|
|
70
|
+
│ └── types/ # Type definitions
|
|
71
|
+
├── utils/ # Reusable functions used across the app
|
|
72
|
+
│ ├── formatCurrency/ # One folder per function
|
|
73
|
+
│ │ ├── formatCurrency.ts
|
|
74
|
+
│ │ ├── formatCurrency.test.ts
|
|
75
|
+
│ │ └── index.ts
|
|
76
|
+
│ ├── formatDate/
|
|
77
|
+
│ │ ├── formatDate.ts
|
|
78
|
+
│ │ ├── formatDate.test.ts
|
|
79
|
+
│ │ └── index.ts
|
|
80
|
+
│ └── index.ts # Exports every function
|
|
81
|
+
├── hooks/ # Custom React hooks
|
|
82
|
+
├── services/ # Business logic services
|
|
83
|
+
├── stores/ # State management stores
|
|
84
|
+
├── types/ # TypeScript type definitions
|
|
85
|
+
├── constants/ # App constants
|
|
86
|
+
├── styles/ # Global styles
|
|
87
|
+
├── public/ # Static assets
|
|
88
|
+
├── tests/ # Test files
|
|
89
|
+
├── docs/ # Project documentation — every file is a Decision Doc
|
|
90
|
+
│ ├── overview/ # What the project is and how it works
|
|
91
|
+
│ ├── architecture/ # How the system is built
|
|
92
|
+
│ ├── scope/ # What is in, out and later
|
|
93
|
+
│ └── ... # The other standard folders
|
|
94
|
+
├── docsSite/ # Docusaurus viewer for docs/ (config only)
|
|
95
|
+
├── package.json
|
|
96
|
+
├── next.config.mjs
|
|
97
|
+
├── tsconfig.json
|
|
98
|
+
└── eslint.config.mjs
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 📁 Next.js Project Structure
|
|
104
|
+
|
|
105
|
+
**Next.js modern standard** (App Router) uses root-level directories:
|
|
106
|
+
|
|
107
|
+
```text
|
|
108
|
+
project-root/
|
|
109
|
+
├── app/ # Next.js App Router
|
|
110
|
+
├── components/ # React components
|
|
111
|
+
├── library/ # Core libraries & integrations
|
|
112
|
+
├── utils/ # Reusable functions
|
|
113
|
+
├── public/ # Static assets
|
|
114
|
+
├── docs/ # Project documentation (Markdown)
|
|
115
|
+
├── docsSite/ # Docusaurus viewer for docs/
|
|
116
|
+
├── package.json
|
|
117
|
+
├── next.config.mjs
|
|
118
|
+
└── tsconfig.json
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### 💡 Why root-level for Next.js?
|
|
122
|
+
|
|
123
|
+
- **Next.js standard** - Official documentation uses root-level
|
|
124
|
+
- **Simpler imports** - Cleaner import paths
|
|
125
|
+
- **Faster development** - No abstraction layer
|
|
126
|
+
- **Better Next.js integration** - Optimized for the framework
|
|
127
|
+
- **Easier for beginners** - Less complexity
|
|
128
|
+
- **Framework conventions** - Matches Next.js ecosystem
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 🧩 Where components live
|
|
133
|
+
|
|
134
|
+
**A component lives where it is used.** There are no feature folders: a component either belongs to one page, to one section, or is shared.
|
|
135
|
+
|
|
136
|
+
| Used by | Lives in | Example |
|
|
137
|
+
| ------------------------------------------------------------------------------------------ | ---------------------------------------------------- | ---------------------------------------------- |
|
|
138
|
+
| **Every project the same way** — the [Design System Components](/design-system-components) | `components/ui/` | `components/ui/button/` |
|
|
139
|
+
| **More than one page** of this project | `components/shared/` | `components/shared/siteHeader/` |
|
|
140
|
+
| **A few pages in one section** | A `components/` folder in that section's route group | `app/(billing)/components/invoiceTable/` |
|
|
141
|
+
| **One page only** | A `components/` folder in that page's route folder | `app/account-settings/components/accountForm/` |
|
|
142
|
+
|
|
143
|
+
A route group is a folder in brackets, such as `(billing)`. It groups pages without changing their URLs: `app/(billing)/invoices/page.tsx` is served at `/invoices`.
|
|
144
|
+
|
|
145
|
+
```text
|
|
146
|
+
project-root/
|
|
147
|
+
├── app/
|
|
148
|
+
│ ├── (billing)/ # A section: groups pages, not part of the URL
|
|
149
|
+
│ │ ├── components/ # Used by more than one billing page
|
|
150
|
+
│ │ │ └── invoiceTable/
|
|
151
|
+
│ │ ├── invoices/
|
|
152
|
+
│ │ │ └── page.tsx # /invoices
|
|
153
|
+
│ │ └── payments/
|
|
154
|
+
│ │ └── page.tsx # /payments
|
|
155
|
+
│ └── account-settings/
|
|
156
|
+
│ ├── components/ # Used only by this page
|
|
157
|
+
│ │ └── accountForm/
|
|
158
|
+
│ │ ├── AccountForm.tsx
|
|
159
|
+
│ │ ├── AccountForm.test.tsx
|
|
160
|
+
│ │ ├── types.ts
|
|
161
|
+
│ │ └── index.ts
|
|
162
|
+
│ └── page.tsx # /account-settings
|
|
163
|
+
└── components/
|
|
164
|
+
├── ui/ # Design System Components: Button, Card, Modal
|
|
165
|
+
│ └── button/
|
|
166
|
+
└── shared/ # Used by more than one page of this project
|
|
167
|
+
└── siteHeader/
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Rules
|
|
171
|
+
|
|
172
|
+
- **Start where it is used, and move it when it is shared.** A new component goes in its page's `components/` folder. When a second page in the same section needs it, move it to the section's `components/` folder. When a page in another section needs it, move it to `components/shared/`.
|
|
173
|
+
- **`components/ui/` is only for [Design System Components](/design-system-components).** They take everything through props and import nothing from the project, so they can be copied into another project unchanged. See [Reusable by design](/Structure/component-organization#reusable-by-design).
|
|
174
|
+
- **A page or shared component wraps Design System Components.** It holds this project's logic and data, and passes props down.
|
|
175
|
+
- **Never group by type** (`atoms/`, `molecules/`, `organisms/`). Group by where a component is used.
|
|
176
|
+
|
|
177
|
+
Other frameworks follow the same rule with their own folders. In a React app without Next.js, a page's folder is the folder for that screen.
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## 🧰 Utils
|
|
182
|
+
|
|
183
|
+
**Every reusable function lives in a `utils/` folder**, never inside a UI file. Where it goes depends on who uses it:
|
|
184
|
+
|
|
185
|
+
| Used by | Location | Example |
|
|
186
|
+
| ------------- | ------------------------------------------------ | ----------------------------------------------------------------- |
|
|
187
|
+
| The whole app | Global `utils/` folder at the project root | `utils/formatCurrency/` |
|
|
188
|
+
| One section | A `utils/` folder in that section's route group | `app/(billing)/utils/calculateInvoiceTotal/` |
|
|
189
|
+
| One component | A `utils/` folder inside that component's folder | `app/(billing)/components/invoiceTable/utils/sortInvoicesByDate/` |
|
|
190
|
+
|
|
191
|
+
Every `utils/` folder has the same shape, at every level: **one folder per function**, holding the function, its test file and an `index.ts` — and an **`index.ts`** in the `utils/` folder that exports them all.
|
|
192
|
+
|
|
193
|
+
```text
|
|
194
|
+
project-root/
|
|
195
|
+
├── utils/ # Global: used across the app
|
|
196
|
+
│ ├── formatCurrency/
|
|
197
|
+
│ │ ├── formatCurrency.ts
|
|
198
|
+
│ │ ├── formatCurrency.test.ts
|
|
199
|
+
│ │ └── index.ts
|
|
200
|
+
│ ├── formatDate/
|
|
201
|
+
│ │ ├── formatDate.ts
|
|
202
|
+
│ │ ├── formatDate.test.ts
|
|
203
|
+
│ │ └── index.ts
|
|
204
|
+
│ └── index.ts
|
|
205
|
+
└── app/
|
|
206
|
+
└── (billing)/
|
|
207
|
+
├── utils/ # Section: used only by billing pages
|
|
208
|
+
│ ├── calculateInvoiceTotal/
|
|
209
|
+
│ │ ├── calculateInvoiceTotal.ts
|
|
210
|
+
│ │ ├── calculateInvoiceTotal.test.ts
|
|
211
|
+
│ │ └── index.ts
|
|
212
|
+
│ └── index.ts
|
|
213
|
+
└── components/
|
|
214
|
+
└── invoiceTable/
|
|
215
|
+
├── InvoiceTable.tsx
|
|
216
|
+
└── utils/ # Component: used only by InvoiceTable
|
|
217
|
+
├── sortInvoicesByDate/
|
|
218
|
+
│ ├── sortInvoicesByDate.ts
|
|
219
|
+
│ ├── sortInvoicesByDate.test.ts
|
|
220
|
+
│ └── index.ts
|
|
221
|
+
└── index.ts
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### The `index.ts` files
|
|
225
|
+
|
|
226
|
+
Each function folder has an `index.ts` that exports its function, and the `utils/` folder has an `index.ts` that exports every function, so imports stay neat:
|
|
227
|
+
|
|
228
|
+
```ts title="utils/formatCurrency/index.ts"
|
|
229
|
+
export { formatCurrency } from "./formatCurrency";
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
```ts title="utils/index.ts"
|
|
233
|
+
export { formatCurrency } from "./formatCurrency";
|
|
234
|
+
export { formatDate } from "./formatDate";
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
```ts
|
|
238
|
+
// ✅ Good — import from the utils folder
|
|
239
|
+
import { formatCurrency, formatDate } from "@/utils";
|
|
240
|
+
import { sortInvoicesByDate } from "./utils";
|
|
241
|
+
|
|
242
|
+
// ❌ Bad — reaching into the function's folder
|
|
243
|
+
import { formatCurrency } from "@/utils/formatCurrency/formatCurrency";
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Add the export to `utils/index.ts` whenever you add a function.
|
|
247
|
+
|
|
248
|
+
### Rules
|
|
249
|
+
|
|
250
|
+
- **Start local, promote when shared.** A function begins in the component's `utils/`. When another component in the same section needs it, move its folder to the section's `utils/`. When anything outside the section needs it, move it to the global `utils/`.
|
|
251
|
+
- **One function per folder**, with the folder and file named after the function (`formatCurrency/formatCurrency.ts`), plus its test file and an `index.ts`.
|
|
252
|
+
- **Every function has a test file** in the same folder. See [Readable Code](/Standards/readable-code#every-function-and-component-has-a-test-file).
|
|
253
|
+
- **Import from the `utils` folder**, never from the files inside it.
|
|
254
|
+
- **Keep UI files clean.** If a function could be written in another file, it does not belong in the component file. See [Writing a component](/Structure/component-organization#-writing-a-component).
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## 🧪 Test Placement
|
|
259
|
+
|
|
260
|
+
**Co-locate tests** with the code they test:
|
|
261
|
+
|
|
262
|
+
```text
|
|
263
|
+
components/
|
|
264
|
+
├── button/
|
|
265
|
+
│ ├── Button.tsx
|
|
266
|
+
│ ├── Button.test.tsx
|
|
267
|
+
│ ├── Button.stories.tsx
|
|
268
|
+
│ └── index.ts
|
|
269
|
+
hooks/
|
|
270
|
+
├── useUserData/
|
|
271
|
+
│ ├── useUserData.ts
|
|
272
|
+
│ ├── useUserData.test.ts
|
|
273
|
+
│ └── index.ts
|
|
274
|
+
utils/
|
|
275
|
+
├── formatCurrency/
|
|
276
|
+
│ ├── formatCurrency.ts
|
|
277
|
+
│ ├── formatCurrency.test.ts
|
|
278
|
+
│ └── index.ts
|
|
279
|
+
└── index.ts
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## 📝 Project Documentation
|
|
285
|
+
|
|
286
|
+
**Keep project documentation in a root-level `docs/` folder.** Every file in it is a Decision Doc, and every project uses the same folders. The Docusaurus viewer that displays it at `/docs` lives beside it in `docsSite/`:
|
|
287
|
+
|
|
288
|
+
```text
|
|
289
|
+
project-root/
|
|
290
|
+
├── docs/ # The docs: plain Markdown only. Every file is a Decision Doc
|
|
291
|
+
│ ├── overview/ # What the project is, how it works, how to write docs
|
|
292
|
+
│ ├── architecture/ # How the system is built
|
|
293
|
+
│ ├── design/ # How it looks and behaves
|
|
294
|
+
│ ├── scope/ # What is in, out and later
|
|
295
|
+
│ ├── ... # The other standard folders
|
|
296
|
+
│ └── product/ # Decisions specific to this product
|
|
297
|
+
└── docsSite/ # The viewer: Docusaurus config, no content
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
See [Documentation](/Standards/documentation) for the full list of folders, the doc format, and how docs are displayed and kept up to date.
|
|
301
|
+
|
|
302
|
+
Name documentation folders and files in **kebab-case** (`background-jobs.md`), not camelCase (`backgroundJobs.md`). The name becomes the page's URL on the docs site.
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## 📄 Configuration Files
|
|
307
|
+
|
|
308
|
+
**Keep configuration at the root** where tools expect it:
|
|
309
|
+
|
|
310
|
+
```text
|
|
311
|
+
/root
|
|
312
|
+
├── eslint.config.mjs # ESLint configuration
|
|
313
|
+
├── prettier.config.js # Prettier configuration
|
|
314
|
+
├── tsconfig.json # TypeScript configuration
|
|
315
|
+
├── next.config.mjs # Next.js configuration
|
|
316
|
+
├── package.json # Dependencies & scripts
|
|
317
|
+
└── .env.local # Environment variables (gitignored)
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
## 🚨 Red Flags
|
|
323
|
+
|
|
324
|
+
Avoid these anti-patterns:
|
|
325
|
+
|
|
326
|
+
- ❌ **Deep nesting** - More than 4-5 levels deep
|
|
327
|
+
- ❌ **Scattered logic** - Related code in multiple unrelated folders
|
|
328
|
+
- ❌ **Vague names** - `helpers/`, `misc/`, `stuff/` without organization
|
|
329
|
+
- ❌ **Inconsistent patterns** - Different structures for similar things
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
## 📚 Naming Conventions
|
|
334
|
+
|
|
335
|
+
See [Naming Conventions](/Structure/naming-conventions) for detailed file and folder naming rules.
|
|
336
|
+
|
|
337
|
+
**Quick reference:**
|
|
338
|
+
|
|
339
|
+
- **Component files**: PascalCase (`UserProfile.tsx`)
|
|
340
|
+
- **Utils files**: camelCase (`apiUtils.ts`)
|
|
341
|
+
- **Hook files**: camelCase with `use` prefix (`useUserData.ts`)
|
|
342
|
+
- **Service files**: camelCase with `Service` suffix (`apiService.ts`)
|
|
343
|
+
- **Route Folder names**: kebab-case (`user-management/`, `api-routes/`)
|
|
344
|
+
- **Component Folder names**: camelCase (`header/`, `model/`)
|
|
345
|
+
- **Documentation files**: kebab-case (`background-jobs.md`)
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## 📚 Resources
|
|
350
|
+
|
|
351
|
+
- [Next.js App Router](https://nextjs.org/docs/app)
|
|
352
|
+
- [Next.js Project Structure](https://nextjs.org/docs/app/building-your-application/routing/colocation)
|
|
353
|
+
- [Monorepo Patterns](https://monorepo.tools/)
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 4
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Import Organization
|
|
6
|
+
|
|
7
|
+
Consistent import organization makes code easier to read and understand.
|
|
8
|
+
|
|
9
|
+
## Import Order
|
|
10
|
+
|
|
11
|
+
Follow this order in all files:
|
|
12
|
+
|
|
13
|
+
1. **React and core packages**
|
|
14
|
+
2. **Internal workspace packages** (the project's own scope, e.g. `@acme/*`)
|
|
15
|
+
3. **External packages**
|
|
16
|
+
4. **Side effect imports**
|
|
17
|
+
5. **Parent imports** (`../`)
|
|
18
|
+
6. **Same-folder imports** (`./`)
|
|
19
|
+
7. **Style imports** (`.css`, `.module.css`)
|
|
20
|
+
|
|
21
|
+
## Example
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
// 1. React and core packages
|
|
25
|
+
import React, { useState, useEffect } from "react";
|
|
26
|
+
import { Link } from "@radix-ui/react-navigation-menu";
|
|
27
|
+
|
|
28
|
+
// 2. Internal workspace packages
|
|
29
|
+
import { Button } from "@acme/ui";
|
|
30
|
+
import { useAuthentication } from "@acme/authentication";
|
|
31
|
+
|
|
32
|
+
// 3. External packages
|
|
33
|
+
import { format } from "date-fns";
|
|
34
|
+
import clsx from "clsx";
|
|
35
|
+
|
|
36
|
+
// 4. Side effect imports
|
|
37
|
+
import "prismjs/themes/prism-tomorrow.css";
|
|
38
|
+
|
|
39
|
+
// 5. Parent imports
|
|
40
|
+
import { formatDate } from "../utils";
|
|
41
|
+
|
|
42
|
+
// 6. Same-folder imports
|
|
43
|
+
import { Header } from "./Header";
|
|
44
|
+
import { useUserData } from "./useUserData";
|
|
45
|
+
|
|
46
|
+
// 7. Style imports
|
|
47
|
+
import "./UserProfile.css";
|
|
48
|
+
import styles from "./styles.module.css";
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Why This Order?
|
|
52
|
+
|
|
53
|
+
1. **React first** - Most important dependency, immediately visible
|
|
54
|
+
2. **Internal packages** - Your team's code, separate from third-party
|
|
55
|
+
3. **External packages** - Third-party dependencies
|
|
56
|
+
4. **Side effects** - Imports that don't export values (CSS, polyfills)
|
|
57
|
+
5. **Parent imports** - Code from parent directories
|
|
58
|
+
6. **Same-folder** - Code from the current directory
|
|
59
|
+
7. **Styles last** - Visual separation, easy to find style imports
|
|
60
|
+
|
|
61
|
+
## Rules
|
|
62
|
+
|
|
63
|
+
- ✅ **Alphabetized** within each group
|
|
64
|
+
- ✅ **Blank lines** between groups
|
|
65
|
+
- ✅ **No duplicates** - Import each module once
|
|
66
|
+
|
|
67
|
+
## Import Safety
|
|
68
|
+
|
|
69
|
+
These four rules **are** enforced, and they are not about tidiness. They stop a whole class of bug: code that runs before the thing it needs exists.
|
|
70
|
+
|
|
71
|
+
### 1. No circular imports
|
|
72
|
+
|
|
73
|
+
**A file never imports a file that imports it back** — directly, or through a chain of other files.
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
// ❌ Bad — userService imports orderService, which imports userService
|
|
77
|
+
// services/userService.ts
|
|
78
|
+
import { getOrdersForUser } from "./orderService";
|
|
79
|
+
|
|
80
|
+
// services/orderService.ts
|
|
81
|
+
import { getUserById } from "./userService";
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
When two files import each other, one of them has to load first, and it sees the other half-finished. The code may work today and break when an unrelated import changes the loading order.
|
|
85
|
+
|
|
86
|
+
**The fix is to move the shared part into a third file** that both import, so the dependency runs one way:
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
// ✅ Good — both services import from a third file; neither imports the other
|
|
90
|
+
// services/userService.ts
|
|
91
|
+
import { findUserRecord } from "./userRecords";
|
|
92
|
+
|
|
93
|
+
// services/orderService.ts
|
|
94
|
+
import { findUserRecord } from "./userRecords";
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Enforced by ESLint `import-x/no-cycle`.
|
|
98
|
+
|
|
99
|
+
### 2. Inside a folder, import files directly
|
|
100
|
+
|
|
101
|
+
**A folder's `index.ts` is for code outside the folder.** Code inside the folder imports its neighbours by file, never through the folder's own `index.ts`. Importing through your own index is the most common way a circular import is created by accident.
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
// card/cardHeader/CardHeader.tsx
|
|
105
|
+
|
|
106
|
+
// ✅ Good — import the file directly
|
|
107
|
+
import type { CardProps } from "../types";
|
|
108
|
+
|
|
109
|
+
// ❌ Bad — the card index imports CardHeader, so this is a circle
|
|
110
|
+
import { Card } from "..";
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
| Importing from | Import through |
|
|
114
|
+
| ---------------------- | ---------------------------------------------------------------------- |
|
|
115
|
+
| **Outside** the folder | The folder's `index.ts`: `import { Card } from "@/components/ui/card"` |
|
|
116
|
+
| **Inside** the folder | The file itself: `import type { CardProps } from "../types"` |
|
|
117
|
+
|
|
118
|
+
A parent component imports its sub-components. **A sub-component never imports its parent.** If a child needs something from the parent, the parent passes it as a prop.
|
|
119
|
+
|
|
120
|
+
### 3. Define before use
|
|
121
|
+
|
|
122
|
+
**A function or variable is written above the code that uses it.** Read top to bottom, a file never refers to something that has not been defined yet.
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
// ✅ Good
|
|
126
|
+
const formatReport = () => "report";
|
|
127
|
+
|
|
128
|
+
export const sendReport = () => formatReport();
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
// ❌ Bad — formatReport is used above where it is defined
|
|
133
|
+
export const sendReport = () => formatReport();
|
|
134
|
+
|
|
135
|
+
const formatReport = () => "report";
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Enforced by ESLint `no-use-before-define`.
|
|
139
|
+
|
|
140
|
+
### 4. Files define things; they do not run things
|
|
141
|
+
|
|
142
|
+
**A file declares its functions and exports them. It does not call them as it loads.** The calling happens later, inside a component or another function.
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
// ✅ Good — nothing runs when this file is imported
|
|
146
|
+
export const connectToDatabase = () => createConnection(DATABASE_URL);
|
|
147
|
+
|
|
148
|
+
// ❌ Bad — importing this file opens a database connection
|
|
149
|
+
export const database = createConnection(DATABASE_URL);
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Code that runs on import makes the order files load in matter. Code that only defines things does not.
|
|
153
|
+
|
|
154
|
+
Enforced by ESLint `unicorn/no-top-level-side-effects`.
|
|
155
|
+
|
|
156
|
+
## Import Order Is Not Enforced
|
|
157
|
+
|
|
158
|
+
The **order of the import lines** is a convention, not a lint rule. Follow the same pattern in every file so imports are easy to read, but ESLint will not report an error if the order differs.
|