@regression-io/claude-config 0.14.16
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/LICENSE +21 -0
- package/README.md +286 -0
- package/cli.js +260 -0
- package/config-loader.js +1556 -0
- package/package.json +62 -0
- package/scripts/postinstall.js +50 -0
- package/scripts/sync-version.js +65 -0
- package/shared/mcp-registry.json +117 -0
- package/templates/composites/fastapi-react-js/rules/backend-python.md +54 -0
- package/templates/composites/fastapi-react-js/rules/frontend-react.md +69 -0
- package/templates/composites/fastapi-react-js/rules/monorepo.md +77 -0
- package/templates/composites/fastapi-react-js/template.json +7 -0
- package/templates/composites/fastapi-react-ts/rules/backend-python.md +54 -0
- package/templates/composites/fastapi-react-ts/rules/frontend-react.md +64 -0
- package/templates/composites/fastapi-react-ts/rules/monorepo.md +82 -0
- package/templates/composites/fastapi-react-ts/template.json +7 -0
- package/templates/frameworks/fastapi/rules/dependencies.md +89 -0
- package/templates/frameworks/fastapi/rules/endpoints.md +86 -0
- package/templates/frameworks/fastapi/rules/errors.md +101 -0
- package/templates/frameworks/fastapi/rules/structure.md +97 -0
- package/templates/frameworks/fastapi/template.json +6 -0
- package/templates/frameworks/mcp-python/rules/resources.md +93 -0
- package/templates/frameworks/mcp-python/rules/structure.md +74 -0
- package/templates/frameworks/mcp-python/rules/tools.md +80 -0
- package/templates/frameworks/mcp-python/template.json +6 -0
- package/templates/frameworks/python-cli/rules/commands.md +103 -0
- package/templates/frameworks/python-cli/rules/output.md +107 -0
- package/templates/frameworks/python-cli/rules/structure.md +91 -0
- package/templates/frameworks/python-cli/template.json +6 -0
- package/templates/frameworks/react-js/rules/components.md +84 -0
- package/templates/frameworks/react-js/rules/hooks.md +98 -0
- package/templates/frameworks/react-js/template.json +6 -0
- package/templates/frameworks/react-ts/rules/components.md +72 -0
- package/templates/frameworks/react-ts/rules/hooks.md +87 -0
- package/templates/frameworks/react-ts/rules/state.md +93 -0
- package/templates/frameworks/react-ts/template.json +6 -0
- package/templates/languages/javascript/rules/patterns.md +126 -0
- package/templates/languages/javascript/rules/style.md +92 -0
- package/templates/languages/javascript/template.json +6 -0
- package/templates/languages/python/rules/dependencies.md +77 -0
- package/templates/languages/python/rules/patterns.md +95 -0
- package/templates/languages/python/rules/style.md +63 -0
- package/templates/languages/python/template.json +6 -0
- package/templates/languages/typescript/rules/config.md +95 -0
- package/templates/languages/typescript/rules/patterns.md +119 -0
- package/templates/languages/typescript/rules/style.md +82 -0
- package/templates/languages/typescript/template.json +6 -0
- package/templates/universal/commands/commit.md +53 -0
- package/templates/universal/commands/debug.md +53 -0
- package/templates/universal/commands/document.md +54 -0
- package/templates/universal/commands/review.md +45 -0
- package/templates/universal/commands/security-review.md +52 -0
- package/templates/universal/commands/test.md +46 -0
- package/templates/universal/rules/api-design.md +38 -0
- package/templates/universal/rules/code-quality.md +40 -0
- package/templates/universal/rules/documentation.md +38 -0
- package/templates/universal/rules/error-handling.md +37 -0
- package/templates/universal/rules/git-workflow.md +39 -0
- package/templates/universal/rules/security.md +39 -0
- package/templates/universal/rules/testing.md +38 -0
- package/templates/universal/template.json +6 -0
- package/ui/dist/assets/index-C5apzulu.css +32 -0
- package/ui/dist/assets/index-CBNCwCnY.js +489 -0
- package/ui/dist/index.html +14 -0
- package/ui/server.cjs +2237 -0
- package/ui/terminal-server.cjs +160 -0
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@regression-io/claude-config",
|
|
3
|
+
"version": "0.14.16",
|
|
4
|
+
"description": "Configuration management UI for Claude Code - manage MCPs, rules, commands, memory, and .claude folders",
|
|
5
|
+
"author": "regression.io",
|
|
6
|
+
"main": "config-loader.js",
|
|
7
|
+
"type": "commonjs",
|
|
8
|
+
"bin": {
|
|
9
|
+
"claude-config": "cli.js"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"start": "node cli.js ui",
|
|
13
|
+
"display": "node cli.js display",
|
|
14
|
+
"ui": "node cli.js ui",
|
|
15
|
+
"ui:dev": "cd ui && npm run dev",
|
|
16
|
+
"ui:build": "cd ui && npm run build",
|
|
17
|
+
"version:sync": "node scripts/sync-version.js",
|
|
18
|
+
"version:bump": "node scripts/sync-version.js --bump",
|
|
19
|
+
"build": "npm run version:bump && cd ui && npm install && npm run build",
|
|
20
|
+
"prepublishOnly": "npm run build",
|
|
21
|
+
"postinstall": "node scripts/postinstall.js",
|
|
22
|
+
"test": "node --test test/*.test.js"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"claude",
|
|
26
|
+
"claude-code",
|
|
27
|
+
"anthropic",
|
|
28
|
+
"configuration",
|
|
29
|
+
"mcp",
|
|
30
|
+
"model-context-protocol",
|
|
31
|
+
"project-management",
|
|
32
|
+
"cli"
|
|
33
|
+
],
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"js-yaml": "^4.1.1",
|
|
37
|
+
"node-pty": "^1.1.0",
|
|
38
|
+
"ws": "^8.19.0"
|
|
39
|
+
},
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=18.0.0"
|
|
42
|
+
},
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "git+https://github.com/regression-io/claude-config.git"
|
|
46
|
+
},
|
|
47
|
+
"bugs": {
|
|
48
|
+
"url": "https://github.com/regression-io/claude-config/issues"
|
|
49
|
+
},
|
|
50
|
+
"homepage": "https://github.com/regression-io/claude-config#readme",
|
|
51
|
+
"files": [
|
|
52
|
+
"cli.js",
|
|
53
|
+
"config-loader.js",
|
|
54
|
+
"ui/server.cjs",
|
|
55
|
+
"ui/terminal-server.cjs",
|
|
56
|
+
"ui/dist/**",
|
|
57
|
+
"templates/**",
|
|
58
|
+
"shared/**",
|
|
59
|
+
"scripts/**",
|
|
60
|
+
"README.md"
|
|
61
|
+
]
|
|
62
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Post-install script for claude-config
|
|
5
|
+
* Sets up default configuration if not present
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const os = require('os');
|
|
11
|
+
|
|
12
|
+
const home = os.homedir();
|
|
13
|
+
const claudeDir = path.join(home, '.claude');
|
|
14
|
+
const configPath = path.join(claudeDir, 'config.json');
|
|
15
|
+
|
|
16
|
+
// Default configuration
|
|
17
|
+
const defaultConfig = {
|
|
18
|
+
toolsDir: path.join(home, 'mcp-tools'),
|
|
19
|
+
registryPath: path.join(claudeDir, 'registry.json'),
|
|
20
|
+
ui: {
|
|
21
|
+
port: 3333,
|
|
22
|
+
openBrowser: true
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Create ~/.claude if it doesn't exist
|
|
27
|
+
if (!fs.existsSync(claudeDir)) {
|
|
28
|
+
fs.mkdirSync(claudeDir, { recursive: true });
|
|
29
|
+
console.log('Created ~/.claude directory');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Create config.json if it doesn't exist
|
|
33
|
+
if (!fs.existsSync(configPath)) {
|
|
34
|
+
fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2) + '\n');
|
|
35
|
+
console.log('Created ~/.claude/config.json with defaults');
|
|
36
|
+
console.log(` Tools directory: ${defaultConfig.toolsDir}`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Create default registry if it doesn't exist
|
|
40
|
+
const registryPath = path.join(claudeDir, 'registry.json');
|
|
41
|
+
if (!fs.existsSync(registryPath)) {
|
|
42
|
+
const defaultRegistry = {
|
|
43
|
+
mcpServers: {}
|
|
44
|
+
};
|
|
45
|
+
fs.writeFileSync(registryPath, JSON.stringify(defaultRegistry, null, 2) + '\n');
|
|
46
|
+
console.log('Created ~/.claude/registry.json');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
console.log('\nClaude Config installed successfully!');
|
|
50
|
+
console.log('Run "claude-config" to start the UI.\n');
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Sync version from package.json to all version locations
|
|
5
|
+
* This ensures version is consistent across the codebase
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* node sync-version.js # Sync current version
|
|
9
|
+
* node sync-version.js --bump # Bump patch version then sync
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
|
|
15
|
+
const rootDir = path.join(__dirname, '..');
|
|
16
|
+
const packageJsonPath = path.join(rootDir, 'package.json');
|
|
17
|
+
const configLoaderPath = path.join(rootDir, 'config-loader.js');
|
|
18
|
+
const uiPackageJsonPath = path.join(rootDir, 'ui', 'package.json');
|
|
19
|
+
|
|
20
|
+
// Read version from package.json (source of truth)
|
|
21
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
22
|
+
let version = packageJson.version;
|
|
23
|
+
|
|
24
|
+
// Check for --bump flag
|
|
25
|
+
const shouldBump = process.argv.includes('--bump');
|
|
26
|
+
|
|
27
|
+
if (shouldBump) {
|
|
28
|
+
// Bump patch version
|
|
29
|
+
const parts = version.split('.');
|
|
30
|
+
parts[2] = parseInt(parts[2], 10) + 1;
|
|
31
|
+
version = parts.join('.');
|
|
32
|
+
|
|
33
|
+
// Update package.json with new version
|
|
34
|
+
packageJson.version = version;
|
|
35
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n', 'utf8');
|
|
36
|
+
console.log(`Bumped version: ${packageJson.version.replace(/\.\d+$/, `.${parseInt(parts[2]) - 1}`)} -> ${version}`);
|
|
37
|
+
} else {
|
|
38
|
+
console.log(`Syncing version: ${version}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Update config-loader.js
|
|
42
|
+
let configLoader = fs.readFileSync(configLoaderPath, 'utf8');
|
|
43
|
+
const versionRegex = /const VERSION = ['"][^'"]+['"]/;
|
|
44
|
+
|
|
45
|
+
if (versionRegex.test(configLoader)) {
|
|
46
|
+
const oldVersion = configLoader.match(versionRegex)[0];
|
|
47
|
+
configLoader = configLoader.replace(versionRegex, `const VERSION = '${version}'`);
|
|
48
|
+
fs.writeFileSync(configLoaderPath, configLoader, 'utf8');
|
|
49
|
+
console.log(` config-loader.js: ${oldVersion} -> const VERSION = '${version}'`);
|
|
50
|
+
} else {
|
|
51
|
+
console.error('Warning: Could not find VERSION constant in config-loader.js');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Update ui/package.json
|
|
55
|
+
if (fs.existsSync(uiPackageJsonPath)) {
|
|
56
|
+
const uiPackageJson = JSON.parse(fs.readFileSync(uiPackageJsonPath, 'utf8'));
|
|
57
|
+
if (uiPackageJson.version !== version) {
|
|
58
|
+
const oldVersion = uiPackageJson.version;
|
|
59
|
+
uiPackageJson.version = version;
|
|
60
|
+
fs.writeFileSync(uiPackageJsonPath, JSON.stringify(uiPackageJson, null, 2) + '\n', 'utf8');
|
|
61
|
+
console.log(` ui/package.json: ${oldVersion} -> ${version}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
console.log('Version sync complete!');
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mcpServers": {
|
|
3
|
+
"github": {
|
|
4
|
+
"command": "npx",
|
|
5
|
+
"args": [
|
|
6
|
+
"-y",
|
|
7
|
+
"@modelcontextprotocol/server-github"
|
|
8
|
+
],
|
|
9
|
+
"env": {
|
|
10
|
+
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"gitlab": {
|
|
14
|
+
"command": "npx",
|
|
15
|
+
"args": [
|
|
16
|
+
"-y",
|
|
17
|
+
"@modelcontextprotocol/server-gitlab"
|
|
18
|
+
],
|
|
19
|
+
"env": {
|
|
20
|
+
"GITLAB_TOKEN": "${GITLAB_TOKEN}",
|
|
21
|
+
"GITLAB_URL": "${GITLAB_URL}"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"slack": {
|
|
25
|
+
"command": "npx",
|
|
26
|
+
"args": [
|
|
27
|
+
"-y",
|
|
28
|
+
"@modelcontextprotocol/server-slack"
|
|
29
|
+
],
|
|
30
|
+
"env": {
|
|
31
|
+
"SLACK_BOT_TOKEN": "${SLACK_BOT_TOKEN}",
|
|
32
|
+
"SLACK_TEAM_ID": "${SLACK_TEAM_ID}"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"postgres": {
|
|
36
|
+
"command": "npx",
|
|
37
|
+
"args": [
|
|
38
|
+
"-y",
|
|
39
|
+
"@modelcontextprotocol/server-postgres"
|
|
40
|
+
],
|
|
41
|
+
"env": {
|
|
42
|
+
"DATABASE_URL": "${DATABASE_URL}"
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"sqlite": {
|
|
46
|
+
"command": "npx",
|
|
47
|
+
"args": [
|
|
48
|
+
"-y",
|
|
49
|
+
"@modelcontextprotocol/server-sqlite"
|
|
50
|
+
],
|
|
51
|
+
"env": {
|
|
52
|
+
"SQLITE_PATH": "${SQLITE_PATH}"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"filesystem": {
|
|
56
|
+
"command": "npx",
|
|
57
|
+
"args": [
|
|
58
|
+
"-y",
|
|
59
|
+
"@modelcontextprotocol/server-filesystem",
|
|
60
|
+
"./"
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
"memory": {
|
|
64
|
+
"command": "npx",
|
|
65
|
+
"args": [
|
|
66
|
+
"-y",
|
|
67
|
+
"@modelcontextprotocol/server-memory"
|
|
68
|
+
]
|
|
69
|
+
},
|
|
70
|
+
"puppeteer": {
|
|
71
|
+
"command": "npx",
|
|
72
|
+
"args": [
|
|
73
|
+
"-y",
|
|
74
|
+
"@modelcontextprotocol/server-puppeteer"
|
|
75
|
+
]
|
|
76
|
+
},
|
|
77
|
+
"brave-search": {
|
|
78
|
+
"command": "npx",
|
|
79
|
+
"args": [
|
|
80
|
+
"-y",
|
|
81
|
+
"@modelcontextprotocol/server-brave-search"
|
|
82
|
+
],
|
|
83
|
+
"env": {
|
|
84
|
+
"BRAVE_API_KEY": "${BRAVE_API_KEY}"
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"fetch": {
|
|
88
|
+
"command": "npx",
|
|
89
|
+
"args": [
|
|
90
|
+
"-y",
|
|
91
|
+
"@modelcontextprotocol/server-fetch"
|
|
92
|
+
]
|
|
93
|
+
},
|
|
94
|
+
"google-drive": {
|
|
95
|
+
"command": "npx",
|
|
96
|
+
"args": [
|
|
97
|
+
"-y",
|
|
98
|
+
"@modelcontextprotocol/server-google-drive"
|
|
99
|
+
],
|
|
100
|
+
"env": {
|
|
101
|
+
"GOOGLE_DRIVE_CREDENTIALS": "${GOOGLE_DRIVE_CREDENTIALS}"
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
"aws-s3": {
|
|
105
|
+
"command": "npx",
|
|
106
|
+
"args": [
|
|
107
|
+
"-y",
|
|
108
|
+
"@modelcontextprotocol/server-aws-s3"
|
|
109
|
+
],
|
|
110
|
+
"env": {
|
|
111
|
+
"AWS_ACCESS_KEY_ID": "${AWS_ACCESS_KEY_ID}",
|
|
112
|
+
"AWS_SECRET_ACCESS_KEY": "${AWS_SECRET_ACCESS_KEY}",
|
|
113
|
+
"AWS_REGION": "${AWS_REGION}"
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
globs: backend/**
|
|
3
|
+
---
|
|
4
|
+
# Python Rules (Backend)
|
|
5
|
+
|
|
6
|
+
These rules apply to the FastAPI backend in `backend/`.
|
|
7
|
+
|
|
8
|
+
## Style
|
|
9
|
+
- Use 4 spaces for indentation
|
|
10
|
+
- `snake_case` for functions/variables, `PascalCase` for classes
|
|
11
|
+
- Type hints on all public functions
|
|
12
|
+
- Google-style docstrings
|
|
13
|
+
|
|
14
|
+
## Patterns
|
|
15
|
+
```python
|
|
16
|
+
# Use Pydantic for validation
|
|
17
|
+
from pydantic import BaseModel
|
|
18
|
+
|
|
19
|
+
class UserCreate(BaseModel):
|
|
20
|
+
name: str
|
|
21
|
+
email: EmailStr
|
|
22
|
+
|
|
23
|
+
# Use dependency injection
|
|
24
|
+
async def get_user(
|
|
25
|
+
user_id: int,
|
|
26
|
+
db: AsyncSession = Depends(get_db),
|
|
27
|
+
) -> User:
|
|
28
|
+
...
|
|
29
|
+
|
|
30
|
+
# Async context managers for resources
|
|
31
|
+
async with async_session() as session:
|
|
32
|
+
...
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Project Structure
|
|
36
|
+
```
|
|
37
|
+
backend/
|
|
38
|
+
├── src/api/
|
|
39
|
+
│ ├── main.py # FastAPI app
|
|
40
|
+
│ ├── config.py # Settings
|
|
41
|
+
│ ├── dependencies.py # DI
|
|
42
|
+
│ ├── routers/ # Endpoints
|
|
43
|
+
│ ├── models/ # SQLAlchemy
|
|
44
|
+
│ ├── schemas/ # Pydantic
|
|
45
|
+
│ └── services/ # Business logic
|
|
46
|
+
├── tests/
|
|
47
|
+
└── pyproject.toml
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Testing
|
|
51
|
+
```bash
|
|
52
|
+
cd backend
|
|
53
|
+
pytest -v --cov=src
|
|
54
|
+
```
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
globs: frontend/**
|
|
3
|
+
---
|
|
4
|
+
# React JavaScript Rules (Frontend)
|
|
5
|
+
|
|
6
|
+
These rules apply to the React frontend in `frontend/`.
|
|
7
|
+
|
|
8
|
+
## Style
|
|
9
|
+
- Functional components only
|
|
10
|
+
- `PascalCase` for components, `camelCase` for functions
|
|
11
|
+
- PropTypes for runtime validation
|
|
12
|
+
- Named exports preferred
|
|
13
|
+
|
|
14
|
+
## Component Pattern
|
|
15
|
+
```javascript
|
|
16
|
+
import PropTypes from 'prop-types';
|
|
17
|
+
|
|
18
|
+
export function UserCard({ user, onEdit }) {
|
|
19
|
+
return (
|
|
20
|
+
<div>
|
|
21
|
+
<h3>{user.name}</h3>
|
|
22
|
+
{onEdit && <button onClick={() => onEdit(user)}>Edit</button>}
|
|
23
|
+
</div>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
UserCard.propTypes = {
|
|
28
|
+
user: PropTypes.shape({
|
|
29
|
+
id: PropTypes.number.isRequired,
|
|
30
|
+
name: PropTypes.string.isRequired,
|
|
31
|
+
}).isRequired,
|
|
32
|
+
onEdit: PropTypes.func,
|
|
33
|
+
};
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Project Structure
|
|
37
|
+
```
|
|
38
|
+
frontend/
|
|
39
|
+
├── src/
|
|
40
|
+
│ ├── components/
|
|
41
|
+
│ │ ├── ui/ # Reusable (Button, Input)
|
|
42
|
+
│ │ └── features/ # Domain-specific
|
|
43
|
+
│ ├── hooks/ # Custom hooks
|
|
44
|
+
│ ├── pages/ # Route pages
|
|
45
|
+
│ ├── services/ # API calls
|
|
46
|
+
│ └── utils/
|
|
47
|
+
├── package.json
|
|
48
|
+
└── jsconfig.json
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## API Integration
|
|
52
|
+
```javascript
|
|
53
|
+
/**
|
|
54
|
+
* @param {number} id
|
|
55
|
+
* @returns {Promise<import('../../shared/api-types').User>}
|
|
56
|
+
*/
|
|
57
|
+
async function fetchUser(id) {
|
|
58
|
+
const res = await fetch(`/api/users/${id}`);
|
|
59
|
+
if (!res.ok) throw new Error('Failed to fetch');
|
|
60
|
+
return res.json();
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Testing
|
|
65
|
+
```bash
|
|
66
|
+
cd frontend
|
|
67
|
+
npm run test
|
|
68
|
+
npm run lint
|
|
69
|
+
```
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# FastAPI + React JavaScript Monorepo Rules
|
|
2
|
+
|
|
3
|
+
## Project Structure
|
|
4
|
+
```
|
|
5
|
+
project/
|
|
6
|
+
├── backend/ # FastAPI Python
|
|
7
|
+
│ ├── src/
|
|
8
|
+
│ │ └── api/
|
|
9
|
+
│ ├── tests/
|
|
10
|
+
│ ├── pyproject.toml
|
|
11
|
+
│ └── .env
|
|
12
|
+
├── frontend/ # React JavaScript
|
|
13
|
+
│ ├── src/
|
|
14
|
+
│ ├── package.json
|
|
15
|
+
│ └── jsconfig.json
|
|
16
|
+
├── shared/ # Shared types via JSDoc
|
|
17
|
+
│ └── api-types.js
|
|
18
|
+
├── docker-compose.yml
|
|
19
|
+
├── .claude/
|
|
20
|
+
│ └── mcps.json
|
|
21
|
+
└── CLAUDE.md
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Path-Scoped Rules
|
|
25
|
+
This monorepo uses path-scoped rules:
|
|
26
|
+
|
|
27
|
+
- `/backend/**` → Python + FastAPI rules
|
|
28
|
+
- `/frontend/**` → JavaScript + React rules
|
|
29
|
+
- `/**` → Universal rules
|
|
30
|
+
|
|
31
|
+
## Shared Types (JSDoc)
|
|
32
|
+
```javascript
|
|
33
|
+
// shared/api-types.js
|
|
34
|
+
/**
|
|
35
|
+
* @typedef {Object} User
|
|
36
|
+
* @property {number} id
|
|
37
|
+
* @property {string} name
|
|
38
|
+
* @property {string} email
|
|
39
|
+
* @property {string} createdAt
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @typedef {Object} CreateUserRequest
|
|
44
|
+
* @property {string} name
|
|
45
|
+
* @property {string} email
|
|
46
|
+
* @property {string} password
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @typedef {Object} ApiError
|
|
51
|
+
* @property {{code: string, message: string, details?: any}} error
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
export {};
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Backend/Frontend Communication
|
|
58
|
+
- Backend generates OpenAPI schema
|
|
59
|
+
- Use PropTypes for runtime validation in React
|
|
60
|
+
- Keep JSDoc types in sync with backend schemas
|
|
61
|
+
- Consistent error handling format
|
|
62
|
+
|
|
63
|
+
## Development Workflow
|
|
64
|
+
```bash
|
|
65
|
+
# Start both services
|
|
66
|
+
docker-compose up
|
|
67
|
+
|
|
68
|
+
# Or separately:
|
|
69
|
+
cd backend && uvicorn src.api.main:app --reload
|
|
70
|
+
cd frontend && npm run dev
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Testing Strategy
|
|
74
|
+
- Backend: pytest
|
|
75
|
+
- Frontend: Jest + Testing Library
|
|
76
|
+
- E2E: Playwright
|
|
77
|
+
- Manual API testing with Postman/httpie
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fastapi-react-js",
|
|
3
|
+
"description": "FastAPI backend + React JavaScript frontend monorepo",
|
|
4
|
+
"includes": ["universal"],
|
|
5
|
+
"mcpDefaults": ["github", "filesystem", "postgres"],
|
|
6
|
+
"_note": "Uses path-scoped rules in backend-python.md and frontend-react.md"
|
|
7
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
globs: backend/**
|
|
3
|
+
---
|
|
4
|
+
# Python Rules (Backend)
|
|
5
|
+
|
|
6
|
+
These rules apply to the FastAPI backend in `backend/`.
|
|
7
|
+
|
|
8
|
+
## Style
|
|
9
|
+
- Use 4 spaces for indentation
|
|
10
|
+
- `snake_case` for functions/variables, `PascalCase` for classes
|
|
11
|
+
- Type hints on all public functions
|
|
12
|
+
- Google-style docstrings
|
|
13
|
+
|
|
14
|
+
## Patterns
|
|
15
|
+
```python
|
|
16
|
+
# Use Pydantic for validation
|
|
17
|
+
from pydantic import BaseModel
|
|
18
|
+
|
|
19
|
+
class UserCreate(BaseModel):
|
|
20
|
+
name: str
|
|
21
|
+
email: EmailStr
|
|
22
|
+
|
|
23
|
+
# Use dependency injection
|
|
24
|
+
async def get_user(
|
|
25
|
+
user_id: int,
|
|
26
|
+
db: AsyncSession = Depends(get_db),
|
|
27
|
+
) -> User:
|
|
28
|
+
...
|
|
29
|
+
|
|
30
|
+
# Async context managers for resources
|
|
31
|
+
async with async_session() as session:
|
|
32
|
+
...
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Project Structure
|
|
36
|
+
```
|
|
37
|
+
backend/
|
|
38
|
+
├── src/api/
|
|
39
|
+
│ ├── main.py # FastAPI app
|
|
40
|
+
│ ├── config.py # Settings
|
|
41
|
+
│ ├── dependencies.py # DI
|
|
42
|
+
│ ├── routers/ # Endpoints
|
|
43
|
+
│ ├── models/ # SQLAlchemy
|
|
44
|
+
│ ├── schemas/ # Pydantic
|
|
45
|
+
│ └── services/ # Business logic
|
|
46
|
+
├── tests/
|
|
47
|
+
└── pyproject.toml
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Testing
|
|
51
|
+
```bash
|
|
52
|
+
cd backend
|
|
53
|
+
pytest -v --cov=src
|
|
54
|
+
```
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
globs: frontend/**
|
|
3
|
+
---
|
|
4
|
+
# React TypeScript Rules (Frontend)
|
|
5
|
+
|
|
6
|
+
These rules apply to the React frontend in `frontend/`.
|
|
7
|
+
|
|
8
|
+
## Style
|
|
9
|
+
- Functional components only
|
|
10
|
+
- `PascalCase` for components, `camelCase` for functions
|
|
11
|
+
- Explicit TypeScript types for props
|
|
12
|
+
- Named exports preferred
|
|
13
|
+
|
|
14
|
+
## Component Pattern
|
|
15
|
+
```typescript
|
|
16
|
+
interface UserCardProps {
|
|
17
|
+
user: User;
|
|
18
|
+
onEdit?: (user: User) => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function UserCard({ user, onEdit }: UserCardProps) {
|
|
22
|
+
return (
|
|
23
|
+
<div>
|
|
24
|
+
<h3>{user.name}</h3>
|
|
25
|
+
{onEdit && <button onClick={() => onEdit(user)}>Edit</button>}
|
|
26
|
+
</div>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Project Structure
|
|
32
|
+
```
|
|
33
|
+
frontend/
|
|
34
|
+
├── src/
|
|
35
|
+
│ ├── components/
|
|
36
|
+
│ │ ├── ui/ # Reusable (Button, Input)
|
|
37
|
+
│ │ └── features/ # Domain-specific
|
|
38
|
+
│ ├── hooks/ # Custom hooks
|
|
39
|
+
│ ├── pages/ # Route pages
|
|
40
|
+
│ ├── services/ # API calls
|
|
41
|
+
│ ├── types/ # TypeScript types
|
|
42
|
+
│ └── utils/
|
|
43
|
+
├── package.json
|
|
44
|
+
└── tsconfig.json
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## API Integration
|
|
48
|
+
```typescript
|
|
49
|
+
// Use shared types from ../shared/
|
|
50
|
+
import type { User, ApiError } from '../../shared/api-types';
|
|
51
|
+
|
|
52
|
+
async function fetchUser(id: number): Promise<User> {
|
|
53
|
+
const res = await fetch(`/api/users/${id}`);
|
|
54
|
+
if (!res.ok) throw new Error('Failed to fetch');
|
|
55
|
+
return res.json();
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Testing
|
|
60
|
+
```bash
|
|
61
|
+
cd frontend
|
|
62
|
+
npm run test
|
|
63
|
+
npm run typecheck
|
|
64
|
+
```
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# FastAPI + React TypeScript Monorepo Rules
|
|
2
|
+
|
|
3
|
+
## Project Structure
|
|
4
|
+
```
|
|
5
|
+
project/
|
|
6
|
+
├── backend/ # FastAPI Python
|
|
7
|
+
│ ├── src/
|
|
8
|
+
│ │ └── api/
|
|
9
|
+
│ ├── tests/
|
|
10
|
+
│ ├── pyproject.toml
|
|
11
|
+
│ └── .env
|
|
12
|
+
├── frontend/ # React TypeScript
|
|
13
|
+
│ ├── src/
|
|
14
|
+
│ ├── package.json
|
|
15
|
+
│ └── tsconfig.json
|
|
16
|
+
├── shared/ # Shared types/contracts
|
|
17
|
+
│ └── api-types.ts
|
|
18
|
+
├── docker-compose.yml
|
|
19
|
+
├── .claude/
|
|
20
|
+
│ └── mcps.json
|
|
21
|
+
└── CLAUDE.md
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Path-Scoped Rules
|
|
25
|
+
This monorepo uses path-scoped rules. Rules apply to specific directories:
|
|
26
|
+
|
|
27
|
+
- `/backend/**` → Python + FastAPI rules
|
|
28
|
+
- `/frontend/**` → TypeScript + React rules
|
|
29
|
+
- `/**` → Universal rules
|
|
30
|
+
|
|
31
|
+
## API Contract
|
|
32
|
+
```typescript
|
|
33
|
+
// shared/api-types.ts
|
|
34
|
+
// Generate from FastAPI OpenAPI schema
|
|
35
|
+
// or define manually and share
|
|
36
|
+
|
|
37
|
+
export interface User {
|
|
38
|
+
id: number;
|
|
39
|
+
name: string;
|
|
40
|
+
email: string;
|
|
41
|
+
createdAt: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface CreateUserRequest {
|
|
45
|
+
name: string;
|
|
46
|
+
email: string;
|
|
47
|
+
password: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface ApiError {
|
|
51
|
+
error: {
|
|
52
|
+
code: string;
|
|
53
|
+
message: string;
|
|
54
|
+
details?: unknown;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Backend/Frontend Communication
|
|
60
|
+
- Backend generates OpenAPI schema: `GET /openapi.json`
|
|
61
|
+
- Frontend can use generated types from OpenAPI
|
|
62
|
+
- Keep shared types in sync
|
|
63
|
+
- Use consistent error format
|
|
64
|
+
|
|
65
|
+
## Development Workflow
|
|
66
|
+
```bash
|
|
67
|
+
# Start both services
|
|
68
|
+
docker-compose up
|
|
69
|
+
|
|
70
|
+
# Or separately:
|
|
71
|
+
# Backend
|
|
72
|
+
cd backend && uvicorn src.api.main:app --reload
|
|
73
|
+
|
|
74
|
+
# Frontend
|
|
75
|
+
cd frontend && npm run dev
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Testing Strategy
|
|
79
|
+
- Backend: pytest with TestClient
|
|
80
|
+
- Frontend: Vitest + Testing Library
|
|
81
|
+
- E2E: Playwright against both services
|
|
82
|
+
- Contract tests: Verify API matches types
|