npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

mern-starter-cli

v2.1.0

Published

CLI that scaffolds a complete MERN project: Express 5 + TypeScript layered backend, RS256 JWT auth, tests, Docker, and a React/Vite + shadcn/ui frontend

Readme

🚀 MERN Starter CLI

A CLI that scaffolds a complete MERN stack project (MongoDB, Express, React, Node.js) with production-grade authentication, a layered TypeScript backend, tests, Docker and a modern UI.

Stop rebuilding the same foundation on every project. Get started in two minutes. ⚡

npm version License: MIT Node.js Version

✨ Features

🔧 Backend (Express 5 + TypeScript)

  • ✅ Strict TypeScript in ESM, from the first file to the last
  • ✅ Layered architecture with a clear contract: routes → validators → controllers → services → repositories → models
  • ✅ Production-grade auth: RS256 JWT (15 min) + opaque refresh tokens, hashed and rotated (30 days), revocable
  • ✅ Two channels: Bearer header (mobile) and httpOnly cookies (web), the client picks
  • ✅ RBAC: roles and permissions re-read from the database on every request (bans take effect instantly)
  • ✅ Email verification and password reset through single-use tokens (Resend)
  • ✅ Account enumeration protection on login and forgot-password
  • ✅ Database: MongoDB + Mongoose (TTL indexes, idempotent seed)
  • ✅ 36 tests with Vitest + Supertest, on a dedicated test database
  • ✅ Quality: type-aware ESLint, Prettier, husky + lint-staged, GitHub Actions CI
  • ✅ Docker: dev compose (Mongo + API + front-end) and multi-stage production image

🎨 Frontend (React + Vite)

  • ✅ Modern design: Tailwind CSS v4 + shadcn/ui components
  • ✅ Complete pages: Login, Register, Dashboard, Profile, Forgot / Reset password, Email verification
  • ✅ State management: Redux Toolkit
  • ✅ Forms: React Hook Form + Yup (rules aligned with the server validators)
  • ✅ Notifications: React Hot Toast
  • ✅ Routing: React Router with protected routes (public / private)
  • ✅ Secure session: access token kept in memory (never in localStorage), automatic refresh on 401 and session restore on startup
  • ✅ Every API call already wired and working

📦 Installation

npm install -g mern-starter-cli

🚀 Usage

mern-starter-cli create

The CLI asks for your project name, then:

  1. ✅ Creates the full structure (client/ + server/) and the git repository
  2. ✅ Installs every dependency
  3. ✅ Updates the packages to their latest versions with ncu
  4. ✅ Configures Tailwind CSS v4 + shadcn/ui
  5. ✅ Copies all the pre-configured templates
  6. ✅ Generates your RS256 JWT keys and the backend .env — nothing to configure by hand

Requirements: Node.js ≥ 22, and a MongoDB database (local, Atlas, or the one from the bundled docker compose).

📁 Generated project structure

