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

nist-stack

v1.0.10

Published

NIST Framework - NestJS + Vite SSR for React

Readme


Why NIST?

NIST combines NestJS's powerful backend architecture with Vite's lightning-fast development experience to deliver server-side rendered React applications with unprecedented performance and developer experience.

// Define your page in a NestJS controller
@Get()
@Page("home")
getHome(): PageResponse {
  return { data: { users: ["Alice", "Bob"] } };
}
// Render with React - props are fully typed!
export default function Home({ users }) {
  return (
    <ul>
      {users.map((u) => (
        <li key={u}>{u}</li>
      ))}
    </ul>
  );
}

Result: Sub-20ms SSR, full type safety, and instant HMR. No configuration needed.


At a Glance

| Feature | NIST | Next.js | Remix | | ------------------------ | ---------------- | -------------------- | ----------------- | | Backend Framework | Full NestJS | Limited API routes | Express-like | | SSR Performance | ~19ms (cached) | ~150-300ms | ~200-400ms | | Dependency Injection | ✅ Built-in | ❌ Manual | ❌ Manual | | Type Safety | ✅ End-to-end | ⚠️ Partial | ⚠️ Partial | | Guards & Auth | ✅ NestJS guards | ⚠️ Custom middleware | ⚠️ Custom loaders | | Build Tool | Vite 7 | Turbopack | esbuild | | Hot Reload | ✅ Instant HMR | ✅ Fast Refresh | ✅ Live reload |


Quick Start

Installation

npm install nist-stack

That's it! One package gives you everything.

1. Server Setup (main.ts)

import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";
import { bootstrapNist } from "nist-stack";

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  await bootstrapNist(app); // One line setup!

  await app.listen(3000);
}
bootstrap();

2. Create a Controller with Pages

import { Controller, Get } from "@nestjs/common";
import { Page, PageRoot } from "nist-stack";

@Controller()
@PageRoot(__dirname)
export class AppController {
  @Get("/")
  @Page("app")
  home() {
    return { users: ["Alice", "Bob"] };
  }
}

3. Create Root Layout (src/app.layout.tsx)

import type { LayoutProps } from "nist-stack/client";

export default function AppLayout({
  children,
  metaTags, // Required for SEO
  hydrationScripts, // Required for React hydration
  metadata,
}: LayoutProps) {
  const isClient = typeof window !== "undefined";
  if (isClient) return <>{children}</>;

  return (
    <html lang="en">
      <head>
        <meta charSet="UTF-8" />
        <title>{metadata?.title || "My App"}</title>
        {metaTags}
      </head>
      <body>
        <div id="root">{children}</div>
        {hydrationScripts}
      </body>
    </html>
  );
}

4. Create a React Page (src/app.page.tsx)

import { Link } from "nist-stack/client";

export default function App({ users }) {
  return (
    <div>
      <h1>Users</h1>
      <ul>
        {users.map((u) => (
          <li key={u}>{u}</li>
        ))}
      </ul>
      <Link href="/about">About</Link>
    </div>
  );
}

5. Create the Vite client entry (src/entry-client.tsx)

import "./globals.css";
import { createClientEntry } from "nist-stack/client";

const globals = window as any;

// Discover all pages and layouts relative to @PageRoot(__dirname)
// @ts-ignore - Vite-specific import.meta.glob helper
const pages = import.meta.glob(["/src/**/*.page.tsx", "/app/**/*.page.tsx"], {
  eager: false,
});

// @ts-ignore - Vite-specific import.meta.glob helper
const layouts = import.meta.glob(
  ["/src/**/*.layout.tsx", "/app/**/*.layout.tsx"],
  { eager: false }
);

const { render } = createClientEntry({
  globals,
  pages,
  layouts,
  targetId: "root",
});

render();

// Enable hot module replacement during development
// @ts-ignore - Vite HMR typings
if (import.meta.hot) {
  // @ts-ignore - Vite HMR typings
  import.meta.hot.accept(Object.keys(pages), async () => {
    await render();
  });
}

✅ The client entry wires Vite + React hydration. Keep it at src/entry-client.tsx so bootstrapNist can inject the scripts automatically.

6. Configure Vite (vite.config.ts)

import { resolve } from "path";
import { createConfig } from "nist-stack";

export default createConfig({
  resolve: {
    alias: {
      "@": resolve(__dirname, "./src"),
    },
  },
});

createConfig() sets up SSR + HMR defaults. Add aliases or plugins here as you would in a normal Vite project.

Available Imports

Server-Side

// From 'nist-stack'
import {
  Page, // Decorator: Mark controller method as page
  PageRoot, // Decorator: Set page root directory
  Layout, // Decorator: Set custom layout
  NistInterceptor, // SSR interceptor
  createViteDevServer, // Create Vite server
  NistError, // Framework error class
} from "nist-stack";

