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

tiny-mood

v0.3.1

Published

Tiny, zero-dependency text-to-mood-to-color utility. Consumes a pre-built mood table JSON — use tiny-mood-generate to build one from your content.

Readme

tiny-mood

Generate deterministic, mood-driven background colors from text — no images, no LLM calls, no network requests at runtime. Just a word table and OKLCH color math.

Feed it a blog post's title and description, get back a CSS background gradient that reflects the tone of the text — calmer posts render softer and cooler, energetic posts render brighter and warmer — optionally clamped to your own brand colors so it never looks off-brand.

What it is

tiny-mood looks up each word in your text against a small mood table (word → weight/energy/warmth), averages the matches into a single mood vector, then maps that vector onto an OKLCH color palette. The result is rendered as a soft, blurred gradient background — entirely deterministic, so the same text and seed always produce the same output.

The mood table itself is just JSON. You can use the small built-in default, or generate your own from your actual content using tiny-mood-generate, a separate companion CLI that builds a table from your real vocabulary using GloVe word embeddings.

Install

npm install tiny-mood

Quick start

import { getMoodBackground } from 'tiny-mood'
import moodTable from './mood-table.json' // generated by tiny-mood-generate, or your own

const post = {
  title: 'Announcing our new release',
  description: 'A fast, exciting launch into something new',
  slug: 'announcing-release' // used as the seed for stable, repeatable layout
}

const { background, filter, mood } = getMoodBackground(
  `${post.title} ${post.description}`,
  moodTable,
  post.slug
)

// background and filter are ready-to-use CSS values:
// <div style={{ background, filter }} />

Examples

Basic usage, no brand constraint

const { background, filter } = getMoodBackground(text, moodTable, seed)

Hue varies freely based on the text's warmth — calm/cold text trends toward blues and greens, warm/energetic text trends toward oranges and reds.

Clamped to your brand colors

import { createBrandPalette, getMoodVector, composeBackground } from 'tiny-mood'

const brand = createBrandPalette({
  colors: ['#0f380f', '#306230', '#8bac0f', '#9bbc0f'] // any hex/rgb()/hsl() strings
})

const mood = getMoodVector(text, moodTable)
const palette = brand.paletteFor(mood)
const { background, filter } = composeBackground(palette, seed)

Mood now picks a position along the real spread of hues in your brand colors, rather than inventing a color outside your palette. A calm post and an energetic post will land in genuinely different parts of your brand's color range, not just vary in lightness.

One-liner with brand colors

const { background, filter } = getMoodBackground(text, moodTable, seed, {
  colors: ['#0f380f', '#306230', '#8bac0f', '#9bbc0f']
})

Same effect as above, without the intermediate steps — pass colors directly and getMoodBackground derives the brand palette internally.

Controlling the visual shape

const { background, filter } = getMoodBackground(text, moodTable, seed, {
  colors: brandColors,
  blendShape: 'linear',      // 'round' | 'linear' | 'spiral'
  blendIntensity: 0.7,        // 0–1, how strongly the shape expresses
  blendAngleRange: [100, 160] // direction guardrail, degrees
})

round (the default) produces soft, organic blooms. linear produces diagonal color streaks. spiral produces sharper conic wedge-rays — a different visual register from the other two, intentionally less blurred so its structure stays visible.

Functions

getMoodBackground(text, table, seed?, options?)

The main convenience function. Extracts a mood vector from text using table, generates a palette (brand-clamped if options.colors is provided, otherwise free-hue), and composes it into CSS.

Returns { background, filter, mood }.

getMoodVector(text, table)

Extracts just the mood vector, if you want it without rendering anything.

Returns { weight, energy, warmth }, each roughly in the range -1 to 1.

createBrandPalette(options)

Builds a reusable palette generator from your brand colors.

const brand = createBrandPalette({ colors: [...] })
brand.paletteFor(mood) // -> Oklch[]
brand.sortedColors      // your colors, sorted by hue, for inspection

composeBackground(palette, seed, options?)

Lower-level: takes an array of OKLCH colors and a seed, returns the final { background, filter } CSS strings. Use this directly if you're building your own palette logic instead of createBrandPalette.

Parameters reference

| Parameter | Where | Type | Default | What it does | |---|---|---|---|---| | colors | getMoodBackground options, createBrandPalette | string[] | — | Your brand colors (hex, rgb()/rgba(), hsl()/hsla()). Omit for free-hue output. | | blendShape | getMoodBackground options, composeBackground options | 'round' \| 'linear' \| 'spiral' | 'round' | The visual form of each color region. | | blendIntensity | same | number (0–1) | 0 | How strongly the selected shape expresses. 0 always looks like round regardless of blendShape. | | blendAngleRange | same | [number, number] | [100, 160] | Degree range streak/spiral direction is randomly drawn from per post. Has no effect when blendShape is 'round'. | | blobCount | composeBackground options | number | 5 | Number of color regions composited together. | | blurPx | composeBackground options | number | 70 | Base blur radius. Actual blur is reduced automatically as blendIntensity rises, more aggressively for spiral than linear. | | blobAlpha | composeBackground options | number | 0.7 | Opacity of each color region before blending. | | moodToPosition | createBrandPalette options | (mood) => number | warmth-weighted blend | Override how the 3-axis mood vector becomes a single position along your sorted brand colors. |

Where the mood table comes from

tiny-mood itself ships with a small default table, but the better option for a real project is generating one from your actual content with tiny-mood-generate:

npx tiny-mood-generate ./content ./mood-table.json

This reads your blog posts, looks up each word's real semantic position using GloVe embeddings, and writes a small JSON table containing only the words your content actually uses. tiny-mood's runtime has no dependency on GloVe or any generation tooling — it only ever reads the resulting JSON.

Try it live

StackBlitz demo — tabbed examples with brand presets, blend shapes, and an interactive Blend Lab.

License

MIT