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

scolta-astro

v1.0.0

Published

Scolta integration for Astro — AI-powered Pagefind search

Readme

scolta-astro

Scolta integration for Astro — AI-powered Pagefind search, on top of the shared scolta binding. It is a deliberate minimal sibling of scolta-next and scolta-nuxt: it reuses the same binding, the same WASM scoring core, and scolta.js (vanilla JS, also used by Drupal/WordPress), so the only Astro-specific work is the injected API routes, an .astro mount component, and the output dir. No bundled CMS module — CMSs are reached through the generic content-source interface or the JSON:API example in scolta-next.

Install

// astro.config.mjs
import { defineConfig } from "astro/config";
import scoltaAstro from "scolta-astro";

export default defineConfig({
  integrations: [scoltaAstro({ site_name: "My Site", results_per_page: 12 })],
});

The integration injects the AI routes at the exact paths scolta.js defaults to (/api/scolta/v1/{expand-query,summarize,followup,health}). They are request-time server routes (POST + a health probe), so live AI needs server output (output: "server" + an adapter such as @astrojs/node) — a fully static site has the same caveat as scolta-next/scolta-nuxt: host the AI endpoint externally or run server mode.

Node version: Astro 6 requires Node >=22.12; Astro 4/5 on Node 20 is fine. This package declares engines.node >=20 so Astro 4/5 users aren't blocked — but npm checks the package's own engines, not the peer's, so an Astro-6-on-Node-20 install hits Astro's own engine refusal rather than a pointer from here.

Component

Astro has no global component registration; import the search component where you mount it (typically a shared layout):

---
import ScoltaSearch from "scolta-astro/ScoltaSearch.astro";
---
<ScoltaSearch config={browserConfig} assetsPath="/scolta" pagefindPath="/pagefind/pagefind.js" />

It renders the mount container, sets window.scolta (including the container and wasmPath keys scolta.js requires), and loads the stylesheet + widget module from the vendored assets — no client framework needed.

Configuration

Route handlers resolve config per request, lowest to highest precedence:

  1. scolta.config.mjs / scolta.config.js at the project root (also what the scolta-build CLI reads),
  2. the options object passed to scoltaAstro() (serialized into the server bundle via a virtual module),
  3. the SCOLTA_API_KEY / SCOLTA_AI_PROVIDER / SCOLTA_AI_MODEL / SCOLTA_AI_BASE_URL environment variables.

Health endpoint

GET /api/scolta/v1/health returns {"status": "ok"|"degraded"} — enough for uptime monitors. The full diagnostic payload (provider, index state, scoring config) is exposed only with healthDetail: true in the integration options (or scolta.config.mjs). There is no user model in a headless stack, so detail is config-gated rather than auth-gated; enable it only where the endpoint is not publicly reachable.

Content modes

  • static-export (default) — after a static astro build, npx scolta-build crawls the rendered HTML in dist/ and writes the index.
  • content — register a content source (async iterable of ContentItems + changed-since check). The JSON:API / decoupled-Drupal worked example lives in scolta-next and applies here unchanged (it is CMS-side, not framework-side).

CLI

npx scolta-build            # fresh build after astro build
npx scolta-build --force | --resume | --restart
npx scolta-build assets     # copy runtime assets into the output dir

Auto-rebuild

ScoltaTracker is the debounced rebuild helper the autoRebuild / autoRebuildDelay config knobs configure — exported from scolta-astro, the same helper scolta-next ships. Wire touch(key) to your content-change events and it schedules a single debounced rebuild that reuses the token cache, so only changed pages re-tokenize:

import { createScoltaTracker, AstroScoltaConfig } from "scolta-astro";

const config = AstroScoltaConfig.fromEnv({ autoRebuild: true, source: "content" });
const tracker = createScoltaTracker(config, { source: mySource });

// from a CMS save / content webhook handler:
tracker.touch(`articles:${id}`);

createScoltaTracker(config) defaults rebuild to this package's buildIndex (BuildIntent.fresh, no force); pass your own rebuild to override it. The in-process debounce needs a long-running process — it works under server/SSR output (output: "server"), but a fully static astro build or a serverless deploy has no shared in-process timer, so trigger rebuilds via webhook/CI there. scolta-next's Payload afterChange/afterDelete hooks are a reference wiring.