Skip to content

Commit 0c4c855

Browse files
committed
init
0 parents  commit 0c4c855

14 files changed

+596
-0
lines changed

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
**/*.md

.eslintrc.json

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{
2+
"root": true,
3+
"env": {
4+
"browser": true,
5+
"es2021": true,
6+
"node": true
7+
},
8+
"parser": "@typescript-eslint/parser",
9+
"plugins": [
10+
"astro",
11+
"markdown",
12+
"@typescript-eslint"
13+
],
14+
"extends": [
15+
"eslint:recommended",
16+
"plugin:astro/recommended",
17+
"plugin:markdown/recommended",
18+
"plugin:@typescript-eslint/recommended",
19+
"prettier",
20+
"plugin:prettier/recommended"
21+
],
22+
"overrides": [
23+
{
24+
"files": [
25+
"*.astro"
26+
],
27+
"parser": "astro-eslint-parser",
28+
"parserOptions": {
29+
"parser": "@typescript-eslint/parser",
30+
"extraFileExtensions": [
31+
".astro"
32+
]
33+
}
34+
},
35+
{
36+
"files": [
37+
"*.md"
38+
],
39+
"parserOptions": {
40+
"ecmaVersion": "latest"
41+
},
42+
"rules": {
43+
"no-undef": "off"
44+
}
45+
},
46+
{
47+
"files": [
48+
"*.ts",
49+
"*.tsx"
50+
],
51+
"excludedFiles": [
52+
"**/*.md"
53+
],
54+
"parserOptions": {
55+
"project": "./tsconfig.json"
56+
},
57+
"rules": {
58+
"@typescript-eslint/no-unused-vars": "warn",
59+
"@typescript-eslint/no-explicit-any": "warn"
60+
}
61+
}
62+
]
63+
}

.gitignore

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
node_modules/
2+
dist/
3+
*.tsbuildinfo
4+
.DS_Store
5+
.vercel
6+
.netlify
7+
_site/
8+
.astro/
9+
scripts/smoke/*-main/
10+
scripts/memory/project/src/pages/
11+
benchmark/projects/
12+
benchmark/results/
13+
test-results/
14+
*.log
15+
package-lock.json
16+
.turbo/
17+
.eslintcache
18+
.pnpm-store
19+
20+
# do not commit .env files or any files that end with `.env`
21+
*.env
22+
23+
packages/astro/src/**/*.prebuilt.ts
24+
packages/astro/src/**/*.prebuilt-dev.ts
25+
packages/astro/test/units/_temp-fixtures/*
26+
!packages/astro/test/units/_temp-fixtures/package.json
27+
packages/integrations/**/.netlify/
28+
29+
# exclude IntelliJ/WebStorm stuff
30+
.idea
31+
32+
# ignore content collection generated files
33+
packages/**/test/**/fixtures/**/.astro/
34+
packages/**/test/**/fixtures/**/env.d.ts
35+
packages/**/e2e/**/fixtures/**/.astro/
36+
packages/**/e2e/**/fixtures/**/env.d.ts
37+
examples/**/.astro/
38+
examples/**/env.d.ts
39+
40+
# make it easy for people to add project-specific Astro settings that they don't
41+
# want to share with others (see
42+
# https://github.com/withastro/astro/pull/11759#discussion_r1721444711)
43+
*.code-workspace

.husky/pre-commit

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
npx lint-staged

.prettierignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
node_modules
2+
dist
3+
build
4+
coverage

.prettierrc

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"trailingComma": "es5",
3+
"semi": false,
4+
"singleQuote": true,
5+
"jsxSingleQuote": true,
6+
"arrowParens": "avoid",
7+
"bracketSameLine": false,
8+
"plugins": ["prettier-plugin-astro"],
9+
"overrides": [
10+
{
11+
"files": "*.astro",
12+
"options": {
13+
"parser": "astro",
14+
"singleQuote": true,
15+
"jsxSingleQuote": true
16+
}
17+
},
18+
{
19+
"files": "*.tsx",
20+
"options": {
21+
"parser": "typescript",
22+
"singleQuote": true,
23+
"jsxSingleQuote": true
24+
}
25+
},
26+
{
27+
"files": "*.md",
28+
"options": {
29+
"parser": "markdown",
30+
"semi": false,
31+
"singleQuote": true,
32+
"arrowParens": "avoid",
33+
"embeddedLanguageFormatting": "off"
34+
}
35+
}
36+
]
37+
}

