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

@erwininteractive/mvc

v0.8.2

Published

A lightweight, full-featured MVC framework for Node.js with Express, Prisma, and EJS

Readme

@erwininteractive/mvc

A lightweight, full-featured MVC framework for Node.js 20+ built with TypeScript.

Features

  • Express - Fast, unopinionated web framework for routing and middleware
  • EJS Templating - Server-side templating with embedded JavaScript
  • Prisma ORM - Type-safe database client (optional, PostgreSQL/MySQL/SQLite support)
  • Redis Sessions - Scalable session management with connect-redis
  • JWT Authentication - Secure token-based auth with bcrypt password hashing
  • Session-Based Auth - Traditional session management with Express-Session
  • WebAuthn (Passkeys) - Passwordless authentication with security keys (YubiKey, Touch ID, Face ID)
  • Tailwind CSS - Modern, utility-first CSS framework (optional, included with --with-tailwind)
  • Zod Validation - Type-safe form validation with TypeScript-first schemas
  • CLI Tools - Scaffold apps with --with-tailwind, generate models/controllers/resources
  • Flash Messages - Session-based success/error messages for forms
  • Cookie Parser - Built-in cookie parsing for JWT and session support
  • Helmet Security - HTTP header security middleware
  • CORS Support - Cross-origin resource sharing middleware
  • GitHub Actions CI - Automated testing with optional CI setup

Quick Start

npx @erwininteractive/mvc init myapp
cd myapp
npm run dev

Visit http://localhost:3000 - your app is running!

CLI Commands

Initialize a new app

# Basic app
npx @erwininteractive/mvc init myapp

# With Tailwind CSS
npx @erwininteractive/mvc init myapp --with-tailwind

# With database support (Prisma)
npx @erwininteractive/mvc init myapp --with-database

# With database + Tailwind
npx @erwininteractive/mvc init myapp --with-database --with-tailwind

# With GitHub Actions CI
npx @erwininteractive/mvc init myapp --with-ci

# Skip npm install (install manually later)
npx @erwininteractive/mvc init myapp --skip-install

Generate models

# Generate a Prisma model
npx erwinmvc generate model User
npx erwinmvc g model User

# Generate without running migration
npx erwinmvc generate model User --skip-migrate

Generate controllers

# Generate a CRUD controller
npx erwinmvc generate controller User
npx erwinmvc g controller User

# Generate without views
npx erwinmvc generate controller User --no-views

Generate resources (model + controller + views)

# Complete resource with all features
npx erwinmvc generate resource Post
npx erwinmvc g resource Post

# Skip specific parts
npx erwinmvc generate resource Post --skip-model
npx erwinmvc generate resource Post --skip-views
npx erwinmvc generate resource Post --skip-controller

# Skip database migration
npx erwinmvc generate resource Post --skip-migrate

# API-only resource (no views, JSON responses)
npx erwinmvc generate resource Post --api-only

Authentication commands

# Generate complete authentication system (login/register)
npx erwinmvc make:auth
npx erwinmvc ma

# Skip User model (use existing)
npx erwinmvc make:auth --without-model

# Only JWT (no sessions)
npx erwinmvc make:auth --jwt-only

# Only sessions (no JWT)
npx erwinmvc make:auth --session-only

WebAuthn (Passkeys)

# Generate WebAuthn authentication (security key login)
npx erwinmvc webauthn
npx erwinmvc w

# Skip database migration
npx erwinmvc webauthn --skip-migrate

List routes

# Show all defined routes
npx erwinmvc list:routes
npx erwinmvc lr

Project Structure

myapp/
├── src/
│   ├── controllers/   # MVC controllers
│   ├── views/         # EJS templates
│   └── server.ts      # App entry point
├── public/            # Static assets
│   └── dist/          # Compiled CSS (Tailwind)
├── prisma/            # Database (optional)
│   └── schema.prisma  # Prisma schema
├── .github/           # CI workflows (optional)
├── package.json
├── tsconfig.json
├── tailwind.config.ts  # Tailwind config (optional)
└── postcss.config.cjs  # PostCSS config (optional)

Database Setup

# Setup Prisma database
npx erwinmvc init myapp --with-database
cd myapp

# Edit .env with your DATABASE_URL
# DATABASE_URL="postgresql://user:password@localhost:5432/mydb"

# Run migrations
npx prisma migrate dev --name init

# Generate Prisma client (auto-run by CLI)
npx prisma generate

Tailwind CSS Setup

npx erwinmvc init myapp --with-tailwind
cd myapp

# Configure content paths in tailwind.config.ts
# Edit src/assets/tailwind.css for custom styles

# Build CSS
npx tailwindcss -i ./src/assets/tailwind.css -o ./public/dist/tailwind.css --watch

Authentication

Session + JWT Auth

The make:auth command generates:

  • User model with password hashing
  • Register/login forms with Zod validation
  • Session-based authentication
  • JWT token generation for API access
  • Password verification with bcrypt
  • Flash messages for errors/success

WebAuthn (Passkeys)

The webauthn command generates:

  • Passkey registration flow
  • Passkey authentication flow
  • User credential storage in database
  • Security key support (YubiKey, Touch ID, Face ID)

Validation

Use Zod schemas for type-safe form validation:

import { z } from "zod";
import { validate } from "@erwininteractive/mvc";

const userSchema = z.object({
  username: z.string().min(3),
  email: z.string().email(),
  password: z.string().min(8)
});

app.post("/users", validate(userSchema), async (req, res) => {
  const user = req.validatedBody; // Type-safe validated data
  // ...
});

API Reference

Core Functions

  • createMvcApp(options) - Create Express app with views, static files
  • startServer(app) - Start HTTP server on port 3000
  • hashPassword(plain) - Hash password with bcrypt
  • verifyPassword(plain, hash) - Verify password
  • signToken(payload, expiresIn) - Sign JWT token
  • verifyToken(token) - Verify and decode JWT
  • authenticate - Express middleware for JWT authentication
  • validate(schema, strategy) - Zod validation middleware

WebAuthn Functions

  • startRegistration(req, res) - Begin WebAuthn registration
  • completeRegistration(req, res) - Complete WebAuthn registration
  • startAuthentication(req, res) - Begin WebAuthn login
  • completeAuthentication(req, res) - Complete WebAuthn login
  • getRPConfig() - Get relying party configuration

Validation Helpers

  • getFieldErrors(error) - Extract field errors from Zod error
  • getOldInput(req) - Get previously submitted form data
  • getErrors(req) - Get flash error messages
  • hasFieldError(field, errors) - Check if field has errors
  • getFieldError(field, errors) - Get error message for field

Environment Variables

Required for full functionality:

# Required
JWT_SECRET=your-secret-key-here

# Database (optional)
DATABASE_URL=postgresql://user:password@localhost:5432/mydb

# WebAuthn (optional, defaults to localhost)
WEBAUTHN_RP_ID=localhost
WEBAUTHN_RP_NAME=MyApp

Testing

# Run all tests
npm test

# Run specific test file
npm test -- auth
npm test -- cli
npm test -- generators

# With coverage
npm run test -- --coverage

Production Build

# Build TypeScript and CLI
npm run build

# The app is ready for production deployment
# Server runs on port 3000

License

MIT © Erwin Interactive