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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@e280/scute

v0.1.2

Published

buildy bundly static site generator

Downloads

357

Readme

🐢 scute

buildy bundly buddies for websites and web apps

npm install --save-dev @e280/scute

@e280/scute contains three lil buddies:

  • 🐢 #scute — eponymous zero-config build cli
  • 🪄 #ssg — html templating library for static site generation
  • 🐙 #octo — watch routine terminal multiplexer cli

👷 project setup

"the golden path."
just an example of how we like to setup our projects

  1. we setup our typescript apps with ts code in s/ dir, and outputting to x/ dir
  2. we install a server like http-server for previewing our app in development
  3. we setup a tests.test.ts test suite with @e280/science
  4. we add these scripts to package.json
    "scripts": {
      "build": "rm -rf x && tsc && scute -v",
      "test": "node x/tests.test.js",
      "watch": "npm run build && octo 'scute -vw' 'tsc -w' 'node --watch x/tests.test.js' 'http-server x'"
    }
  5. now we can run these commands
    • npm run build — run your project build
    • npm run watch — start a watch routine
    • npm run test — run our test suite

🐢 scute cli

zero-config build tool and static site generator

  • scute command builds your project
  • scute -v for verbose mode so you can see what's up
  • scute -vw for watch mode
  • scute --help
    🐢 scute {params}
      readme https://github.com/e280/scute
      zero-config static site generator
      - bundles .bundle.js files with esbuild
      - copies files like .css and .json
      - builds .html.js template files
      - executes .exe.js scripts
    
      --watch, -w, flag boolean
        watch mode
    
      --in, default string-list s
        dirs to read from
    
      --out, default string x
        output dir
    
      --bundle, default boolean yes
        should we bundle .bundle.js files?
    
      --copy, default string-list **/*.css,**/*.json,**/*.txt
        what files should we copy verbatim?
    
      --html, default boolean yes
        should we build .html.js templates?
    
      --exe, default boolean yes
        should we execute .exe.js scripts?
    
      --debounce, default number 200
        milliseconds to wait before watch routine build
    
      --exclude, optional string-list
        what files should we ignore?
    
      --verbose, -v, flag boolean
        should we log a bunch of crap?
  • by default we use s/ and x/, instead of src/ and dist/. it's our weird e280 tradition. if you wanna be a normie, do this:
    scute --in="src" --out="dist"

🪄 ssg html templating library

library for static site generation

import {ssg, html} from "@e280/scute"
  • ssg is a toolkit for templating and paths and stuff
  • html is for writing html, and interleaving it with async js
  • orb does path/url magic and hash-version cache-busting

ssg.page quickstart homepage

  • make a web page. it makes an document. let's make index.html.ts
    export default ssg.page(import.meta.url, async orb => ({
      title: "cool website",
      js: "main.bundle.min.js",
      css: "main.css",
      dark: true,
      favicon: "/assets/favicon.png",
    
      head: html`
        <meta name="example" value="whatever"/>
      `,
    
      socialCard: {
        themeColor: "#8FCC8F",
        title: "scute",
        description: "buildy bundly buddies",
        siteName: "https://e280.org/",
        image: `https://e280.org/assets/e.png`,
      },
    
      body: html`
        <h1>incredi website</h1>
      `,
    }))

    did you notice the orb? we must'nt yet speak of the all-powerful orb..

  • ssg.page is just sugar which produces an ordinary TemplateFn

html templating

  • html templating fns, with protection against injection attacks
  • basic usage
    html`<div>hello</div>`
  • it returns an Html instance
    const h = html`<div>hello</div>`
    h.toString() // "<div>hello</div>"
  • strings are safely sanitized
    html`<div>${"<evil/>"}</div>`.toString()
      // "<div>&lt;evil/&gt;</div>"
  • html.raw to circumvent sanitization (🚨 allowing injection attacks, lol)
    html`<div>${html.raw("<evil/>")}</div>`.toString()
      // "<div><evil/></div>"
  • html.render produces a string. it's async and resolves injected promises
    await html`<div>${Promise.resolve("async magic")}</div>`.render()
      // "<div>async magic</div>"
    the rendering is handled automatically by the scute cli

ssg.template pages

  • ssg.template produces a TemplateFn.
    if it's the default export, and your module has a .html.ts or .html.js extension, the scute build cli will automatically build the .html page.
  • page.html.ts
    import {partial} from "./partial.js"
    
    export default ssg.template(import.meta.url, async orb => html`
      <!doctype html>
      <html>
        <head>
          <title>scute</title>
          <script type="module" src="${orb.hashurl("main.bundle.min.js")}"></script>
        </head>
        <body>
          <h1>scute is good</h1>
          ${orb.place(partial)}
        </body>
      </html>
    `)

    orb.place to insert one template into another, while maintaining relative pathing..

ssg.template partials

  • we can inject one ssg template into another. let's make partial.ts
    export const partial = ssg.template(import.meta.url, async orb => html`
      <div>
        <img alt="" src="${orb.url("../images/turtle.avif")}"/>
      </div>
    `)
    • orb.url is relative to our module, partial.ts

🔮 the almighty orb

relative paths and urls

every template gets an orb

  • the orb's superpower is dealing with paths and urls
  • the orb allows you to reference files relative to the current template module,
    regardless of how you import html partials from all around your codebase.
    this should impress you.

orb pathing fns

  • orb.url("main.css") — 🧙‍♂️ important! for clientside browser urls!
    this outputs a browser url relative to the page (not partial).
    don't get confused here! the input is relative following the magic conventions. the output is page-relative.
    eg, you can use these urls as <script> src and such.
  • orb.path("main.css") — 🧙‍♂️ important! for serverside filesystem paths!
    this outputs a filesystem path relative to the current working directory.
    eg, you can use these paths in node readFile calls and such.
  • orb.hashurl("main.css") — 🧙‍♂️ important! saves you from browser cache problems!
    like orb.url, but it attaches a hash-version query param to the url.
    looks like main.css?v=cdd9738a8eda.
    this allows the browser to properly cache that exact version of the content.
    anything using orb.hashurl will not have stale caching problems in your deployments.
    yes, it's reading the target file on disk and producing a sha256 hash of it.

orb's magic pathing conventions

  • 🧙‍♂️ important! all orb functions that expect path strings respect these conventions
  • "main.css" — relative to the current template module
  • "./main.css" — relative to the current template module (same as above)
  • "/main.css" — relative to the server root (aka, your scute --out dir, maybe x/)
  • "$/main.css" — relative to the build process current working directory

more orb fns

  • orb.place(partial)
    prepare a partial template for insertion into this template, preserving relative pathing magic.
  • orb.inject("main.css")
    read the contents of that file, and inject it raw without sanitization.
    used to insert text directly, like , , json, stuff like that.
  • orb.packageVersion()
    returns the version string found in your package.json.

orb.io file operations

  • orb.io.read("main.css") — read a text file
  • orb.io.write("main.css", "* {}") — write a text file
  • orb.io.readJson("$/package.json") — read and parse a json file
  • orb.io.writeJson("$/package.json", {}) — write json to a file

ssg.exe executable scripts

  • your .exe.ts modules will be automatically executed, and they must provide a default exported exe fn like this:
    export default ssg.exe(import.meta.url, async orb => {
      await orb.io.write("blog.txt", "lol")
    })
  • this gives you access to an orb, which is useful for resolving paths relative to this module.
  • eg, imagine a script like blog.exe.ts where you read hundreds of markdown files and emit a webpage for each, or something like that.

🐙 octo cli

tiny watch routine terminal multiplexer

  • octo 'scute -vw' 'tsc -w' command runs your watch routine
  • each subcommand gets its own pane
  • press [ and ] to shimmy between panes, q to quit
  • octo --help
    🐙 octo ...commands
      tiny terminal multiplexer for watch routines
    
      ...commands,
        each command gets its own pane that you can flip between.
    
        for example,
          $ octo "scute -vw" "tsc -w"
    
        this will give you two panes,
          - press 1 to see the scute output
          - press 2 to see the tsc output
          - press [ or h or j to shimmy left
          - press ] or l or k to shimmy right
          - press backspace to clear the pane
          - press q or ctrl+c to quit
    
        local npm bin is available,
          $ scute -vw      # GOOD this works
          $ npx scute -vw  # BAD npx is unnecessary
  • here's a typical 4-pane watch routine with octo
    octo \
      "scute --verbose --watch" \
      "tsc -w" \
      "node --watch x/tests.test.ts" \
      "http-server x"

🧑‍💻 scute is by e280

reward us with github stars
build with us at https://e280.org/ but only if you're cool