Skip to content

building and developing

xero edited this page Nov 21, 2025 · 13 revisions

Building and Developing

This guide covers the build process, development workflow, tooling, and scripts for teXt0wnz.

Requirements

System Requirements

  • Node.js v22.19.0 or higher (but less than v23)
  • Bun (recommended) or npm
  • Modern web browser (Chrome 95+, Firefox 93+, Safari 15+, Edge 95+)

Installing Bun

This project uses Bun as the preferred package manager and runtime for better performance.

Platform install examples

# From an existing npm installation:
npm i -g bun

# For UNIX systems like Linux, MacOS, and Open/FreeBSD:
curl -fsSL https://bun.sh/install | bash
# or
wget -qO- https://bun.sh/install | bash

# For Windows:
powershell -c "irm bun.sh/install.ps1 | iex"

Quick Start

# Install dependencies
bun install

# Build for production
bun bake

# Serve the built application
bun www

# Start collaboration server
bun server

Build Tools

Vite (Build System)

Purpose: Modern build tool for bundling and optimizing the application.

Configuration: vite.config.js

Key features:

  • ES module bundling with code splitting
  • Automatic code splitting into logical chunks (core, canvas, tools, fileops, network, palette)
  • Asset optimization with cache-busting hashes
  • Development server with hot module replacement
  • Production minification with Terser

Build output structure:

dist/
β”œβ”€β”€ index.html              # Main entry point
β”œβ”€β”€ site.webmanifest        # PWA manifest
β”œβ”€β”€ service.js              # Service worker
β”œβ”€β”€ robots.txt              # Search engine directives
β”œβ”€β”€ sitemap.xml             # Site map
β”œβ”€β”€ humans.txt              # Humans.txt file
β”œβ”€β”€ favicon.ico             # Favicon
└── ui/
    β”œβ”€β”€ stylez-[hash].css   # Minified CSS with cache-busting hash
    β”œβ”€β”€ icons-[hash].svg    # SVG icon sprite (hashed)
    β”œβ”€β”€ topazplus_1200.woff2  # Font file (UI font)
    β”œβ”€β”€ fonts/              # Bitmap font assets (PNG format)
    β”œβ”€β”€ img/                # Images and icons
    └── js/                 # Code-split JavaScript bundles
        β”œβ”€β”€ editor-[hash].js      # Main application entry
        β”œβ”€β”€ core-[hash].js        # Core modules (state, storage, compression, UI)
        β”œβ”€β”€ canvas-[hash].js      # Canvas rendering, fonts, lazy loading, font cache
        β”œβ”€β”€ tools-[hash].js       # Drawing tools, keyboard, toolbar
        β”œβ”€β”€ fileops-[hash].js     # File I/O operations
        β”œβ”€β”€ network-[hash].js     # Collaboration/WebSocket
        β”œβ”€β”€ palette-[hash].js     # Color palette management
        └── websocket.js          # Web Worker (no hash for service worker caching)

Vite Plugins

vite-plugin-pwa (PWA Support)

Strategy: injectManifest (custom service worker)

Generates Progressive Web App files:

  • service.js - Custom service worker with Workbox manifest injection
  • site.webmanifest - PWA manifest with file handling capabilities
  • Workbox runtime for precaching and caching strategies

Features:

Offline & Caching:

  • Custom runtime caching strategies (assets, scripts, styles, HTML)
  • Workbox-based precaching with __WB_MANIFEST injection
  • Cache-first strategy for static assets
  • Auto-update on new service worker versions

File Handling (Multi-Platform):

  • Desktop (Chrome/Edge): File Handlers API for OS "Open with" integration
  • Android: Share Target API for share sheet integration
  • iOS: Manual file picker with accept="*/*" workaround

