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

@eldrex/papyr-pssr

v3.1.3

Published

PSSR SDK — Papyrus Server Side Rendering advanced rendering strategy SDK

Readme

@eldrex/papyr-pssr

PSSR SDK — Papyrus Server-Side Rendering & Rendering Strategy SDK

Part of the Papyrus.js framework ecosystem.

npm version License: MIT


What is PSSR?

PSSR (Papyrus Server-Side Rendering) is Papyrus's advanced rendering orchestration layer. It enables Papyrus applications to support multiple rendering modes per route, lazy island hydration, SEO metadata pipelines, and edge/serverless deployment — all with a unified, composable SDK.

This package (@eldrex/papyr-pssr) gives developers the tools to configure and control the rendering lifecycle without modifying the core Papyrus kernel.

Browser / Edge Runtime
    ↓
papyr.pssr.sdk         ← This package
    ↓
papyr.pssr (core)      ← Hydration, island registry, SSR compiler
    ↓
papyr.ssr / papyr.isr  ← Runtime rendering and cache
    ↓
Browser / Node.js APIs

Rendering Modes

| Mode | Best For | How | |------|----------|-----| | csr | Dashboards, internal tools, IDEs | Client-side only | | ssr | SaaS, e-commerce, SEO-critical pages | Server renders HTML, client hydrates | | ssg | Blogs, docs, marketing | HTML generated at build time | | isr | Large catalogues, storefronts | Cached HTML + background regeneration |


Installation

As part of the full Papyrus bundle (recommended)

<script src="https://papyrus-js.vercel.app/papyr-complete.js"></script>

The PSSR SDK is already available as papyr.pssr.sdk.

Standalone

npm install @eldrex/papyr-pssr
const { pssr } = require('@eldrex/papyr-pssr');
// or ESM
import { pssr } from '@eldrex/papyr-pssr';

API Reference

papyr.pssr.sdk.strategy(options) — Per-Route Rendering Strategy

Configure different rendering modes per URL pattern:

papyr.pssr.sdk.strategy({
    default: 'ssr',
    routes: {
        '/blog/*':      'ssg',    // Blog posts — build-time HTML
        '/dashboard':   'csr',    // Dashboard — client-only
        '/shop/*':      'isr',    // Shop pages — cached + regenerate
        '/':            'ssr'     // Home — server-rendered
    },
    isrTtl: 300                   // ISR cache TTL in seconds (default 300)
}).apply();

Pattern matching supports * wildcards and :param segments.

papyr.pssr.sdk.islands(options) — Lazy Island Hydration

Hydrate UI islands lazily when they enter the viewport (zero layout shift):

papyr.pssr.sdk.islands({
    lazy: true,                   // Use IntersectionObserver
    threshold: 0.1,               // Hydrate when 10% visible
    islandsOnly: true,            // Only hydrate declared islands
    onHydrate: (id) => {
        console.log('Hydrated island:', id);
    }
});

Register an island:

papyr.registerIsland('hero', HeroComponent);
papyr.registerIsland('chart', ChartComponent);

Mark HTML for island hydration:

<div data-papyr-island="hero"></div>
<div data-papyr-island="chart"></div>

papyr.pssr.sdk.meta — SEO Metadata Pipeline

Composable middleware pipeline for generating head metadata:

papyr.pssr.sdk.meta.pipe([
    (ctx) => ({ title: ctx.page.title }),
    (ctx) => ({ description: ctx.page.excerpt }),
    (ctx) => ({
        og: {
            title: ctx.page.title,
            image: ctx.page.thumbnail,
            type: 'article'
        }
    }),
    (ctx) => ({
        twitter: { card: 'summary_large_image' }
    }),
    (ctx) => ({
        canonical: `https://example.com${ctx.route}`
    })
]);

// Run the pipeline
const head = await papyr.pssr.sdk.meta.run(routeContext);

papyr.pssr.sdk.edge(options) — Edge Runtime Configuration

Configure for serverless and edge deployment:

papyr.pssr.sdk.edge({
    runtime: 'cloudflare',        // 'cloudflare' | 'deno' | 'bun' | 'node'
    isrTtl: 600,                  // Cache-Control TTL
    streamingSSR: true,           // Enable streaming HTML
    onRequest: async (req, ctx) => {
        // Pre-request middleware
    }
});

Detect the current runtime:

papyr.edge.isEdge();             // true on Cloudflare/Deno/Bun
papyr.edge.isNode();             // true on Node.js
papyr.edge.detectCloudflare();   // true on Cloudflare Workers
papyr.edge.detectDeno();         // true on Deno Deploy
papyr.edge.detectBun();          // true on Bun

papyr.pssr.sdk.build.prerender(options) — SSG Prerendering

Generate static HTML at build time with optional concurrency:

await papyr.pssr.sdk.build.prerender({
    routes: ['/about', '/blog/1', '/blog/2', '/shop'],
    concurrency: 4,               // Parallel render workers
    outputDir: './dist',
    onRoute: (route, html) => {
        console.log(`Rendered: ${route} (${html.length} bytes)`);
    }
});

ISR Cache Management

// Invalidate a specific route
papyr.isr.invalidate('/shop/product-123');

// Clear all ISR cache
papyr.isr.clear();

// Check cache status
const status = papyr.isr.status('/blog/hello-world');
// { cached: true, age: 145, ttl: 300, stale: false }

// Express.js middleware
app.use(papyr.isr.middleware({ ttl: 300 }));

PSSR + WATT Integration

PSSR is WATT-aware. When WATT is in 'strict' mode, PSSR disables client-side analytics hydration during the island hydration phase. Configure both together:

papyr.config('watt', { mode: 'strict' });
papyr.config('ssr', { mode: 'ssr', streaming: true });

papyr.pssr.sdk.strategy({ default: 'ssr' }).apply();
papyr.pssr.sdk.islands({ lazy: true });

SEO Capabilities

// Full OG/Twitter/Schema pipeline
papyr.pssr.sdk.meta.pipe([
    blogMetaMiddleware,
    openGraphMiddleware,
    schemaOrgMiddleware
]);

// Direct SEO API
papyr.seo.og({ title: 'My Page', image: '/og.png' });
papyr.seo.twitter({ card: 'summary_large_image' });
papyr.seo.schema({ '@type': 'Article', name: 'My Page' });
papyr.seo.canonical('https://example.com/my-page');
papyr.seo.sitemap(['/about', '/blog', '/shop']);
papyr.seo.robots({ disallow: ['/admin'] });

Related Packages

| Package | Description | |---------|-------------| | @eldrex/papyr | Core Papyrus framework | | @eldrex/papyr-watt | WATT privacy & consent SDK |


Documentation


License

MIT © Eldrex Delos Reyes Bula