LICENSE.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
# React + TypeScript Feature-First Style Guide
2+
3+
A **feature-first** approach to building **scalable, maintainable, and predictable** React applications with TypeScript. Designed for **clarity, consistency, and efficiency**, this guide minimizes cognitive load and enforces best practices.
4+
5+
---
6+
7+
## Core Principles
8+
9+
**Feature-First Development** – Features are self-contained and organized around routes.\
10+
**Minimal Cognitive Load** – Engineers should immediately know where code belongs.\
11+
**Predictability & Consistency** – Every feature follows the same structure.\
12+
**No Unnecessary Abstractions** – Complexity is only introduced when necessary.\
13+
**Automation Over Convention** – Enforceable via ESLint/Prettier instead of manual rules.\
14+
15+
📖 **Additional Resources:**
16+
17+
- [Google TypeScript Style Guide](https://google.github.io/styleguide/tsguide.html)
18+
- [Airbnb React Style Guide](https://airbnb.io/javascript/react/)
19+
20+
---
21+
22+
## Feature-First Folder Structure
23+
24+
### **What is a Feature?**
25+
26+
A **feature** is a **self-contained module** that represents:
27+
28+
- A **route** (`/guides/:guideId`)
29+
- A **significant UI section**
30+
- **Reusable business logic specific to a domain**
31+
32+
### **Feature Structure Example**
33+
34+
```
35+
pages/guides/search → Feature (route: `/guides/search`)
36+
GuideSearch.tsx → Main component
37+
38+
pages/guides/:guideId → Feature (route: `/guides/:guideId`)
39+
Guide.tsx → Main component
40+
hooks/useGetGuideQuery.ts → Query for getting details
41+
hooks/useGuideMetricShare.ts → Handles copy-to-clipboard/sharing
42+
components/GuideHero.tsx → Feature-scoped component
43+
44+
pages/profile/:accountHandle → Feature (route: `/profile/:accountHandle`)
45+
Profile.tsx → Main component
46+
47+
pages/profile/:accountHandle/guides → Feature (route: `/profile/:accountHandle/guides`)
48+
ProfileGuides.tsx → Main component
49+
```
50+
51+
**Flat structure:** No deep nesting inside features.\
52+
**Feature-scoped:** Hooks and components belong inside the feature they support.\
53+
**No `common/` folder** – Instead, use `src/hooks/` for sitewide hooks and `src/components/` for reusable components.
54+
55+
---
56+
57+
## Component Structure
58+
59+
**Ordering Inside a Component:**\
60+
1️⃣ **Hooks** (`useState`, `useEffect`, etc.)
61+
2️⃣ **Local Variables** (constants, derived values)
62+
3️⃣ **useEffect Hooks** (side effects, lifecycle logic)
63+
4️⃣ **Event Handlers & Functions**
64+
5️⃣ **Return Statement (JSX)**
65+
66+
**Example Component:**
67+
68+
```tsx
69+
export const Profile = () => {
70+
const { hasError, isLoading, profileData } = useGetProfileQuery()
71+
72+
if (isLoading) return <ProfileLoading />
73+
74+
if (hasError) return <ProfileEmpty />
75+
76+
return (
77+
<section>
78+
<ProfileHero />
79+
<ProfileContent />
80+
</section>
81+
)
82+
}
83+
```
84+
85+
---
86+
87+
## Naming Conventions
88+
89+
| Item | Naming Convention |
90+
| --------------------------------- | ---------------------------------------------------------- |
91+
| **Variables, Functions, Hooks** | `camelCase` (e.g., `getUserProfile`) |
92+
| **Components, Enums, Interfaces** | `PascalCase` (e.g., `UserProfileCard`) |
93+
| **Folders** | `kebab-case` (e.g., `profile-settings/`) |
94+
| **Constants** | Defined within feature files, not in a global folder. |
95+
| **GraphQL Queries/Mutations** | `camelCase` inside operations, `PascalCase` for file names |
96+
97+
---
98+
99+
## GraphQL Queries & Mutations
100+
101+
| Type | Placement |
102+
| ------------------------- | --------------------------------- |
103+
| **Feature-based Queries** | Inside `pages/featureName/hooks/` |
104+
| **Sitewide Queries** | Inside `src/hooks/` |
105+
106+
**Correct Naming Examples:**
107+
108+
```graphql
109+
query GetGuide($id: ID!) { ... } # ✅ Fetches full guide details
110+
query GetGuideEvents($guideId: ID!) { ... } # ✅ Fetches related guide events
111+
query GetGuideImages($guideId: ID!) { ... } # ✅ Fetches guide images
112+
```
113+
114+
📖 **Additional Resources:**
115+
116+
- [GraphQL Best Practices](https://graphql.org/learn/best-practices/)
117+
118+
---
119+
120+
## Types & Interfaces
121+
122+
| When to Use | Rule |
123+
| -------------------------------------------------------------- | ------------------------------------------------------- |
124+
| **Props for Components** | Use `interface` (e.g., `interface ProfileProps {}`) |
125+
| **Everything Else (Utilities, Hooks, GraphQL, API Responses)** | Use `type` (e.g., `type UseGetProfileQueryResult = {}`) |
126+
| **Extracting Subsets of Types** | Use `Pick<>` and `Omit<>` |
127+
128+
**Additional Resources:**
129+
130+
- [TypeScript Handbook: Types vs. Interfaces](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html)
131+
132+
---
133+
134+
## Feature Flags
135+
136+
| Item | Rule |
137+
| ----------- | ----------------------------------------------------- |
138+
| **Storage** | Centralized in `config/feature-flags/featureFlags.ts` |
139+
| **Usage** | Accessed via `useFlag` hook |
140+
| **Cleanup** | Feature flags should be short-lived |
141+
142+
📖 **Additional Resources:**
143+
144+
- [Feature Flags Best Practices](https://martinfowler.com/articles/feature-toggles.html)
145+
146+
---
147+
148+
## ✍️ Comments & Documentation
149+
150+
**Code should be self-explanatory; avoid unnecessary comments.**
151+
**Use JSDoc `@todo` for tracking future work.**
152+
**Only document "why", not "what" the code does.**
153+
154+
**Example:**
155+
156+
```ts
157+
/** @todo Remove this workaround when the new API version is available */
158+
const getUserPreferences = async (userId: string) => {
159+
return await fetch(`/api/preferences/${userId}`)
160+
}
161+
```
162+
163+
**Additional Resources:**
164+
165+
- [Clean Code Principles](https://www.oreilly.com/library/view/clean-code/9780136083238/)
166+
167+
---
168+
169+
## Final Thoughts
170+
171+
**This cheat sheet ensures clarity, predictability, and minimal cognitive load.**
172+
173+
**Keep rules minimal & enforceable.**\
174+
**Follow automation-first principles.**\
175+
**Structure code in a way that scales naturally.**
176+
177+
This is your definitive **React + TypeScript Feature-First Style Guide**, designed to **reduce thinking, improve efficiency, and create scalable applications effortlessly.**

README.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
README.md

atro.config.mjs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { defineConfig } from 'astro/config'
2+
import mdx from '@astrojs/mdx'
3+
4+
export default defineConfig({
5+
integrations: [mdx()],
6+
site: 'https://react-typescript-feature-style-guide.vercel.app',
7+
})

0 commit comments

Comments
 (0)