Supported File Types:

  • Text art: .ans, .ansi, .xb, .xbin, .bin, .nfo, .diz, .utf8ans
  • Plain text: .txt
  • MIME types: text/plain, text/*, application/octet-stream

Share Target Handler:

  • Receives files via POST to /open
  • Caches files temporarily in text0wnz-shared-files cache
  • Main app retrieves and deletes cached files after opening
  • Stale file cleanup on service worker activation

Service Worker Location:

  • Source: src/service.js (custom, not auto-generated)
  • Build output: dist/service.js
  • Uses injectManifest strategy (not generateSW)

vite-plugin-static-copy

Copies static assets to the build directory:

  • Web Worker (worker.js)
  • Font files (.png format)
  • Manifest icons
  • humans.txt

vite-plugin-sitemap

Generates SEO files:

  • sitemap.xml - Site structure for search engines
  • robots.txt - Search engine crawler directives

Configuration:

  • Hostname from VITE_DOMAIN environment variable
  • Monthly change frequency
  • Extensive bot blocking list (AI crawlers, scrapers, etc.)

PostCSS (CSS Processing)

Purpose: Process and optimize CSS.

Configuration: postcss.config.js

Plugins:

  • @tailwindcss/postcss - Tailwind CSS processing
  • cssnano - CSS minification and optimization

Optimization:

  • Advanced preset for maximum compression
  • Dead code elimination
  • Merging of rules

Tailwind CSS (Styling Framework)

Purpose: Utility-first CSS framework for rapid UI development.

Configuration: tailwind.config.js

Features:

  • Dark mode support (class-based)
  • Custom content scanning
  • Minimal output (only used classes)

Content sources:

  • ./src/www/index.html
  • ./src/css/editor.css

NPM Scripts

Build Scripts

bun bake - Build for production

bun bake
# or
npm run bake
  • Runs Vite build in production mode
  • Minifies JavaScript and CSS
  • Generates PWA files and service worker
  • Creates sitemap and robots.txt
  • Outputs to dist/ directory

Development Scripts

bun www - Serve built application

bun www
# or
npm run www
  • Serves dist/ directory on port 8060
  • Useful for testing production builds
  • No hot reload (static server)

bun server - Start collaboration server

bun server [port] [options]
# or
npm run server [port] [options]
  • Starts Node.js collaboration server
  • Default port: 1337

Note

See collaboration-server.md for options

Code Quality Scripts

bun fix - Auto-fix all code issues

bun fix
# or
npm run fix
  • Runs Prettier for formatting
  • Runs ESLint with auto-fix
  • Applies to HTML, CSS, and JavaScript

bun lint:check - Check for linting issues

bun lint:check
# or
npm run lint:check
  • Checks code with ESLint
  • Reports issues without fixing
  • Exits with error if issues found

bun lint:fix - Auto-fix linting issues

bun lint:fix
# or
npm run lint:fix
  • Runs ESLint with auto-fix
  • Fixes code style and syntax issues

bun format:check - Check code formatting

bun format:check
# or
npm run format:check
  • Checks formatting with Prettier
  • Reports unformatted files
  • Doesn't modify files

bun format:fix - Auto-fix formatting

bun format:fix
# or
npm run format:fix
  • Formats code with Prettier
  • Applies consistent style

Testing Scripts

bun test:unit - Run unit tests

bun test:unit
# or
npm run test:unit
  • Runs Vitest unit tests
  • Generates coverage report

Note

See testing.md for details

bun test:e2e - Run end-to-end tests

bun test:e2e
# or
npm run test:e2e
  • Runs Playwright E2E tests
  • Tests in Chrome, Firefox, WebKit

Note

See testing.md for details

bun test:install - Install test dependencies

bun test:install
# or
npm run test:install
  • Installs Playwright browsers
  • Required before first E2E test run

Environment Variables

Configure the build with environment variables in .env file:

VITE_DOMAIN='https://text.0w.nz'
VITE_UI_DIR='ui/'
VITE_FONT_DIR='fonts/'
VITE_WORKER_FILE='websocket.js'

Variable Reference

VITE_DOMAIN

  • Used for sitemap.xml and robots.txt generation
  • All app URLs are relative (domain only for SEO)
  • Default: https://text.0w.nz

VITE_UI_DIR

  • Directory for UI assets in build output
  • Trailing slash required
  • Default: ui/

VITE_FONT_DIR

  • Directory for font files (not currently used)
  • Default: fonts/

VITE_WORKER_FILE

  • Web Worker filename
  • Default: websocket.js

Development Workflow

Initial Setup

# Clone repository
git clone https://github.com/xero/teXt0wnz.git
cd teXt0wnz

# Install dependencies
bun install

# Build the application
bun bake

# Serve and test
bun www

Development Iteration

For client-side changes:

# Make changes to files in src/

# Build
bun bake

# Test
bun www
# Visit http://localhost:8060

For server-side changes:

# Make changes to files in src/js/server/

# Restart server
bun server 1337

Before Committing

Important

Always format and lint your code before committing, then fix any issues ESLint may have.

# Fix all issues
bun fix

# Verify everything passes
bun lint:check
bun format:check

# Run tests
bun test:unit

Linting and Formatting

ESLint (Code Linting)

Configuration: eslint.config.js

Purpose:

  • Enforce code quality standards
  • Catch potential bugs
  • Maintain consistent style

Plugins:

  • @html-eslint/eslint-plugin - HTML linting
  • @stylistic/eslint-plugin - Code style rules

Usage:

# Check for issues
bun lint:check

# Auto-fix issues
bun lint:fix

Prettier (Code Formatting)

Configuration: .prettierrc

Purpose:

  • Consistent code formatting
  • Automatic style application
  • Reduces formatting debates

Ignore patterns: .prettierignore

Usage:

# Check formatting
bun format:check

# Fix formatting
bun format:fix

Project Structure

Source Directory (src/)

src/
β”œβ”€β”€ index.html          # Main HTML template
β”œβ”€β”€ humans.txt          # Humans.txt file
β”œβ”€β”€ css/
β”‚   └── style.css       # Tailwind CSS styles
β”œβ”€β”€ fonts/              # Font assets (PNG format)
β”œβ”€β”€ img/                # Static images and icons
β”‚   └── manifest/       # PWA icons
└── js/
    β”œβ”€β”€ client/         # Client-side modules
    β”‚   β”œβ”€β”€ main.js
    β”‚   β”œβ”€β”€ canvas.js
    β”‚   β”œβ”€β”€ keyboard.js
    β”‚   β”œβ”€β”€ ui.js
    β”‚   β”œβ”€β”€ palette.js
    β”‚   β”œβ”€β”€ file.js
    β”‚   β”œβ”€β”€ freehandTools.js
    β”‚   β”œβ”€β”€ toolbar.js
    β”‚   β”œβ”€β”€ state.js
    β”‚   β”œβ”€β”€ storage.js       # IndexedDB storage system
    β”‚   β”œβ”€β”€ compression.js   # RLE compression utilities
    β”‚   β”œβ”€β”€ font.js
    β”‚   β”œβ”€β”€ lazyFont.js      # Lazy glyph generation
    β”‚   β”œβ”€β”€ fontCache.js     # Font caching system
    β”‚   β”œβ”€β”€ magicNumbers.js
    β”‚   β”œβ”€β”€ websocket.js     # Security-hardened WebSocket worker
    β”‚   └── network.js       # Network layer with silent checks
    └── server/         # Server-side modules
        β”œβ”€β”€ main.js
        β”œβ”€β”€ config.js
        β”œβ”€β”€ server.js
        β”œβ”€β”€ text0wnz.js
        β”œβ”€β”€ websockets.js
        β”œβ”€β”€ fileio.js
        └── utils.js

Build Output (dist/)

Generated by bun bake. Do not edit files in this directory manually.

Tests Directory (tests/)

tests/
β”œβ”€β”€ unit/               # Vitest unit tests
β”œβ”€β”€ e2e/                # Playwright E2E tests
β”œβ”€β”€ dom/                # Testing Library tests
β”œβ”€β”€ results/            # Test results (not committed)
└── setupTests.js       # Test setup configuration

Documentation (docs/)

docs/
β”œβ”€β”€ manual.md                   # Frontend app documentation
β”œβ”€β”€ building-and-developing.md  # This file
β”œβ”€β”€ privacy.md                  # Privacy policy
β”œβ”€β”€ ...                         # Other files
└── examples/                   # Sample artwork
    β”œβ”€β”€ ansi/
    └── xbin/

Build Process Details

1. Asset Processing

Code Splitting:

  • Automatic chunking into logical modules (core, canvas, tools, fileops, network, palette)
  • Lazy loading of non-critical code
  • Shared dependencies extracted to reduce duplication

Fonts:

  • Copied from src/fonts/ to dist/ui/fonts/
  • PNG format (bitmap fonts for text art)
  • No transformation applied
  • Lazy glyph generation (only creates character images when needed)
  • Font caching system for instant switching between common fonts

Images:

  • Icons and manifest images
  • Optimized during build
  • Multiple sizes for different devices
  • Hashed filenames for cache busting

CSS:

  • Processed with Tailwind CSS
  • Minified with cssnano advanced preset
  • Output: dist/ui/stylez-[hash].css (hashed for cache busting)

JavaScript:

  • Bundled with Vite/Rollup into code-split chunks
  • Minified with Terser for production
  • Each chunk has a unique hash for cache invalidation
  • Main entry: dist/ui/js/editor-[hash].js

2. PWA Generation

Service Worker (service.js):

  • Custom implementation using injectManifest strategy
  • Source: src/service.js (manually written, not auto-generated)
  • Workbox manifest (__WB_MANIFEST) injected at build time
  • Custom runtime caching strategies:
    • Images: CacheFirst β†’ asset-cache
    • Scripts: CacheFirst β†’ app-cache
    • Styles: CacheFirst β†’ style-cache
    • HTML: CacheFirst β†’ html-cache
  • Share Target API handler for Android file sharing
  • File Handlers API support for Desktop file opening
  • Stale shared file cleanup on activation

Manifest (site.webmanifest):

  • App metadata: name, description, theme colors
  • Icons and screenshots for install prompts
  • Share Target configuration:
    • Action: /open (POST endpoint)
    • Accepts: Text art files, plain text, any text MIME type
  • File Handlers configuration:
    • Desktop "Open with" integration
    • Registered file extensions and MIME types
    • Launches app when files are opened from OS

Build Configuration:

VitePWA({
	strategies: 'injectManifest', // Custom service worker
	srcDir: '.', // Source at root level
	filename: 'service.js', // Service worker filename
	// ...
});

3. SEO Files

Sitemap:

  • Auto-generated from routes
  • Hostname from environment variable
  • Monthly update frequency

Robots.txt:

  • Search engine directives
  • Blocks AI crawlers and scrapers
  • Allows legitimate search engines

Debugging

Development Build

For debugging, create a development build with source maps:

# Set environment to development
NODE_ENV=development bun bake

This enables:

  • Source maps for debugging
  • Readable output (not minified)
  • Development warnings

Browser DevTools

  1. Open browser DevTools (F12)
  2. Go to Sources tab
  3. Find src/ in source maps
  4. Set breakpoints in original code
  5. Inspect variables and call stack

Server Debugging

Enable debug mode:

bun server 1337 --debug

This logs:

  • Connection attempts
  • Message routing
  • State changes
  • Error details

Performance Optimization

Build Performance

  • Use Bun instead of npm (faster package management)
  • Enable parallel processing in Vite
  • Cache dependencies in CI/CD

Runtime Performance

Code Splitting:

  • Automatic chunking into logical modules (core, canvas, tools, fileops, network, palette)
  • Lazy loading of non-critical code reduces initial bundle size
  • Shared dependencies extracted to minimize duplication

Font Optimization:

  • Lazy glyph generation: Only creates character glyphs when first needed
  • Font caching system: Preloads common fonts (CP437, Topaz) for instant switching
  • In-memory glyph cache prevents regeneration
  • Significantly reduces memory footprint compared to pre-generating all 65,536 possible glyph combinations

Storage Optimization:

  • IndexedDB for large binary canvas data (efficient storage of Uint16Array)
  • localStorage for small configuration settings
  • RLE compression for canvas data reduces storage size
  • Auto-save on canvas changes without blocking the UI

Asset Optimization:

  • PNG fonts (small bitmap files)
  • CSS minification with cssnano advanced preset
  • JavaScript minification with Terser
  • Gzip/Brotli compression in nginx
  • Hashed filenames enable aggressive browser caching

PWA Optimization:

Service Worker:

  • Custom injectManifest strategy for full control
  • Workbox precaching for critical assets
  • Runtime caching with cache-first strategy
  • Regex-safe UI directory path construction from env vars

File Handling:

  • Temporary cache for shared files (auto-cleanup)
  • Stale file cleanup on service worker activation
  • Non-blocking file operations (Cache API)
  • Platform-specific optimizations (iOS accept="*/*")

Cache Strategy:

  • Service worker cache-first for static assets
  • Font cache for instant font switching (client-side)
  • IndexedDB for canvas persistence
  • Aggressive browser caching with hashed filenames

Troubleshooting

Build Fails

Node version mismatch:

node --version  # Should be 22.19.0+
nvm use 22      # Or install correct version

Missing dependencies:

rm -rf node_modules
bun install

Permission errors:

# Fix permissions
chmod -R 755 src/
chmod -R 755 dist/

Bun Issues

Bun not found:

# Reinstall Bun
curl -fsSL https://bun.sh/install | bash
source ~/.bashrc  # Reload shell config

Version conflicts:

bun upgrade  # Update to latest version

Build Output Issues

Assets not copied:

  • Check vite.config.js static copy targets
  • Verify source file paths
  • Rebuild with bun bake

CSS not updating:

  • Clear browser cache
  • Check Tailwind content paths
  • Rebuild CSS with bun bake

Service worker cache:

  • Clear service worker in browser DevTools
  • Unregister old service worker
  • Hard reload (Ctrl+Shift+R)

See Also

Clone this wiki locally