# xeerpe (v1.0.9): complete reference for AI assistants
> Generated by scripts/generate-ai-files.mjs. Docs: https://xeerpe.io. Short index: https://xeerpe.io/llms.txt
xeerpe turns a chain of layers into one inline-style object.
Zero dependencies, works in React, Vue, Angular and plain JS. Package: `xeerpe`.
## When to use / not use
Use it for layered backgrounds, animated backgrounds without hand-written keyframes, backgrounds computed from props/state/theme, presets, and gradient text. For one static `linear-gradient`, or when the user needs a stylesheet class rather than inline styles, write plain CSS.
## Core pattern
```ts
import { Builder } from 'xeerpe'
const style = new Builder()
.meshGradient({
background: '#04121c',
layers: [{ position: '15% 25%', from: 'rgba(16,185,129,0.8)', to: 'transparent', colorToPosition: '60%' }],
})
.dots({ color: '#10b981', size: '24px', opacity: 0.14 })
.grain({ intensity: 2 })
.toStyle()
```
- React: `
`; Vue: `:style="style"`; Angular: `[style]="style"`; vanilla: `Object.assign(el.style, style)`.
- `toStyle()` returns an object, not a string. `el.style.cssText = style` does not work.
- Gradient text: `new Builder().linearGradient({...}).toTextStyle()`. It returns `backgroundClip`/`WebkitBackgroundClip: 'text'`, transparent `color`/`WebkitTextFillColor`, plus `backgroundImage`/`backgroundSize`/`backgroundColor`; apply it to the text element.
- Shortcut methods (`grain()`, `vignette()`, `pulse()`, `dots()`, ...) can be called with no arguments; gradient methods need options. Imports: `import { Builder, Preset, colors } from 'xeerpe'`.
- Presets: `new Preset('sunrise').toStyle()`; it is a `Builder`, so keep chaining. Names are in the sections below; never invent one (unknown names throw).
## Rules that prevent bugs
1. **Layer order is fixed, not chain order.** `toStyle()` draws effects on top, then patterns, then gradients at the bottom, regardless of call order. Within the same kind, earlier calls are drawn first.
2. **Animations need the stylesheet.** Add `import 'xeerpe/animations.css'` once in the app entry. Without it the style applies but nothing moves and there is no error.
3. **Animations don't add a layer**; they add an `animation` property. `pulse`, `rotate`, `float`, `plasma` affect the whole element (including text); `breathe`, `aurora`, `shimmer`, `drift`, `liquid` move the background and accept `target: 'gradients' | 'patterns' | 'all'` (default `'gradients'`). Any other `target` throws.
4. Animation option values (`duration`, `easing`, ...) are not validated. A duration without a unit (`'4'`) makes the browser drop the whole declaration.
5. **Validated inputs**: colors (hex, `rgb()/hsl()/oklch()...`, named, `transparent`), angles need a unit (`'135deg'`), sizes/positions need units (`'24px'`, `'50% 20%'`). Exact rules in the sections below.
6. `meshGradient` requires `background` and `layers` (array of radial options). Use `to: 'transparent'` plus `colorToPosition` so blobs fade out.
7. `toStyle()` always sets `backgroundPosition: 'center'`.
## Picking tools
- Base color/shape: `linearGradient` (`from`/`to`, or `colors` with stop positions, `angle` or `direction`), `radialGradient`, `conicGradient`, `meshGradient`.
- Texture: `grain`, `noise`, `vignette`, `glow`.
- Pattern: `dots`, `grid`, `stars`, `rays`.
- Blur: `blur({ type: 'backdrop' })` for frosted glass.
- Motion: see rule 3 and the sections below.
- Ready-made look: `Preset`, then extend.
## xeerpe animations
Load the keyframes once in the app entry, or nothing moves (and nothing errors):
```ts
import 'xeerpe/animations.css'
```
An animation adds an `animation` CSS property (plus helper CSS variables for scoped ones). It never adds a background layer. Keyframes are prefixed `xeerpe-`.
Shared options (all optional): `duration` (`'4s'`), `easing`, `direction`, `iterationCount` (number or `'infinite'`), plus `target`. `direction` only matters for `pulse` and `aurora`. Values other than `target` are inserted into CSS unvalidated.
| Animation | Changes | Defaults (duration, easing, extras) | `target` |
| --------- | ----------------------------- | ------------------------------------- | -------------------------- |
| `pulse` | element opacity (1 to 0.7) | 4s, ease-in-out, alternate, infinite | no |
| `rotate` | element transform, full turn | 12s, linear, infinite | no |
| `breathe` | background size | 12s, ease-in-out, infinite | gradients / all |
| `aurora` | background size (gentle zoom) | 12s, ease-in-out, alternate, infinite | gradients / all |
| `shimmer` | background position (sweep) | 3s, linear, infinite | gradients / patterns / all |
| `liquid` | background position + hue | 8s, ease-in-out, infinite | gradients / patterns / all |
| `plasma` | element filter (hue cycle) | 6s, linear, infinite | no |
| `float` | element transform (bob) | 6s, ease-in-out, infinite | no |
| `drift` | background position (wander) | 10s, ease-in-out, infinite | gradients / patterns / all |
Guidance:
- `target` defaults to `'gradients'`: gradients move, patterns and effects (grain, vignette) stay put. Use `'all'` to move everything; `'patterns'` moves only patterns over a still gradient. Anything else throws.
- With the default target, grain/vignette/glow stay still while the gradient moves; set `target: 'all'` only if the effects should move too. For a "slow" animation, raise `duration` (defaults are listed above).
- `pulse`, `rotate`, `float`, `plasma` act on the whole element, text included. `rotate` suits square or round elements.
- Sliding animations (`shimmer`, `drift`) enlarge unsized gradients automatically; don't set `backgroundSize` on the gradient you animate.
- Generic form: `.animation('pulse', {})` (options required).
- Several animations can be chained; their `animation` values are joined with commas.
- Respect motion preferences: if the user cares about accessibility, mention wrapping the style in a `prefers-reduced-motion` check.
## xeerpe recipes
All recipes use only `import { Builder, Preset, colors } from 'xeerpe'`. Apply the result as an inline style.
### Glowing orange dark panel
```ts
new Builder()
.radialGradient({ from: '#FF7A18', to: 'transparent', position: '75% 25%' })
.linearGradient({ from: '#1a0b05', to: '#060302', angle: '160deg' })
.dots({ color: '#FF7A18', size: '24px', opacity: 0.14 })
.grain({ intensity: 2 })
.toStyle()
```
### Animated aurora (needs animations.css)
```ts
new Builder()
.meshGradient({
background: '#04121c',
layers: [
{ position: '15% 25%', from: 'rgba(16,185,129,0.8)', to: 'transparent', colorToPosition: '60%' },
{ position: '85% 30%', from: 'rgba(56,189,248,0.65)', to: 'transparent', colorToPosition: '55%' },
],
})
.aurora({ duration: '8s' })
.toStyle()
```
### Multi-stop linear gradient
```ts
new Builder()
.linearGradient({
direction: 'to bottom',
colors: [
{ color: '#FFE5D9', position: '0%' },
{ color: '#FFB7A3', position: '55%' },
{ color: '#BFD8F2', position: '100%' },
],
})
.toStyle()
```
### Gradient text
```ts
const textStyle = new Builder().linearGradient({ from: '#5EB847', to: '#BFD43F', angle: '135deg' }).toTextStyle()
// Hello
```
### Preset plus film look
```ts
new Preset('sunrise').grain({ intensity: 1.5 }).vignette({ color: '#7c2d12', intensity: 0.2, spread: 0.5 }).toStyle()
```
### Shimmering loading skeleton (needs animations.css)
```ts
new Builder()
.linearGradient({ colors: ['#1f2937', '#374151', '#1f2937'], angle: '90deg' })
.shimmer({ duration: '1.5s' })
.toStyle()
```
### Frosted glass panel
```ts
new Builder().blur({ amount: '12px', type: 'backdrop' }).toStyle()
// place over a colorful background; add a translucent background color in your own CSS
```
### Computed from a theme
```ts
const bg = (accent: string, base: string) =>
new Builder()
.radialGradient({ from: accent, to: 'transparent', position: '80% 10%' })
.linearGradient({ from: base, to: '#000000', angle: '180deg' })
.vignette({ intensity: 0.3 })
.toStyle()
```
## xeerpe API reference (v1.0.9)
> Generated file. Do not edit by hand.
### Builder methods
Every method returns the builder, so calls chain. Shortcut methods take optional options; the generic ones require them.
| Method | Options type |
| --- | --- |
| `linearGradient / radialGradient / conicGradient / meshGradient` | LinearGradientOptions / RadialGradientOptions / ConicGradientOptions / MeshGradientOptions (required) |
| `gradient(type, options)` | GradientOptions |
| `dots / grid / stars / rays` | DotsOptions / GridOptions / StarsOptions / RaysOptions (optional) |
| `noise / vignette / grain / glow` | NoiseOptions / VignetteOptions / GrainOptions / GlowOptions (optional) |
| `blur` | BlurOptions (optional) |
| `pulse / rotate / breathe / aurora / shimmer / liquid / plasma / float / drift` | AnimationOptions (optional) |
| `pattern / effect / filter / animation (type, options)` | generic forms, options required (use {} for defaults) |
| `toStyle()` | Record, camelCase CSS properties |
| `toTextStyle()` | Record, gradient-filled text |
`new Preset(name)` extends `Builder`; unknown names throw `Preset "" not found`.
### Option types (from lib/src/models)
#### gradient.ts
```ts
export type GradientType = 'linear' | 'radial' | 'conic' | 'mesh'
export type LinearGradientDirection =
'to top' | 'to bottom' | 'to left' | 'to right' | 'to top right' | 'to bottom right' | 'to top left' | 'to bottom left'
export type LinearGradientAngle = `${number}deg` | `${number}rad` | `${number}grad` | `${number}turn`
export type RadialGradientShape = 'circle' | 'ellipse' | null
export type RadialGradientSize = 'closest-side' | 'closest-corner' | 'farthest-side' | 'farthest-corner' | string
export type LinearGradientPositionUnit =
`${number}%` | `${number}px` | `${number}rem` | `${number}em` | `${number}vh` | `${number}vw` | `${number}vmin` | `${number}vmax`
export type LinearGradientPosition = LinearGradientPositionUnit | `calc(${string})`
export type GradientOptions = LinearGradientOptions | RadialGradientOptions | ConicGradientOptions | MeshGradientOptions
export type GradientColorStop = string | { color: string; position?: LinearGradientPosition }
export interface GradientBase {
from?: string
to?: string
backgroundSize?: string
}
export interface LinearGradientOptions extends GradientBase {
colors?: (string | GradientColorStop)[]
angle?: LinearGradientAngle
direction?: LinearGradientDirection
size?: string
}
export interface RadialGradientOptions extends GradientBase {
shape?: RadialGradientShape
position?: string
size?: RadialGradientSize
colorFromPosition?: string
colorToPosition?: string
}
export interface ConicGradientOptions extends GradientBase {
colors?: (string | GradientColorStop)[]
angle?: string
position?: string
}
export interface MeshGradientOptions extends GradientBase {
background: string
layers: RadialGradientOptions[]
}
```
#### pattern.ts
```ts
export type PatternType = 'dots' | 'grid' | 'stars' | 'rays'
export interface PatterBaseOptions {
color?: string
background?: string
size?: string
opacity?: number
strokeWidth?: string
backgroundSize?: string
}
export interface DotsOptions extends PatterBaseOptions {
color?: string
background?: string
size?: string
spacing?: string
style?: string
opacity?: number
}
export interface GridOptions extends PatterBaseOptions {}
export interface StarsOptions extends PatterBaseOptions {
count?: number
seed?: number
}
export interface RaysOptions extends PatterBaseOptions {
count?: number
position?: string
angle?: string
}
export type PatternOptions = DotsOptions | GridOptions | StarsOptions | RaysOptions
```
#### effects.ts
```ts
export type EffectType = 'noise' | 'vignette' | 'grain' | 'glow'
export type EffectOptions = NoiseOptions | VignetteOptions | GrainOptions | GlowOptions
export type NoiseType = 'turbulence' | 'fractalNoise'
export type GlowType = 'outer' | 'inner'
export interface NoiseOptions {
opacity?: number
scale?: number
type?: NoiseType
octaves?: number
backgroundSize?: string
}
export interface VignetteOptions {
color?: string
intensity?: number
spread?: number
backgroundSize?: string
}
export interface GrainOptions {
intensity?: number
size?: string
animated?: boolean
backgroundSize?: string
}
export interface GlowOptions {
amount?: string
spread?: string
x?: string
y?: string
color?: string
type?: GlowType
}
```
#### filters.ts
```ts
export type FilterType = 'blur'
export type BlurType = 'backdrop' | 'blur'
export type FilterOptions = BlurOptions
export interface BlurOptions {
amount?: string
type?: BlurType
}
```
#### animation.ts
```ts
export type AnimationType = 'pulse' | 'rotate' | 'breathe' | 'aurora' | 'shimmer' | 'liquid' | 'plasma' | 'float' | 'drift'
export type AnimationTarget = 'gradients' | 'patterns' | 'all'
export interface AnimationOptions {
duration?: string
easing?: string
direction?: 'normal' | 'reverse' | 'alternate' | 'alternate-reverse'
iterationCount?: number | 'infinite'
target?: AnimationTarget
}
```
### Input validation (from lib/src/validations)
Values that fail these checks are rejected by the builder. Keep inputs inside these shapes.
#### color.ts
```ts
export const HEX_REGEX = /^#([0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/
const COLOR_FUNC_REGEX = /^(rgb|rgba|hsl|hsla|oklch|color|hwb|lch|lab)\(.+\)$/i
const NAMED_COLOR_REGEX = /^[a-zA-Z]+$/
export const isHexColor = (value: string): boolean => HEX_REGEX.test(value.trim())
export const isValidColor = (value: string): boolean => {
const t = value.trim()
return (
HEX_REGEX.test(t) ||
COLOR_FUNC_REGEX.test(t) ||
t === 'transparent' ||
t === 'currentColor' ||
t === 'inherit' ||
NAMED_COLOR_REGEX.test(t)
)
}
```
#### angle.ts
```ts
import { LinearGradientAngle } from '../models/index.ts'
const ANGLE_UNIT_REGEX = /^-?\d*\.?\d+(deg|rad|grad|turn)$/
export const isValidAngle = (value: string): value is LinearGradientAngle => ANGLE_UNIT_REGEX.test(value.trim())
```
#### backgroundSize.ts
```ts
const GLOBALS: readonly string[] = ['auto', 'cover', 'contain', 'initial', 'inherit', 'unset']
const SIZE_TOKEN_REGEX = /^(\d*\.?\d+(px|%|rem|em|vh|vw|vmin|vmax))$/
const CALC_REGEX = /^calc\(.+\)$/
const isValidSizeToken = (value: string): boolean => GLOBALS.includes(value) || SIZE_TOKEN_REGEX.test(value) || CALC_REGEX.test(value)
export const isValidBackgroundSize = (value: string): boolean => {
const trimmed = value.trim()
if (GLOBALS.includes(trimmed)) return true
const parts = trimmed.split(/\s+/)
return parts.length <= 2 && parts.every(isValidSizeToken)
}
```
#### cssPosition.ts
```ts
const KEYWORD_REGEX = /^(top|bottom|left|right|center)$/
const LENGTH_REGEX = /^-?\d*\.?\d+(%|px|rem|em|vh|vw|vmin|vmax)$/
const CALC_REGEX = /^calc\(.+\)$/
const VALID_DOUBLE_KEYWORDS: readonly string[] = [
'top left',
'top center',
'top right',
'center left',
'center center',
'center right',
'bottom left',
'bottom center',
'bottom right',
'left top',
'left center',
'left bottom',
'right top',
'right center',
'right bottom',
]
const isValidToken = (value: string): boolean => KEYWORD_REGEX.test(value) || LENGTH_REGEX.test(value) || CALC_REGEX.test(value)
export const isValidCSSPosition = (value: string): boolean => {
const trimmed = value.trim()
if (trimmed === 'center') return true
if (VALID_DOUBLE_KEYWORDS.includes(trimmed)) return true
const parts = trimmed.split(/\s+/)
return parts.length <= 2 && parts.every(isValidToken)
}
```
#### directions.ts
```ts
import { LinearGradientDirection } from '../models/index.ts'
const VALID_DIRECTIONS: readonly LinearGradientDirection[] = [
'to top',
'to bottom',
'to left',
'to right',
'to top right',
'to bottom right',
'to top left',
'to bottom left',
]
export const isValidDirection = (value: string): value is LinearGradientDirection => (VALID_DIRECTIONS as readonly string[]).includes(value)
```
#### position.ts
```ts
import { LinearGradientPosition } from '../models/index.ts'
const POSITION_REGEX = /^-?\d*\.?\d+(%|px|rem|em|vh|vw|vmin|vmax)$/
const CALC_REGEX = /^calc\(.+\)$/
export const isValidPosition = (value: string): value is LinearGradientPosition => {
const trimmed = value.trim()
return POSITION_REGEX.test(trimmed) || CALC_REGEX.test(trimmed)
}
```
#### radial.ts
```ts
import { RadialGradientShape, RadialGradientSize } from '../models/index.ts'
export const isValidRadialShape = (value: string | null): value is RadialGradientShape =>
value === null || value === 'circle' || value === 'ellipse'
const VALID_SIZE_KEYWORDS: readonly string[] = ['closest-side', 'closest-corner', 'farthest-side', 'farthest-corner', 'auto']
const LENGTH_REGEX = /^\d*\.?\d+(px|%|rem|em|vh|vw)(\s+\d*\.?\d+(px|%|rem|em|vh|vw))?$/
const CALC_REGEX = /^calc\(.+\)$/
export const isValidRadialSize = (value: string): value is RadialGradientSize => {
const trimmed = value.trim()
return VALID_SIZE_KEYWORDS.includes(trimmed) || LENGTH_REGEX.test(trimmed) || CALC_REGEX.test(trimmed)
}
```
## xeerpe presets (229, v1.0.9)
> Generated file. Do not edit by hand.
Usage: `new Preset('name').toStyle()`. Names are kebab-case and case-sensitive. A preset is a `Builder`, so you can keep chaining (`.grain()`, `.vignette()`, animations).
Category hints: `pastel`, `sky`, `neutral` are mostly light backgrounds (pair with dark text); `neon`, `space`, `luxury`, `moods` are mostly dark. Check the preview on xeerpe.io/guide/presets-examples when unsure.
### metals (20)
`gold`, `antique-gold`, `rose-gold`, `white-gold`, `champagne`, `gold-leaf`, `black-gold`, `silver`, `platinum`, `chrome`, `steel`, `titanium`, `gunmetal`, `bronze`, `copper`, `brass`, `mercury`, `holographic`, `iridescent`, `oil-slick`
### gems (16)
`emerald`, `sapphire`, `ruby`, `amethyst`, `topaz`, `citrine`, `garnet`, `aquamarine`, `turquoise`, `jade`, `tanzanite`, `opal`, `pearl`, `moonstone`, `rose-quartz`, `onyx`
### food (26)
`chocolate`, `dark-chocolate`, `milk-chocolate`, `white-chocolate`, `mint-chocolate`, `caramel`, `honey`, `espresso`, `cappuccino`, `matcha`, `vanilla`, `tiramisu`, `strawberry-milk`, `raspberry`, `blueberry`, `blackberry`, `cherry`, `red-wine`, `whisky`, `mango`, `peach`, `tangerine`, `lemonade`, `watermelon`, `pistachio`, `cotton-candy`
### nature (25)
`jungle`, `rainforest`, `forest`, `pine`, `moss`, `meadow`, `bamboo`, `desert`, `dunes`, `savanna`, `canyon`, `glacier`, `tundra`, `volcano`, `lava`, `ocean`, `lagoon`, `coral-reef`, `deep-sea`, `tropical`, `autumn`, `cherry-blossom`, `lavender-field`, `sunflower`, `wheat`
### sky (21)
`dawn`, `morning`, `golden-hour`, `sunrise`, `sunset`, `dusk`, `twilight`, `blue-hour`, `afterglow`, `midnight`, `starry-night`, `storm`, `fog`, `rain`, `snowfall`, `overcast`, `monsoon`, `rainbow`, `horizon`, `cloud-nine`, `solstice`
### space (17)
`galaxy`, `nebula`, `cosmos`, `milky-way`, `stardust`, `supernova`, `black-hole`, `eclipse`, `event-horizon`, `quasar`, `mars`, `jupiter`, `saturn`, `neptune`, `venus`, `moonlight`, `northern-lights`
### neon (16)
`cyberpunk`, `synthwave`, `outrun`, `retrowave`, `vaporwave`, `neon-tokyo`, `miami`, `laser`, `arcade`, `hologram`, `grid-runner`, `matrix`, `electric`, `ultraviolet`, `acid`, `neon-noir`
### pastel (20)
`cotton`, `marshmallow`, `lavender-haze`, `peach-fuzz`, `baby-blue`, `mint-cream`, `blush`, `lilac`, `sorbet`, `candy`, `cloud`, `powder`, `rosewater`, `buttercream`, `seafoam`, `apricot`, `daydream`, `unicorn`, `fairy-floss`, `bubblegum`
### neutral (16)
`paper`, `linen`, `ivory`, `porcelain`, `sand`, `stone`, `concrete`, `marble`, `black-marble`, `slate`, `smoke`, `ash`, `graphite`, `charcoal`, `ink`, `mono`
### luxury (14)
`velvet`, `emerald-velvet`, `silk`, `satin`, `champagne-silk`, `leather`, `cashmere`, `royal`, `imperial`, `bordeaux`, `noir`, `tuxedo`, `art-deco`, `boudoir`
### textures (14)
`blueprint`, `graph-paper`, `chalkboard`, `polka`, `halftone`, `terminal`, `carbon`, `film-noir`, `vintage`, `sepia`, `kraft`, `canvas`, `denim`, `cork`
### moods (12)
`spring`, `summer`, `harvest`, `winter`, `serenity`, `zen`, `calm`, `euphoria`, `romance`, `mystic`, `nostalgia`, `wanderlust`
### motion (12)
`lava-lamp`, `aurora-dream`, `aurora-australis`, `bioluminescence`, `breathing-nebula`, `ocean-drift`, `rainbow-drift`, `sunset-drift`, `molten-gold`, `liquid-silver`, `skeleton`, `ember`
### Palette (`colors`)
`import { colors } from 'xeerpe'` gives named hex values: `inkwell`, `obsidian`, `void`, `midnightOil`, `pitch`, `carbon`, `graphite`, `flint`, `stone`, `pewter`, `ash`, `smoke`, `bone`, `chalk`, `salt`, `parchment`, `linen`, `cream`, `absinthe`, `forestFloor`, `malachite`, `verdigris`, `celadon`, `fern`, `chartreuse`, `mantis`, `viridian`, `spruce`, `prussian`, `lapis`, `cobalt`, `cerulean`, `denim`, `glacier`, `powder`, `steel`, `maya`, `delft`, `indigoInk`, `wisteria`, `aubergine`, `amethyst`, `mauve`, `byzantium`, `mulberry`, `plum`, `heliotrope`, `iris`, `cinnabar`, `amaranth`, `carmine`, `rouge`, `garnet`, `crimson`, `venetian`, `blush`, `tomato`, `poppy`, `amber`, `saffron`, `ochre`, `goldenrod`, `harvest`, `copper`, `terra`, `sienna`, `umber`, `rust`, `coral`, `peach`, `apricot`, `cantaloupe`, `melon`, `spearmint`, `sage`, `taupe`, `khaki`, `dusk`, `slate`, `cadet`, `eucalyptus`, `clay`, `mushroom`, `tealDeep`, `aquamarine`, `seafoam`, `jade`, `turquoise`, `niagara`, `tiffany`, `pine`, `mint`, `patina`, `sakura`, `orchid`, `fandango`, `cerise`, `magenta`, `teal`, `sapphire`