// From 'nist-stack/decorators' (alternative)
import { Page, PageRoot, Layout } from "nist-stack/decorators";

Client-Side

// From 'nist-stack/client'
import {
  Link, // Client-side navigation component
  Image, // Optimized image component
  ErrorBoundary, // Error boundary component
  Router, // Router component
  useRouter, // Router hook
  useParams, // Get route params
  useQuery, // Get query params
  usePathname, // Get current pathname
  useParam, // Get single param
  useQueryParam, // Get single query param
  useRouteData, // Get all route data
  useNistData, // Get full hydration data
} from "nist-stack/client";

// TypeScript types
import type {
  Metadata, // Page/layout metadata
  LayoutProps, // Layout component props
  PageProps, // Page component props
  PageConfig, // Page configuration (ISR, etc.)
  RouteData, // Route data interface
} from "nist-stack/client";

Features

  • ✅ Server-Side Rendering (SSR)
  • ✅ Hot Module Replacement (HMR)
  • ✅ Type-safe routing with decorators
  • ✅ Automatic page validation
  • ✅ Built-in security (CSRF, XSS protection)
  • ✅ Production-ready builds
  • ✅ Client-side navigation
  • ✅ SEO metadata support
  • ✅ ISR support (Incremental Static Regeneration)

Examples

Simple Page

// my-page.page.tsx
export default function MyPage() {
  return <div>Hello World</div>;
}

Using Route Params

import { useParams } from "nist-stack/client";

export default function UserPage() {
  const { id } = useParams<{ id: string }>();
  return <div>User ID: {id}</div>;
}

Custom Layout

// app.layout.tsx
export default function Layout({ children }) {
  return (
    <div>
      <nav>Navigation</nav>
      {children}
    </div>
  );
}

Controller with Layout

import { Controller, Get } from "@nestjs/common";
import { Page, PageRoot, Layout } from "nist-stack";

@Controller()
@PageRoot(__dirname)
export class AppController {
  @Get("/profile")
  @Page("profile")
  @Layout("app") // Use app.layout.tsx
  profile() {
    return { user: { name: "Alice" } };
  }
}

Development

The framework is optimized for hot reloading:

  • Frontend changes → Vite HMR (instant updates, no page reload)
  • Backend changes → NestJS restarts (Vite HMR preserved)

Run with your preferred NestJS dev tool:

# Using ts-node-dev
ts-node-dev --respawn --transpile-only src/main.ts

# Using nodemon
nodemon --watch src -e ts --exec ts-node src/main.ts

# Using NestJS CLI
nest start --watch

The Vite dev server persists across NestJS restarts, so frontend HMR is never interrupted.

Production Build

# Build everything
npm run build

# Start production server
npm run start:prod

The framework automatically switches between dev (HMR) and production (static bundles) based on NODE_ENV.

TypeScript Configuration

Full TypeScript support out of the box. All exports are typed.

Development vs Production Configuration

NIST requires two separate TypeScript configs to prevent conflicts between NestJS compilation and Vite HMR:

1. tsconfig.build.json (for development - excludes .tsx):

{
  "extends": "./tsconfig.json",
  "exclude": [
    "node_modules",
    "test",
    "dist",
    "**/*spec.ts",
    "public",
    "**/*.tsx"
  ]
}

2. tsconfig.prod.json (for production builds - includes .tsx):

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "./dist",
    "declaration": true
  },
  "include": ["src/**/*", "src/**/*.tsx"],
  "exclude": ["node_modules", "dist", "**/*.spec.ts", "**/*.test.ts"]
}

Key points:

  • tsconfig.build.json excludes **/*.tsx - prevents nest start --watch from compiling React files
  • tsconfig.prod.json includes "src/**/*.tsx" - compiles pages/layouts for production
  • Development: Vite handles all .tsx compilation with HMR
  • Production: TypeScript compiles .tsx files to JavaScript
  • ⚠️ Without the exclude in build config, NestJS will try to compile .tsx files and break HMR

License

MIT

Who Should Use NIST?

Perfect for:

  • 🏢 Enterprise applications requiring robust backend architecture
  • 🔐 Auth-heavy applications with complex permission systems
  • 📊 Data-intensive apps with significant server-side logic
  • 🚀 Performance-critical applications needing fast SSR
  • 🧩 Microservices architectures wanting consistent frontend

Documentation


Community & Support


Contributing

We welcome contributions! Please see our Contributing Guide for details.


Security

Found a security vulnerability? Please review our Security Policy and report it responsibly.


Changelog

See CHANGELOG.md for release notes and version history.


License

MIT


Acknowledgments

Built with:

  • NestJS - Progressive Node.js framework
  • Vite - Next generation frontend tooling
  • React - Library for building user interfaces