Dynamic ASCII Art Components for the Browser
Five generative algorithms β each a living system, every render unique.
π Live Demo Β· π¦ Components Β· π Quick Start Β· π API Reference
The GlyphStream homepage β a live ASCII flow field runs as the hero background.
GlyphStream is an open-source generative ASCII art engine built for the browser. It uses particle-driven brightness fields, text measurement via pretext, and variable font rendering to create stunning, ever-changing ASCII art.
Each component is a living algorithm β not a static image. Every render is unique, driven by seeded randomness and emergent behavior.
- π¨ 5 distinct components β flow fields, typography, reactive art, ambient backgrounds, and face generation
- π§ Designer-first API β clean props for fonts, colors, particle counts, seeds
- β‘ Zero framework dependency β works with vanilla JS, React, Vue, anything
- π Color palettes β monochrome, gradient, multi-color modes
- π― Seeded randomness β reproduce any render with a seed value
- π± Responsive β works on any screen size
- ποΈ Built on pretext β precise text measurement by Cheng Lou
Generative ASCII art from layered Perlin noise flow fields. Particles follow vector forces, accumulating into organic density maps.
| Feature | Details |
|---|---|
| Use cases | Hero sections, generative backgrounds, loading screens |
| Modes | noise, spiral, waves |
| Particles | 100β2000 |
| Presets | calm, turbulent, spiral, waves, static-art |
| Live Demo β |
Particle-driven brightness field rendered with variable font weights, styles, and sizes. Supports proportional AND monospace side-by-side comparison.
| Feature | Details |
|---|---|
| Use cases | Portfolio hero pieces, typography showcases, generative art posters |
| Font variants | Multiple weights (300, 500, 800) Γ styles (normal, italic) |
| Attractors | lissajous, circular, random, mouse |
| Panels | Proportional + monospace comparison |
| Live Demo β |
ASCII art that responds to user input β mouse position, clicks, scroll, or custom data streams.
| Feature | Details |
|---|---|
| Use cases | Interactive installations, audio visualizers, data-driven art |
| Input modes | mouse, click, scroll, audio, custom |
| Color modes | velocity, position, time, palette |
| Brush | Configurable size, intensity, trail modes |
| Live Demo β |
Slow, meditative ASCII art that evolves over time. Minimal particle count, gentle forces, long decay times.
Watch the ambient background breathe and drift in real-time.
| Feature | Details |
|---|---|
| Use cases | Ambient screensavers, portfolio backgrounds, meditation apps |
| Particles | 20β80 (low count for minimalism) |
| Force modes | gentle, drift, breathe |
| Color modes | dawn, dusk, midnight, custom |
| Live Demo β |
Procedurally generated talking faces with random gender, features, and accessories.
| Feature | Details |
|---|---|
| Use cases | Fun demos, avatar generation, procedural art |
| Randomization | Gender, eye shape, mouth style, accessories |
| Color coding | Blue tones, pink tones, custom palettes |
| Live Demo β |
git clone https://github.com/Poojan38380/glyphstream.git
cd glyphstream
npm install
npm run devOpen http://localhost:3001 β that's it.
Each component is a self-contained TypeScript module. Import and instantiate:
import { AsciiFlowField } from './src/components/ascii-flow-field'
const art = new AsciiFlowField('#container', {
cols: 80,
rows: 40,
particleCount: 600,
noiseScale: 0.005,
colorMode: 'gradient',
palette: ['#c4a35a', '#8b6914', '#4a3520'],
seed: 42,
})
art.start()
art.setPreset('turbulent')
art.regenerate(123) // new seed, new artnpm run buildOutput goes to dist/ β deploy anywhere as a static site.
Every component follows the same pattern:
class AsciiComponent {
constructor(container: string | HTMLElement, config: ComponentConfig)
start(): void // Begin animation
stop(): void // Stop animation
dispose(): void // Clean up (important for SPAs)
regenerate(seed?: number): void // New seed
setPreset(name: string): void // Apply a preset
updateConfig(partial: Partial<ComponentConfig>): void
getElement(): HTMLElement
}| Option | Type | Default | Description |
|---|---|---|---|
cols |
number |
80 |
Grid columns |
rows |
number |
40 |
Grid rows |
fontSize |
number |
12 |
Font size in px |
fontFamily |
string |
'Georgia, serif' |
CSS font family |
charset |
string |
' .,:;!+-=*#@%' |
Character ramp (dark β light) |
colorMode |
string |
'monochrome' |
'monochrome' | 'gradient' | 'palette' |
palette |
string[] |
[] |
Array of hex colors |
seed |
number |
random |
Random seed for reproducibility |
decay |
number |
0.94 |
Field decay rate (0.0β1.0) |
| Option | Type | Default | Description |
|---|---|---|---|
particleCount |
number |
600 |
Number of particles |
noiseScale |
number |
0.005 |
Noise zoom level |
noiseOctaves |
number |
3 |
Noise detail level |
particleSpeed |
number |
1.0 |
Speed multiplier |
flowMode |
string |
'noise' |
'noise' | 'spiral' | 'waves' |
monochromeColor |
string |
'#c4a35a' |
Color for monochrome mode |
| Option | Type | Default | Description |
|---|---|---|---|
weights |
number[] |
[300, 500, 800] |
Font weights |
styles |
string[] |
['normal', 'italic'] |
Font styles |
monoFontFamily |
string |
'Courier New, monospace' |
Monospace font |
attractorMode |
string |
'lissajous' |
'lissajous' | 'circular' | 'random' | 'mouse' |
showMono |
boolean |
true |
Show monospace panel |
showSource |
boolean |
false |
Show source simulation |
monoTint |
string |
'rgba(130,155,210,0.7)' |
Monospace panel tint |
| Option | Type | Default | Description |
|---|---|---|---|
inputMode |
string |
'mouse' |
'mouse' | 'click' | 'scroll' | 'audio' | 'custom' |
brushSize |
number |
8 |
Reactive brush size |
brushIntensity |
number |
0.6 |
Brightness per interaction |
trailMode |
string |
'fade' |
'fade' | 'accumulate' | 'bounce' |
| Option | Type | Default | Description |
|---|---|---|---|
particleCount |
number |
40 |
Low count (20β80) |
speed |
number |
0.15 |
Very slow evolution |
forceMode |
string |
'breathe' |
'gentle' | 'drift' | 'breathe' |
colorMode |
string |
'dawn' |
'dawn' | 'dusk' | 'midnight' | 'custom' |
cycleTime |
number |
60000 |
Full color cycle in ms |
glyphstream/
βββ README.md # You are here
βββ PLAN.md # Full project vision & architecture
βββ package.json # Dependencies & scripts
βββ vite.config.ts # Vite MPA configuration
βββ vercel.json # Vercel deployment config
βββ tsconfig.json # TypeScript configuration
β
βββ pages/
β βββ index.html # Homepage (gallery + playground)
β βββ demos/ # Individual component demos
β β βββ ascii-flow-field.html
β β βββ ascii-typography.html
β β βββ ascii-reactive.html
β β βββ ascii-ambient.html
β β βββ ascii-face-generator.html
β βββ src/ # All source code
β βββ core/ # Core generative engine
β β βββ brightness-field.ts
β β βββ char-palette.ts
β β βββ field-renderer.ts
β β βββ particle-system.ts
β β βββ types.ts
β βββ components/ # 5 reusable components
β β βββ ascii-flow-field/
β β βββ ascii-typography/
β β βββ ascii-reactive/
β β βββ ascii-ambient/
β β βββ ascii-face-generator/
β βββ utils/ # Shared utilities
β βββ color.ts
β βββ dom.ts
β βββ math.ts
β
βββ public/ # Static assets (screenshots, videos)
βββ dist/ # Production build output
| Layer | Technology |
|---|---|
| Language | TypeScript (strict mode) |
| Build | Vite 5 (Multi-Page App) |
| Text Measurement | @chenglou/pretext |
| Rendering | Canvas 2D + DOM |
| Deployment | Vercel (static site) |
| Dependencies | 1 runtime dependency (pretext) |
Algorithmic art as living systems β beauty emerges from process, not product.
GlyphStream is built on the idea that every render tells a different story. The same seed, the same parameters β but watch it breathe, and you'll never see the exact same art twice.
Projects and demos powered by GlyphStream:
- glyphstream.vercel.app β Live demo site
Built something with GlyphStream? Open a PR and add it here!
We love contributions! Whether it's:
- π Bug fixes
- β¨ New components
- π¨ New presets
- π Documentation improvements
- π Performance optimizations
See CONTRIBUTING.md for guidelines.
MIT β Free to use, modify, and distribute. Attribution appreciated but not required.
- Built by Poojan
- Text measurement powered by pretext by Cheng Lou
- Inspired by pretext's
variable-typographic-asciidemo
Made with β and ASCII characters




