Skip to content

Repository files navigation

BBS Nostalgia Simulator

An authentic 1990s BBS (Bulletin Board System) dial-up experience in your browser. Features character-by-character ANSI art streaming at simulated modem speeds with automatic rotation through 731 classic BBS welcome screens.

Live Demo: bbs.nitwit.se

Features

  • 731 ANSI Art Files - Classic BBS welcome screens from the 1990s
  • Authentic Modem Simulation - ATZ, ATDT dial sequences, and NO CARRIER disconnect
  • Variable Baud Rates - 2400, 9600, or 28800 baud based on file size
  • IBM EGA Graphics - Authentic DOS font and 16-color palette
  • CRT Effects - Scanline overlay for authentic terminal feel
  • Lazy Loading - Fast initial load (~60KB), on-demand chunk loading
  • Auto-Rotation - Automatically connects to random BBS after each session

Tech Stack

Modern (2025):

  • ES6+ modules with async/await
  • Vite 5 build system
  • @xterm/xterm 5.5.0 terminal emulator
  • Lazy-loaded JSON chunks
  • Zero dependencies (no jQuery)

Preserved Authenticity:

  • CP437 (DOS) character encoding
  • IBM EGA color palette
  • Original timing and baud rate simulation
  • Character-by-character rendering

Project Structure

bbsss/
├── src/                      # Source code
│   ├── main.js              # Application entry point
│   ├── terminal/            # Terminal configuration & CP437 mapping
│   ├── modem/               # Modem simulation sequences
│   ├── renderer/            # ANSI rendering & timing
│   ├── ui/                  # Status bar & UI updates
│   └── data/                # ANSI data loader
├── public/                   # Static assets
│   ├── data/                # JSON chunks (generated)
│   ├── fonts/               # IBM EGA fonts
│   └── scanlines.png        # CRT effect overlay
├── ansi/                     # Source ANSI files (731 files)
├── dist/                     # Production build output
├── generate.py              # Generate JSON chunks from ANSI files
├── package.json
└── vite.config.js

Quick Start

Prerequisites

  • Node.js 18+
  • Python 3 (for regenerating data)

Development

# Install dependencies
npm install

# Start dev server (http://localhost:3000)
npm run dev

# Build for production
npm run build

# Preview production build (http://localhost:4173)
npm run preview

Regenerating ANSI Data

If you add/remove ANSI files in the ansi/ directory:

python3 generate.py

This creates:

  • public/data/index.json - File index (57KB)
  • public/data/chunk-*.json - Data chunks (8 files, ~600KB each)

Deployment

Deploy to Static Host

The dist/ directory contains everything needed:

npm run build
# Upload contents of dist/ to your web server

What gets deployed:

  • index.html - Entry point
  • assets/ - Bundled JS (~296KB) and CSS (~4KB)
  • data/ - JSON chunks (8 files, ~5MB total)
  • fonts/ - IBM EGA fonts
  • scanlines.png - CRT overlay

Deploy to GitHub Pages

npm run build
# Push dist/ contents to gh-pages branch

Using with macOS Screen Saver

The screen saver can load the website directly from bbs.nitwit.se:

  1. Configure your web-based screen saver to point to https://bbs.nitwit.se
  2. The application will auto-rotate through BBS systems
  3. Works offline if you deploy dist/ locally

Performance

Bundle Size

  • Initial Load: 75KB gzipped (JS + CSS)
  • First ANSI: +57KB (index.json) + ~600KB (one chunk)
  • Total Assets: ~5.4MB (all chunks + fonts)

Load Time Comparison

Before modernization:

  • 5.5MB embedded ANSI data loaded immediately
  • Slow initial page load

After modernization:

  • ~60KB initial load (98% reduction!)
  • Chunks loaded on-demand
  • Sub-second initial render

Architecture Highlights

Lazy Loading

// Load index once (57KB)
const index = await loadIndex();

// Select random file
const file = index.files[randomIndex];

// Load only needed chunk (~600KB)
const chunk = await loadChunk(file.chunk);

Async Flow

async function BBSLoop() {
  await delay(200 * timeScale);
  await writePreamble(terminal, baudRate, timeScale);
  await writeWithDelay(terminal, content, 24, timeScale);
  await writePostamble(terminal, timeScale);
  window.location.reload();
}

Module Organization

  • terminal/ - Configuration, CP437 encoding
  • modem/ - Preamble/postamble sequences
  • renderer/ - Character streaming, timing
  • ui/ - Status bar, clock
  • data/ - ANSI loading with caching

Configuration

Edit src/terminal/config.js to customize:

export const BAUD_RATES = {
  SLOW: 2400,    // For files < 3000 bytes
  MEDIUM: 9600,  // For files 3000-10000 bytes
  FAST: 28800    // For files > 10000 bytes
};

export const FILE_SIZE_THRESHOLDS = {
  SMALL: 3000,
  LARGE: 10000
};

Browser Support

  • Chrome/Edge 90+
  • Firefox 88+
  • Safari 14+

Requires ES6 modules and async/await support.

Credits

License

ISC

Modernization Journey

This codebase was modernized from a 2010s-era hack into clean, maintainable 2025 code:

Phase 1: Vite + ES6 modules Phase 2: Removed jQuery, extracted modules Phase 3: Converted callbacks to async/await Phase 4: Lazy-loaded JSON chunks (98% size reduction) Phase 5: Upgraded to xterm.js v5.5.0 Phase 6: Production build & testing

See git history for the complete transformation!

About

BBS Screensaver

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages