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 🙏

© 2024 – Pkg Stats / Ryan Hefner

staging

v0.0.7

Published

Open-source alternative to Vercel's Password Protection feature

Downloads

658

Readme

staging

Free and open-source alternative to Vercel's Password Protection and Netlify's Password Protection for Non-Production Deploys - protect your staging environments without enterprise or pro plan requirements.

npm version Bundle Size License: MIT TypeScript npm downloads

Overview

Staging provides a simple, secure way to password protect your staging environments - for free. While Vercel's Password Protection requires an Enterprise plan and Netlify's protection requires a Pro plan, staging offers the same core functionality as an open-source solution. It works seamlessly with Express, Next.js and Nuxt.js applications, offering a modern, responsive login interface.

Why Staging?

  • 🆓 Free and Open Source: No enterprise or pro plans required
  • 🔄 Environment-based Protection: Easily protect preview/staging environments using platform environment variables (VERCEL_ENV, NETLIFY_ENV, or your own)
  • 🌐 Framework Agnostic: Works with Next.js, Nuxt.js, and Express.js out of the box
  • ⚡️ Edge Compatible: Optimized for Edge Runtime in Next.js
  • 🛠️ Simple Setup: Get running in minutes with just a few lines of code
  • 💰 Cost Effective: Save hundreds of dollars per month compared to platform-specific solutions

https://github.com/user-attachments/assets/c9369415-bc26-41e3-88c8-2de7a72e14c5

Live Demos

Try out our demo sites (password: demo):

Features

  • 🔐 Simple password protection
  • 🎨 Beautiful, modern login page with light/dark mode
  • ⚡️ Works with Express, Next.js and Nuxt.js
  • 🎯 Flexible route protection with regex support
  • 🔄 Session support for better UX
  • 🌍 Environment variables configuration
  • 🛡️ Secure by default
  • 📱 Mobile-friendly design

Protecting Platform Deployments

Vercel Preview Deployments

// Next.js example (middleware.ts)
import staging from 'staging-next';

export const middleware = staging({
  // Only enable password protection on preview deployments
  enabled: process.env.VERCEL_ENV === 'preview',
  password: process.env.STAGING_PASSWORD,
  siteName: "Preview Site"
});

Netlify Deploy Previews and Branch Deploys

// Next.js example (middleware.ts)
import staging from 'staging-next';

export const middleware = staging({
  // Protect deploy previews and branch deploys
  enabled: ['deploy-preview', 'branch-deploy'].includes(process.env.CONTEXT),
  password: process.env.STAGING_PASSWORD,
  siteName: "Preview Site"
});

Custom Environment Protection

You can protect specific environments based on your needs:

const isProtectedEnvironment = 
  process.env.VERCEL_ENV === 'preview' ||     // Vercel preview deployments
  process.env.CONTEXT === 'deploy-preview' ||  // Netlify deploy previews
  process.env.NODE_ENV === 'staging' ||       // Staging environment
  process.env.PROTECT_ENV === 'true';         // Custom protection flag

export const middleware = staging({
  enabled: isProtectedEnvironment,
  password: process.env.STAGING_PASSWORD
});

Framework Support

Each framework has its own package with specific optimizations and implementations:

Installation

Choose and install the package for your framework:

# For Express.js
npm install staging-express
# or
yarn add staging-express
# or
pnpm add staging-express

# For Next.js
npm install staging-next
# or
yarn add staging-next
# or
pnpm add staging-next

# For Nuxt.js
npm install staging-nuxt
# or
yarn add staging-nuxt
# or
pnpm add staging-nuxt

Quick Start

Express.js

import express from 'express';
import staging from 'staging-express';
import cookieParser from 'cookie-parser';

const app = express();

app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(staging({
  password: process.env.STAGING_PASSWORD
}));

For more Express.js specific features, check out the Express.js docs.

Next.js

// middleware.ts
import staging from 'staging-next';

export const middleware = staging({
  password: process.env.STAGING_PASSWORD
});

For Edge Runtime optimizations and Next.js specific features, check out the Next.js docs.

Nuxt.js

// server/middleware/staging.ts
import staging from "staging-nuxt";

export default staging({
  password: process.env.STAGING_PASSWORD
});

For Nuxt-specific features and H3 integration, check out the Nuxt.js docs.

Configuration

Options

All frameworks support these base options:

interface StagingOptions {
  /** Whether the protection should be enabled. Default: true. Can be set via STAGING_ENABLED env var */
  enabled?: boolean;
  
  /** The password required to access protected routes. Can be set via STAGING_PASSWORD env var */
  password?: string;

  /** Duration in milliseconds for how long the auth cookie remains valid. Default: 7 days. Can be set via STAGING_COOKIE_MAX_AGE env var (in days) */
  cookieMaxAge?: number;

  /** Secret used to sign the JWT token. Default: randomly generated. Can be set via STAGING_JWT_SECRET env var */
  jwtSecret?: string;

  /** Path for the login endpoint. Default: '/protected'. Can be set via STAGING_LOGIN_PATH env var */
  loginPath?: string;

  /** Name displayed on the login page. Default: 'Protected Page'. Can be set via STAGING_SITE_NAME env var */
  siteName?: string;

  /** Routes that should be protected. Default: all routes except loginPath. Can be set via STAGING_PROTECTED_ROUTES env var as comma-separated paths */
  protectedRoutes?: string[];

  /** Routes that should never be protected. Default: []. Can be set via STAGING_PUBLIC_ROUTES env var as comma-separated paths */
  publicRoutes?: string[];

  /** URL to redirect to after successful login. Default: the original requested URL. Can be set via STAGING_REDIRECT_URL env var */
  redirectUrl?: string;
}

Each framework may provide additional options. See their respective documentation for details.

Environment Variables

All options can be configured via environment variables:

To generate secure secrets for your environment, you can use:

# Generate a secure JWT secret
openssl rand -base64 32
# or
node -e "console.log(crypto.randomBytes(32).toString('base64'))"

Then set your environment variables:

# Required
STAGING_PASSWORD=your-password

# Optional
STAGING_ENABLED=true
STAGING_JWT_SECRET=your-jwt-secret
STAGING_COOKIE_MAX_AGE=7 # days
STAGING_LOGIN_PATH=/protected
STAGING_SITE_NAME="Protected Page"
STAGING_PROTECTED_ROUTES=/admin/*,/dashboard/*
STAGING_PUBLIC_ROUTES=/api/public/*,/static/*
STAGING_REDIRECT_URL=/

Route Protection

You can use regex patterns to protect or expose routes:

{
  // Protect specific paths
  protectedRoutes: [
    '^/admin(/.*)?$',    // Protect /admin/*
    '^/dashboard(/.*)?$' // Protect /dashboard/*
  ],

  // Make specific paths public
  publicRoutes: [
    '^/(_next|static|images)(/.*)?$', // Public assets
    '^/api/public(/.*)?$'             // Public API routes
  ]
}

Security

The middleware:

  • Uses secure httpOnly cookies
  • Implements JWT for token validation
  • Enables secure cookies in production
  • Implements sameSite cookie policy
  • Generates random JWT secrets by default

Examples

Full examples for each framework are available in the repository:

Framework-specific Features

Each framework implementation has its own optimizations and features:

  • Express.js (docs)

    • Session support
    • Express middleware integration
    • Node.js optimized
  • Next.js (docs)

    • Edge Runtime compatible
    • Next.js middleware
    • Cookie-based session handling
  • Nuxt.js (docs)

    • H3 integration
    • Nuxt-specific route handling
    • Cookie-based session handling

Contributing

Contributions are welcome! Please see our Contributing Guide for more details.

License

MIT