my-project/
├── client/                      # 🎨 React frontend
│   ├── src/
│   │   ├── api/                # API services
│   │   │   └── auth.js
│   │   ├── components/         # UI components (shadcn/ui)
│   │   │   └── ui/
│   │   ├── lib/                # Helpers
│   │   │   ├── axios.js        # Axios instance, refresh interceptor
│   │   │   └── utils.js
│   │   ├── pages/              # Application pages
│   │   │   ├── Login.jsx
│   │   │   ├── Register.jsx
│   │   │   ├── Dashboard.jsx
│   │   │   ├── Profile.jsx
│   │   │   ├── ForgotPassword.jsx
│   │   │   ├── ResetPassword.jsx
│   │   │   └── VerifyEmail.jsx
│   │   ├── schemas/            # Yup validation schemas
│   │   │   ├── login.schema.js
│   │   │   ├── register.schema.js
│   │   │   └── ...
│   │   ├── slices/             # Redux slices
│   │   │   └── authSlice.js
│   │   ├── store/              # Redux store
│   │   │   └── store.js
│   │   ├── App.jsx
│   │   └── main.jsx
│   ├── .npmrc
│   ├── .env / .env.example
│   ├── jsconfig.json           # @/ alias configured
│   ├── vite.config.js
│   └── package.json
│
└── server/                      # 🔧 Express 5 + TypeScript backend
    ├── src/
    │   ├── config/mongoose.ts  # Connection + index synchronisation
    │   ├── constants/          # ROLES, PERMISSIONS, durations, cookies, statuses
    │   ├── models/             # Mongoose schemas (user, role, token, session)
    │   ├── repositories/       # The only place that queries Mongoose
    │   ├── services/           # All the business logic
    │   ├── controllers/        # HTTP to domain translation
    │   ├── routes/             # URLs + middlewares (index = table of contents)
    │   ├── validators/         # express-validator (422)
    │   ├── dtos/               # Input/output shapes (never a passwordHash)
    │   ├── middlewares/        # jwt · role · permission · validation · errors
    │   ├── exceptions/         # Typed domain errors → HTTP statuses
    │   ├── utils/              # bcrypt · JWT · SHA-256 tokens · email
    │   ├── app.ts              # Express application (does not listen)
    │   └── index.ts            # Entry point (connect + listen)
    ├── tests/                  # Vitest + Supertest (36 tests)
    ├── scripts/                # seed.ts · generate-keys.js
    ├── .github/workflows/ci.yml
    ├── .husky/pre-commit
    ├── Dockerfile · docker-compose.yml · docker-compose.prod.yml
    ├── eslint.config.js · .prettierrc · tsconfig.json · vitest.config.ts
    ├── .env / .env.example
    ├── README.md               # Architecture, conventions and pitfalls
    └── package.json

🔧 Configuration and start-up

The backend .env is already generated by the CLI (JWT keys included): there is nothing to fill in before starting.

1️⃣ Backend

With Docker — MongoDB included, nothing else to install:

cd my-project/server
docker compose up --build            # database + API (hot reload)
docker compose --profile client up   # + the React front-end

Without Docker — with a local MongoDB or Atlas:

cd my-project/server

# Adjust MONGODB_URI in .env if your database is not on localhost:27017
npm run db:seed    # creates the roles and permissions (safe to replay)
npm run dev

Backend environment variables (.env):

APP_NAME="My App"
PORT=5000
COOKIE_SECRET=<generated by the CLI>
MONGODB_URI="mongodb://localhost:27017/my_app"
MONGO_USER=app                  # used by docker compose
MONGO_PASSWORD=app_dev
MONGO_DB=my_app
JWT_PRIVATE_KEY="<generated by the CLI>"   # RS256, flattened PEM
JWT_PUBLIC_KEY="<generated by the CLI>"
CLIENT_URLS=http://localhost:5173          # origins allowed by CORS
# ADMIN_EMAIL=                              # optional: creates an admin
# ADMIN_PASSWORD=                           # account on the next db:seed
# RESEND_API_KEY=                           # optional: without a key, emails
# EMAIL_FROM=                               # are printed to the logs

2️⃣ Frontend

cd my-project/client
npm run dev

Frontend environment variables (.env):

VITE_API_URL=http://localhost:5000

3️⃣ Open the application

📚 Available API routes

All prefixed with /api/v1.

| Method | Route | Description | Auth | | ------ | ------------------------- | ---------------------------------- | ---- | | POST | /auth/register | Create an account (client role) | ❌ | | POST | /auth/login | Sign in | ❌ | | POST | /auth/refresh | Renew the tokens (rotation) | ❌ | | POST | /auth/logout | Revoke the session | ❌ | | POST | /auth/verify-email | Validate the address (emailed token) | ❌ | | POST | /auth/forgot-password | Ask for a reset link | ❌ | | POST | /auth/reset-password | Choose a new password | ❌ | | GET | /auth/me | Profile + permissions | ✅ | | PATCH | /auth/me | Update the profile | ✅ | | POST | /auth/change-password | Change the password | ✅ | | POST | /auth/resend-verification | Resend the verification email | ✅ | | GET | /admin/ping | Canary route (admin role) | 🔒 | | GET | /admin/stats | Counters (dedicated permission) | 🔒 |

