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

streak-forge

v2.1.20

Published

A performance-first static site builder. Build

Downloads

770

Readme

streak-forge

The build engine and CLI for Streak.js — a performance-first static site generator that ships zero framework overhead to the browser.

npm version docs license


What is Streak.js?

Streak.js is a static site generator that pre-renders every page to plain HTML at build time. The only thing delivered to the browser is the generated HTML and a tiny client-side coordinator (app.js) — no framework runtime, no virtual DOM, no hydration.

TSX components are used as build-time templates only. Once the HTML is written, React is gone. A minimal runtime enables progressive features like lazy-loaded widgets, dynamic components, and on-demand JS loading — but it never re-renders anything.

What Streak is NOT:

  • No hydration — output is complete static HTML
  • No virtual DOM in the browser — DOM mutations use plain JS in Script functions
  • No routing — handled by the web server (Netlify, nginx, etc.)
  • No state management — widgets are pure render functions
  • No CSS-in-JS — all styling is Tailwind compiled at build time
  • No code splitting — one HTML file per page, JS loaded progressively

How It Works

streak.sitemap.json
{ url, renderId, dataHandler, rootLayout, widgets[] }
         │
         ├── DataHandler (async fn)  →  returns { status: 200, WidgetId: { ... } }
         │
         └── Layout (TSX)           →  full HTML with WidgetPlaceholders

                         ↓ Streak Renderer ↓

         For each widget in widgets[]:
           1. find src/widgets/<type>.tsx
           2. render TSX with { data: handlerData[id] }
           3. replace WidgetPlaceholder in layout HTML

                         ↓ Output ↓

         out/<renderId>/index.html
         ─────────────────────────
         Complete static HTML
         + <script id="w-m">{json}</script>   ← widget registry
         + <script>app.js IIFE</script>        ← client coordinator
         + inline Script widgets               ← each Script component

Installation

streak-forge is the CLI and build engine. Add it to your Streak.js project:

bun add streak-forge

Prerequisites: Bun >= 1.0


Quick Start

Clone the hello-streak-app starter and install dependencies:

git clone https://github.com/valoriz/hello-streak-app.git my-app
cd my-app
bun install

Start the dev server:

bun run dev
# → http://localhost:3690

See the full getting-started guide for a step-by-step walkthrough.


CLI Commands

streak-forge dev

Starts a development server on port 3690 with hot-reload. Pages are rendered on request — nothing is written to disk.

streak-forge dev

streak-forge pre-build

Reads streak.sitemap.json, runs every page through the 7-stage rendering pipeline, and writes static HTML to out/.

streak-forge pre-build

Output structure:

out/
  homeRenderId/
    index.html
  aboutRenderId/
    index.html

Typical package.json scripts

{
  "scripts": {
    "dev":        "concurrently \"bun run css-dev\" \"bun run dev:streak\"",
    "dev:streak": "streak-forge dev",
    "build":      "bun run css-build && streak-forge pre-build",
    "css-build":  "tailwindcss -i ./src/common/styles/input.css -o ./public/styles/tailwind.css",
    "css-dev":    "tailwindcss -i ./src/common/styles/input.css -o ./public/styles/tailwind.css --watch"
  }
}

Project Structure

my-streak-site/
  src/
    handlers/         ← async data providers (one per page)
    layouts/          ← full HTML document templates with WidgetPlaceholders
    widgets/          ← stateless TSX components rendered at build time
  public/
    assets/           ← JS/CSS loaded at runtime via the asset worker
    styles/           ← compiled Tailwind CSS
  out/                ← generated static output (created by build)
  streak.sitemap.json
  tsconfig.json
  package.json

Core Concepts

Sitemap — streak.sitemap.json

The single entry point for the entire build. Every page, its layout, data source, and widget list is declared here.

[
  {
    "url": "/",
    "renderConfig": {
      "renderId": "homeRenderId",
      "dataHandler": "HomeDataHandler",
      "rootLayout": "MainLayout",
      "widgets": [
        { "id": "PageHead",     "type": "PageHead" },
        { "id": "HeroBanner",   "type": "HeroBanner" },
        { "id": "Footer",       "type": "Footer", "loadingStrategy": "lazy" }
      ],
      "version": "1.0.0"
    }
  }
]

| Field | Description | |---|---| | url | The URL path for this page | | renderId | Unique ID; becomes the output folder name inside out/ | | dataHandler | Filename (no extension) of the handler in src/handlers/ | | rootLayout | Filename (no extension) of the layout in src/layouts/ | | widgets[] | Ordered list of widgets to render on this page | | loadingStrategy | "lazy" to defer widget JS until after page is interactive |


Data Handlers

Async functions that run before any JSX is rendered. They fetch data and return a plain object whose keys match widget ids.

// src/handlers/HomeDataHandler.ts
const getHomeData = async () => {
  const posts = await fetch("https://cms.example.com/api/posts").then(r => r.json());

  return {
    status: 200,           // required — signals render success
    PageHead: {
      title: "Home",
    },
    HeroBanner: {
      heading: "Welcome",
      posts,
    },
  };
};

export default getHomeData;
  • Must be the default export
  • Must return { status: 200, ...widgetData }
  • Each top-level key (except status) must match a widget id in the sitemap
  • Fully async — await any API, CMS, or database call here

Layouts

TSX components that return the full HTML document. They contain no business logic — only structure and WidgetPlaceholder slots.

