new-project-scaffolding
npx skills add https://github.com/workshop-ventures/skills --skill new-project-scaffolding
Agent 安装分布
Skill 文档
New Project Scaffolding
This skill guides you through scaffolding a new Nx monorepo with a standard structure including backend API, frontend web app, shared types library, and essential tooling (Just, direnv).
Project Structure Overview
{project-name}/
âââ apps/
â âââ backend/ # Node.js/Koa backend API
â âââ webapp/ # React frontend application
âââ libs/
â âââ types/ # Shared TypeScript types (@{project}/types)
âââ scripts/ # Utility TypeScript scripts (run with vite-node)
âââ .envrc # direnv configuration
âââ .env.example # Environment variable template
âââ .env.local # Local environment variables (gitignored)
âââ justfile # Task runner commands
âââ nx.json # Nx configuration
âââ tsconfig.base.json # Base TypeScript configuration
âââ package.json # Root package.json
Scaffolding Steps
Step 1: Create Nx Workspace
npx create-nx-workspace@latest {project-name} \
--preset=ts \
--packageManager=npm \
--nxCloud=skip \
--interactive=false
This creates a minimal TypeScript workspace. The --preset=ts gives us a clean slate to add exactly what we need.
Step 2: Install Required Nx Plugins
cd {project-name}
npm install -D @nx/node @nx/react @nx/webpack @nx/jest @nx/eslint
Step 3: Generate Backend Application
npx nx generate @nx/node:application \
--name=backend \
--directory=apps/backend \
--framework=express \
--projectNameAndRootFormat=as-provided \
--e2eTestRunner=none \
--unitTestRunner=jest
Step 4: Generate Frontend Application
npx nx generate @nx/react:application \
--name=webapp \
--directory=apps/webapp \
--projectNameAndRootFormat=as-provided \
--bundler=webpack \
--style=css \
--routing=true \
--e2eTestRunner=none \
--unitTestRunner=jest
Step 5: Generate Shared Types Library
npx nx generate @nx/js:library \
--name=types \
--directory=libs/types \
--projectNameAndRootFormat=as-provided \
--unitTestRunner=jest \
--bundler=tsc \
--strict
After generation, update libs/types/package.json:
{
"name": "@{project}/types",
"version": "0.0.1",
"private": true,
"type": "module",
"main": "./src/index.ts",
"types": "./src/index.ts",
"exports": {
"./package.json": "./package.json",
".": {
"types": "./src/index.ts",
"import": "./src/index.ts",
"default": "./src/index.ts"
}
},
"dependencies": {
"tslib": "^2.3.0"
}
}
Step 6: Configure TypeScript Path Aliases
Update tsconfig.base.json to include the types library path:
{
"compilerOptions": {
"composite": true,
"declaration": true,
"declarationMap": true,
"importHelpers": true,
"isolatedModules": true,
"lib": ["es2022"],
"module": "esnext",
"moduleResolution": "bundler",
"noEmitOnError": true,
"noFallthroughCasesInSwitch": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
"skipLibCheck": true,
"strict": true,
"target": "es2022",
"baseUrl": ".",
"paths": {
"@{project}/types": ["libs/types/src/index.ts"]
}
}
}
Step 7: Create Scripts Directory
mkdir -p scripts
Create scripts/example-script.ts as a template:
/**
* Example utility script
* Run with: npx vite-node scripts/example-script.ts
*/
const run = async () => {
console.log('Script executed successfully');
process.exit(0);
};
run().catch((error) => {
console.error('Error:', error);
process.exit(1);
});
Install vite-node for running scripts:
npm install -D vite-node
Step 8: Create justfile
Create justfile in the project root:
# {Project Name} - Just Command Runner
# Run `just --list` to see all available commands
# Default recipe to display help
default:
@just --list
# === Development ===
# Serve backend
serve-backend:
echo "Starting backend..."
npx nx serve backend
# Serve webapp
serve-webapp:
echo "Starting webapp..."
npx nx serve webapp
# Serve all projects in parallel (backend + webapp)
serve-all:
echo "Starting all projects..."
npx nx run-many --targets=serve --projects=backend,webapp --parallel=2
# Serve with debugger
serve-all-debug:
echo "Starting all projects with debugger..."
NODE_OPTIONS='--inspect' npx nx run-many --targets=serve --projects=backend,webapp --parallel=2
# === Building ===
# Build a specific project
build project:
echo "Building {{project}}..."
npx nx build {{project}}
# Build all projects
build-all:
echo "Building all projects..."
npx nx run-many --targets=build --all
# === Testing ===
# Run unit tests for a project
test project:
echo "Running tests for {{project}}..."
npx nx test {{project}}
# Run all tests
test-all:
echo "Running all tests..."
npx nx run-many --targets=test --all
# === Linting ===
# Lint a specific project
lint project:
echo "Linting {{project}}..."
npx nx lint {{project}} --fix
# Lint all projects
lint-all:
echo "Linting all projects..."
npx nx run-many --targets=lint --all --fix
# === Utilities ===
# Clean NX cache
clean:
echo "Cleaning NX cache..."
npx nx reset
# Show project details
show project:
npx nx show project {{project}}
# View dependency graph
graph:
npx nx graph
# Install dependencies
install:
npm install
# Generate a new library
gen-lib name:
npx nx generate @nx/js:library --name={{name}} --directory=libs/{{name}} --projectNameAndRootFormat=as-provided --unitTestRunner=jest --bundler=tsc --strict
# Run a TypeScript script
run-script script:
npx vite-node scripts/{{script}}.ts
Step 9: Set Up Environment Variables
Create .env.example:
# Database
MONGODB_URI=mongodb://localhost:27017/{project-name}
# Server
PORT=3005
NODE_ENV=development
# Frontend
VITE_API_URL=http://localhost:3005
# Add your environment variables here
Create .envrc:
# Use direnv to auto load environment variables upon entering this project directory
set -o allexport; source .env.local; set +o allexport
Copy to local:
cp .env.example .env.local
Step 10: Update .gitignore
Add these entries to .gitignore:
# Environment
.env.local
.env*.local
# Nx
.nx/cache
dist/
# Dependencies
node_modules/
# IDE
.idea/
.vscode/
*.swp
*.swo
# OS
.DS_Store
Thumbs.db
# Build outputs
*.tsbuildinfo
Step 11: Configure nx.json
Update nx.json with recommended settings:
{
"$schema": "./node_modules/nx/schemas/nx-schema.json",
"plugins": [
{
"plugin": "@nx/js/typescript",
"options": {
"typecheck": {
"targetName": "typecheck"
},
"build": {
"targetName": "build",
"configName": "tsconfig.lib.json",
"buildDepsName": "build-deps",
"watchDepsName": "watch-deps"
}
}
},
{
"plugin": "@nx/webpack/plugin",
"options": {
"buildTargetName": "build",
"serveTargetName": "serve",
"previewTargetName": "preview",
"buildDepsTargetName": "build-deps",
"watchDepsTargetName": "watch-deps",
"serveStaticTargetName": "serve-static"
}
},
{
"plugin": "@nx/eslint/plugin",
"options": {
"targetName": "lint"
}
},
{
"plugin": "@nx/jest/plugin",
"options": {
"targetName": "test"
}
}
],
"targetDefaults": {
"test": {
"dependsOn": ["^build"]
}
},
"generators": {
"@nx/react": {
"application": {
"babel": true,
"style": "css",
"linter": "eslint",
"bundler": "webpack"
},
"component": {
"style": "css"
},
"library": {
"style": "css",
"linter": "eslint"
}
}
},
"tui": {
"enabled": false
}
}
Post-Scaffolding Checklist
After scaffolding, verify:
- Install dependencies:
npm install - Allow direnv:
direnv allow - Test backend:
just serve-backend - Test frontend:
just serve-webapp - Test both:
just serve-all - View dependency graph:
just graph
Using Shared Types
In the backend, import types:
import { MyType } from '@{project}/types';
In the frontend, import types:
import type { MyType } from '@{project}/types';
Adding New Libraries
# Generate a new shared library
just gen-lib my-utils
# Or manually
npx nx generate @nx/js:library \
--name=my-utils \
--directory=libs/my-utils \
--projectNameAndRootFormat=as-provided \
--unitTestRunner=jest \
--bundler=tsc \
--strict
Then add the path alias to tsconfig.base.json:
{
"paths": {
"@{project}/types": ["libs/types/src/index.ts"],
"@{project}/my-utils": ["libs/my-utils/src/index.ts"]
}
}
Troubleshooting
NX Cache Issues
just clean
# or
npx nx reset
rm -rf .nx/cache
Port Already in Use
lsof -i :3005
kill -9 <PID>
direnv Not Loading
direnv allow
direnv status
TypeScript Path Not Resolving
Ensure:
- Path is in
tsconfig.base.json - Restart your IDE/editor
- Run
npx nx resetto clear cache