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

@strifeapp/astro

v1.2.0

Published

Official Strife integration for Astro — connect your Astro site to a RavenDB-backed Strife content store via a strife:store virtual module.

Readme

@strifeapp/astro

npm version

Official Strife integration for Astro. It connects your Astro site to a Strife (RavenDB-backed) content store and exposes an initialized document store to your pages through a strife:store virtual module — resolved at runtime, so the same build runs against any environment and secrets are never baked into the bundle.

Contents

Installation

npx astro add @strifeapp/astro

Or install manually and add the integration to your config yourself:

npm install @strifeapp/astro

Requirements

  • Astro 5 or 6astro is a peer dependency (^5.0.0 || ^6.0.0). Astro 5+ is required because the integration uses astro:env for runtime-safe secret resolution.
  • Node 22.12+.
  • A Strife / RavenDB content store and a client certificate registered with it (PFX, any key type — RSA or ECDSA).

ravendb is installed as a dependency; you do not need to install it yourself.

Usage

Register the integration in your Astro config:

import { defineConfig } from 'astro/config';
import strife from '@strifeapp/astro';

export default defineConfig({
  integrations: [
    strife({
      // All fields are optional; environment variables take precedence (see Configuration).
      urls: ['https://your-ravendb.example.com'],
      database: 'your-database',
      collections: [{ name: 'Posts' }, { name: 'Pages' }],
    }),
  ],
});

Reading content

Read from the store anywhere in your site through the strife:store virtual module:

---
import { store } from 'strife:store';

const session = store.openSession();
// The integration deploys a `Content_ByUrl` index for URL-based lookups.
const page = await session
  .query({ indexName: 'Content_ByUrl' })
  .whereEquals('url', Astro.url.pathname)
  .firstOrNull();
---

TypeScript: typing strife:store

Typed ambient declarations for the strife:store virtual module are not bundled in this release. Until a typed surface is published, add your own declaration (e.g. in src/env.d.ts):

declare module 'strife:store' {
  import type { DocumentStore } from 'ravendb';
  export const store: DocumentStore;
}

Direct Vite plugin

The underlying Vite plugin is also exported standalone:

import { vitePluginStrifeStore } from '@strifeapp/astro/vite-plugin-strife-store';

Configuration

strife(options?) accepts:

| Option | Type | Description | | --- | --- | --- | | urls | string[] | RavenDB server URLs. | | database | string | Database name. | | collections | { name: string }[] | Collections to index (default: Posts). |

Credentials are not build-time options. certificate and password are not accepted as integration options — passing them would bake the secret into the built bundle. Provide them at runtime via STRIFE_SECRET or the STRIFE_CERTIFICATE / STRIFE_CERTIFICATE_PASSWORD env vars (below). The integration strips any certificate/password it receives as options before generating the store module.

Environment variables

The integration registers STRIFE_* as astro:env server secret variables, so you do not need import 'dotenv/config' or any other loader — just set them:

| Variable | Maps to | | --- | --- | | STRIFE_SECRET | All of the below, packed into one value (see Generating STRIFE_SECRET) | | STRIFE_DATABASE_URLS | urls (comma-separated) | | STRIFE_DATABASE | database | | STRIFE_CERTIFICATE | base64-encoded PFX (optional in development) | | STRIFE_CERTIFICATE_PASSWORD | certificate password |

Set them in a local .env for development, or in your host's environment (Vercel project settings, Kubernetes secrets, etc.) for deployment. Because they are astro:env server secrets, they are read at runtime via getSecret and never inlined into the built bundle.

STRIFE_SECRET is a single, compact value that bundles the URLs, database, certificate, and password — convenient when one secret is easier to manage than four. It is additive: when set, each field it carries takes priority; when unset, the four individual variables work exactly as before.

Resolution order, per field: STRIFE_SECRET → individual STRIFE_* env var → non-secret integration option (urls/database only) → built-in default.

Reading via astro:env (rather than process.env) is deliberate: in astro dev, Astro does not populate process.env from .env, so a process.env-based read would be empty locally. astro:env's getSecret reads .env in dev and the host environment in production, with no extra setup.

Generating STRIFE_SECRET

STRIFE_SECRET has the form v1.<meta>.<cert>: a version tag, your urls/database/password as base64url-encoded JSON, and your PFX certificate as base64url-encoded raw bytes (encoded once — ~33% smaller than embedding an already-base64 cert in JSON). The format is key-algorithm-agnostic: the same STRIFE_SECRET works whether the certificate inside is RSA or ECDSA.

The blob format is stable, so you can generate it yourself in a few lines: base64url-encode JSON.stringify({ urls, database, password }), base64url-encode the raw .pfx bytes, and join them as v1.<meta>.<cert>. Contributors working in the repository can use the bundled helper:

# password via env var (recommended)
STRIFE_PFX_PASSWORD='your-cert-password' node --experimental-strip-types \
  scripts/pack-secrets.mjs \
  --pfx ./client.pfx \
  --urls https://your-ravendb.example.com \
  --database your-database

# …or pipe the password instead of putting it in the environment
printf '%s' "$PFX_PW" | node --experimental-strip-types \
  scripts/pack-secrets.mjs --pfx ./client.pfx --urls … --database … --password-stdin

The password is read only from STRIFE_PFX_PASSWORD or --password-stdin — never a CLI flag, since process arguments are world-readable. The helper prints STRIFE_SECRET=<blob>; pipe it straight into your host's secret store rather than echoing it (it otherwise lands in shell history). --experimental-strip-types is unnecessary on Node ≥ 23.6 / 22.18. (The helper script ships with the repository, not the published package; a strife secrets pack CLI command is planned.)

Platform size limits

The certificate dominates the value's size, and base64 of an encrypted PFX is incompressible — so a large certificate may not fit a platform's per-variable env limit. This is a property of the certificate, not of STRIFE_SECRET (the standalone STRIFE_CERTIFICATE has the same ceiling).

| Platform | Per-variable limit | A ~2 KB ECDSA cert (~1.8 KB blob) | A ~4 KB RSA-4096 cert (~5.5 KB blob) | | --- | --- | --- | --- | | Kubernetes secret | ~1 MiB | ✅ | ✅ | | Vercel (serverless) | 64 KB total | ✅ | ✅ | | Vercel (edge) / Cloudflare Workers | ~5 KB | ✅ | ❌ | | Netlify build-time | 5,000 chars | ✅ | ❌ | | AWS Lambda / Netlify Functions (SSR) | 256 chars / 4 KB total | ❌ | ❌ |

If you hit a limit, the fix is a smaller certificate — RavenDB authenticates clients by thumbprint, not key algorithm, so you can register a compact ECDSA P-256 client certificate (≈1.2 KB PFX) and use it instead of an RSA-4096 one. No encoding change helps a large cert; a smaller key does.

How it works

On astro:config:setup the integration registers the STRIFE_* env schema and a Vite plugin. When the strife:store module is first evaluated (at build for prerendered pages, at request time for SSR), the plugin:

  1. Resolves configuration at runtime via getSecret (never baked into the bundle).
  2. Connects to RavenDB using the resolved URLs, database, and client certificate.
  3. Deploys a Content_ByUrl multi-map index (deploymentMode: 'Rolling') for URL-based content lookup.
  4. Bulk-inserts the configured collections into the Templates collection.
  5. Exposes the initialized RavenDB DocumentStore through the strife:store virtual module.

The Content_ByUrl index is deployed with a bundled helper source (localized-content-index.js) that runs inside RavenDB's Jint engine. It is intentionally plain ES5 — do not transpile it.

License

ISC © Strife