agentleFS
Workshop-VenturesWorkshop-Ventures/skills/new-project-scaffolding/SKILL.md

new-project-scaffolding

Skill1 starsChanged 10 months agoMITView on GitHub

Scaffold a new Nx monorepo project with backend, frontend, shared types library, justfile commands, and direnv setup. Use when starting a fresh project or asked to "create a new project", "scaffold a monorepo", or "set up a new workspace".

  • Reads credentials
  • Deletes or force-pushes
  • Installs packages

1 other project uses a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

7 rules. About 0 are common, 0 are distinctive, and 7 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈0

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 7

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    After generation, update libs/types/package.json:

    line 88
  2. Very specific:

    Update tsconfig.base.json to include the types library path:

    line 114
  3. Very specific:

    Create scripts/example-script.ts as a template:

    line 149
  4. Very specific:

    Create justfile in the project root:

    line 176
  5. Very specific:

    Add these entries to .gitignore:

    line 305
  6. Very specific:

    Update nx.json with recommended settings:

    line 335
  7. Very specific:

    Run npx nx reset to clear cache

    line 485

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

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:

  1. Install dependencies: npm install
  2. Allow direnv: direnv allow
  3. Test backend: just serve-backend
  4. Test frontend: just serve-webapp
  5. Test both: just serve-all
  6. 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:

  1. Path is in tsconfig.base.json
  2. Restart your IDE/editor
  3. Run npx nx reset to clear cache

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.