🧪 Tests

cd my-project/server

npm test           # 36 tests (unit + API)
npm run test:watch # watch mode
npm run typecheck  # type checking
npm run lint       # ESLint

Tests run against a <your_database>_test database, created and seeded automatically: your development database is never touched.

📦 Main packages included

Backend

  • express 5 - web framework (native async error propagation)
  • typescript + tsx - strict typing and direct execution in dev
  • mongoose - MongoDB ODM
  • bcryptjs - password hashing (12 rounds)
  • jsonwebtoken - RS256 signed JWTs
  • express-validator - input validation
  • helmet - secure HTTP headers
  • cors + cookie-parser - CORS with httpOnly cookies
  • morgan - HTTP logging
  • resend - email delivery
  • vitest + supertest - tests
  • eslint + prettier + husky - quality and commit hooks

Frontend

  • react + react-dom - UI framework
  • vite - lightning-fast build tool
  • tailwindcss - CSS framework
  • shadcn/ui - modern, customisable components
  • react-router-dom - routing
  • @reduxjs/toolkit + react-redux - state management
  • axios - HTTP client
  • react-hook-form - form handling
  • yup - schema validation
  • react-hot-toast - notifications

🎯 Key features

🔐 Complete authentication

  • Sign-up with validation and a verification email
  • Sign-in through RS256 JWTs, with rotating refresh tokens
  • Routes protected by role and by permission
  • Profile management (changing your email requires a new verification)
  • Password change (signs out the other devices)
  • Password reset by email, single-use token

🎨 Modern design

  • Responsive interface (mobile first)
  • Customisable shadcn/ui components
  • Smooth animations
  • Dark mode ready (Tailwind CSS)

🛡️ Security

  • Passwords hashed with bcryptjs (12 rounds), never returned by the API
  • RS256 signed JWTs (private key to sign, public key to verify), carrying only the id
  • Opaque refresh tokens stored SHA-256 hashed: a database leak does not let anyone replay them
  • Refresh token rotation: a replayed token is rejected
  • httpOnly cookies + sameSite: lax (anti-XSS and anti-CSRF), the refresh cookie limited to the auth path
  • Role and account status re-read from the database on every request: a ban is immediate
  • Identical answers whether the email exists or not (account enumeration protection)
  • Secure headers with Helmet, CORS restricted to a list of origins

⚡ Performance and robustness

  • MongoDB indexes declared in the schemas and synchronised at startup
  • TTL indexes: expired tokens and sessions are purged automatically
  • Atomic operations on single-use tokens (no double consumption)
  • Graceful server shutdown (SIGINT/SIGTERM)
  • Vite optimisation, hot reload configured even inside Docker on Windows

🤝 Contributing

Contributions are welcome! Here is how:

  1. 🍴 Fork the project
  2. 🌿 Create a branch (git checkout -b feature/AmazingFeature)
  3. 💾 Commit your changes (git commit -m 'Add some AmazingFeature')
  4. 📤 Push the branch (git push origin feature/AmazingFeature)
  5. 🔀 Open a Pull Request

🐛 Reporting a bug

Open an issue with:

  • A description of the problem
  • Steps to reproduce
  • Expected versus actual behaviour
  • Screenshots when relevant

📄 License

MIT © Perrin Emmanuel Nzaou

👨‍💻 Author

Perrin Emmanuel NZAOU - Full-Stack Web Developer

⭐ Support

If this project helps you, give it a ⭐!


Built with ❤️ for the MERN developer community