// src/layouts/MainLayout.tsx
import { WidgetPlaceholder } from "streak/components";

const MainLayout = () => (
  <html lang="en">
    <head>
      <WidgetPlaceholder id="PageHead" type="PageHead" />
    </head>
    <body>
      <WidgetPlaceholder id="NavBar"     type="NavBar"     />
      <WidgetPlaceholder id="HeroBanner" type="HeroBanner" />
      <WidgetPlaceholder id="Footer"     type="Footer"     />
    </body>
  </html>
);

export default MainLayout;

At build time, each WidgetPlaceholder is replaced with the fully rendered HTML of the matching widget.


Widgets

Stateless TSX components rendered once at build time. They receive handler data as props.data and return a section of page HTML.

// src/widgets/HeroBanner.tsx
type HeroBannerProps = {
  data?: {
    heading?: string;
  };
};

const HeroBanner = (props: HeroBannerProps) => (
  <section class="hero">
    <h1>{props?.data?.heading ?? "Welcome"}</h1>
  </section>
);

export default HeroBanner;

Rules:

  • Filename must exactly match the type in the sitemap (case-sensitive)
  • Must be the default export
  • Data arrives as props.data — always use ?. and ?? as data can be undefined
  • No useState, no useEffect — widgets are pure build-time functions
  • Client-side interactivity lives in <Script> components inside the widget

Adding Client-Side Behavior with <Script>

The Script component serializes a function to a string at build time and runs it as an IIFE in the browser. The first argument is gDomwindow extended with Streak's runtime helpers.

import { Script } from "streak/components";

const HeroBanner = (props: HeroBannerProps) => (
  <section>
    <h1 id="hero-heading">{props?.data?.heading ?? "Welcome"}</h1>
    <Script id="hero-script" options={{ color: "#818cf8" }}>
      {(gDom: any, options: any) => {
        gDom.geById("hero-heading").style.color = options.color;
      }}
    </Script>
  </section>
);

Loading Strategies

| Strategy | HTML in initial payload | JS loaded | Best for | |---|---|---|---| | Default (no loadingStrategy) | Yes | Immediately | Hero, nav, above-the-fold | | "lazy" | Yes | After page is interactive | Footer, below-fold sections | | <Dynamic> component | No | On demand via loadDynamicComponent() | Modals, menus, overlays |


Runtime API (gDom)

Inside Script functions, gDom is window extended with:

| Method | Description | |---|---| | gDom.ftr | true on user's first visit (30-min session) | | gDom.loadPackage(path) | Loads a JS/CSS file from public/assets/ via the asset worker | | gDom.loadDynamicComponent(id, cb) | Injects a <Dynamic> component's HTML on demand | | gDom.onVisible(el, cb) | IntersectionObserver wrapper — fires cb when el enters viewport | | gDom.debounce(fn, delay) | Returns a debounced version of fn | | gDom.geById(id) | Shorthand for document.getElementById | | gDom.stall(ms) | Promise that resolves after ms milliseconds | | gDom.setCookie(name, value, days) | Sets a browser cookie | | gDom.getCookie(name) | Reads a browser cookie |

Load third-party libraries via the asset worker:

await gDom.loadPackage("js/motion.js");
const { animate, scroll } = gDom.Motion;

await gDom.loadPackage("js/lenis.min.js");
const lenis = new gDom.Lenis();

The 7-Stage Rendering Pipeline

When streak-forge pre-build runs, each sitemap entry passes through:

| Stage | Name | Description | |---|---|---| | 1 | validateStreakConfig | Validates the sitemap entry structure | | 2 | pageDataHandler | Calls the async data handler | | 3 | renderRootLayout | Renders the layout JSX to an HTML string | | 4 | renderWidgets | Renders each widget and injects into the layout | | 5 | pageBuildAndOptimize | Optimizes the output (build only) | | 6 | prepareStyle | Embeds or links CSS (build only) | | 7 | prepareRawForBuild | Writes out/<renderId>/index.html (build only) |

In dev mode, stages 5–7 are replaced with hot-reload variants that serve over HTTP without writing to disk.


Configuration

tsconfig.json

{
  "compilerOptions": {
    "jsx": "react-jsx",
    "moduleResolution": "bundler",
    "baseUrl": "src/",
    "strict": true,
    "target": "ESNext",
    "module": "ESNext",
    "types": ["bun-types"]
  },
  "include": ["src/**/*"]
}

Environment Variables

| Variable | Default | Description | |---|---|---| | NODE_ENV | "development" | Set to "production" for production builds | | PORT | 3690 | Dev server port | | STATIC_BUILD_DIR | "out" | Output directory for pre-build | | TARGET_SRC | "src" | Root directory for handlers, layouts, and widgets |


Deployment

Production builds are handled by Nexus — the Streak cloud build and deployment system. When you publish through Nexus, it runs the build pipeline and deploys the output automatically. Local bun run build is used for testing; Nexus runs it for production.

Refer to the Nexus documentation for publishing and deployment details.


Full Documentation

Complete documentation is available at docs.streakjs.com.


License

Licensed under the Apache License, Version 2.0.

Copyright 2026 Valoriz Digital

You may use, reproduce, modify, and distribute this software under the terms of the Apache 2.0 license. See the LICENSE file for the full license text, or visit apache.org/licenses/LICENSE-2.0.


Built and maintained by Valoriz Digitalnpm org · GitHub · Docs