{"id":20060520,"url":"https://github.com/xero/moebius-web","last_synced_at":"2025-09-10T02:45:48.185Z","repository":{"id":179484063,"uuid":"663557795","full_name":"xero/moebius-web","owner":"xero","description":"web based moebius ansi editor prototype aka “ansiedit”","archived":false,"fork":false,"pushed_at":"2024-08-15T15:20:19.000Z","size":8165,"stargazers_count":5,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-08-15T17:23:37.244Z","etag":null,"topics":["16colors","67","ansi","ansi-art","ansi-editor","ansiedit","artscene","ascii","ascii-art","bbs","blocktronics","moebius","text","text-art","textmode","web","web-based","web-based-application","webapp"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xero.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-07-07T15:15:44.000Z","updated_at":"2024-08-15T15:20:23.000Z","dependencies_parsed_at":null,"dependency_job_id":"766be0f3-ba5a-4c67-8b05-d47f630b30db","html_url":"https://github.com/xero/moebius-web","commit_stats":null,"previous_names":["xero/moebius-web"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xero%2Fmoebius-web","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xero%2Fmoebius-web/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xero%2Fmoebius-web/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xero%2Fmoebius-web/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xero","download_url":"https://codeload.github.com/xero/moebius-web/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224452763,"owners_count":17313668,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["16colors","67","ansi","ansi-art","ansi-editor","ansiedit","artscene","ascii","ascii-art","bbs","blocktronics","moebius","text","text-art","textmode","web","web-based","web-based-application","webapp"],"created_at":"2024-11-13T13:15:02.187Z","updated_at":"2025-09-10T02:45:48.172Z","avatar_url":"https://github.com/xero.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![preview](https://github.com/xero/moebius-web/assets/227907/3d71fc0d-6d84-498f-aa70-67f7196ab2db)\n\nThis was the web-based precursor to [moebius](https://blocktronics.github.io/moebius/), the best ansi editor around.\n\nCode for both projects by the amazing [andy](http://github.com/andyherbert)\n\nRevival, on-going dev, and maintenance by [xero](https://github.com/xero)\n\n# Demo\n\nThe public working version (without netcode) is a available at [xero.github.io/moebius-web](https://xero.github.io/moebius-web/)\n\nMy personal instance is available at [ansi.0w.nz](https://ansi.0w.nz) - sometimes I have joints enabled, other times I don't. I also dev here, so it may be broken at any time.\n\n# Client Usage\n\nMoebius-web is a comprehensive web-based ANSI/ASCII art editor that operates entirely in the browser. This client-side application provides a full suite of drawing tools, color management, and file operations for creating text-based artwork.\n\n## Features Overview\n\n### Drawing Tools\n\n**Keyboard Mode (K)** - Text input mode that allows typing characters directly onto the canvas with full keyboard navigation support.\n\n**Freestyle/Freehand (F)** - Free drawing tool using half-block characters as large pixels. Supports pressure-sensitive drawing and straight lines when holding Shift.\n\n**Character Brush (B)** - Draw with any character from the extended ASCII character set. Includes a character picker panel for easy selection.\n\n**Fill Tool (N)** - Flood fill that works on single-color text characters or half-block pixels. Respects color boundaries and handles attribute conflicts intelligently.\n\n**Attribute Brush (A)** - Paint-only tool that changes foreground/background colors without affecting the character itself. Hold Alt to paint background colors.\n\n**Line Tool** - Draw straight lines between two points with immediate preview. Supports color conflict resolution.\n\n**Square Tool** - Draw rectangles with outline or filled modes. Toggle between outline and filled using the floating panel.\n\n**Circle Tool** - Draw circles and ellipses with outline or filled modes. Includes real-time preview during drawing.\n\n**Selection Tool** - Select rectangular areas for copying, cutting, and manipulation. Includes flip horizontal/vertical and move operations.\n\n**Sample Tool (Alt)** - Color picker that samples colors from existing artwork. Works as a quick color selection method.\n\n### Color Management\n\n- **16-color ANSI palette** with foreground/background color selection\n- **iCE colors support** for extended color capabilities\n- **Color swapping** and default color restoration\n- **Real-time color preview** in the palette picker\n- **Smart conflict resolution** when overlapping half-block colors\n\n### File Operations\n\n**Supported Import Formats:**\n- ANSI (.ans) files\n- Binary Text (.bin) files\n- XBin (.xb) files\n- Standard image formats (PNG, JPEG, GIF) with palette reduction\n\n**Supported Export Formats:**\n- Save as ANSI (.ans)\n- Save as Binary Text (.bin)\n- Save as XBin (.xb)\n- Export as PNG image\n- Export as UTF-8 ANSI\n\n### Canvas Operations\n\n- **Unlimited undo/redo** (up to 1000 operations)\n- **Canvas resizing** with width/height controls\n- **Grid overlay** for precise alignment\n- **SAUCE metadata** editing (title, author, group)\n- **Font selection** from multiple character sets\n\n## Comprehensive Key Mappings\n\n### Main Tool Shortcuts\n| Key | Tool | Description |\n|-----|------|-------------|\n| `K` | Keyboard Mode | Enter text input mode with cursor navigation |\n| `F` | Freestyle | Free drawing with half-block pixels |\n| `B` | Character Brush | Draw with selected ASCII characters |\n| `N` | Fill | Flood fill tool |\n| `A` | Attribute Brush | Paint colors only (no characters) |\n| `G` | Grid Toggle | Show/hide alignment grid |\n\n### Color Shortcuts\n| Key | Action | Description |\n|-----|--------|-------------|\n| `D` | Default Colors | Reset to default foreground/background |\n| `Q` | Swap Colors | Exchange foreground and background colors |\n| `1`-`8` | Select Colors | Choose from basic color palette |\n| `Shift+1`-`8` | Bright Colors | Choose from highlighted palette |\n| `F1`-`F12` | Special Characters | Insert predefined special characters |\n\n### File Operations\n| Key Combination | Action | Description |\n|-----------------|--------|-------------|\n| `Ctrl+Z` | Undo | Reverse last operation |\n| `Ctrl+Y` | Redo | Restore undone operation |\n| `Ctrl+X` | Cut | Cut selected area to clipboard |\n| `Ctrl+C` | Copy | Copy selected area to clipboard |\n| `Ctrl+V` | Paste | Paste from clipboard |\n| `Ctrl+Shift+V` | System Paste | Paste from system clipboard |\n| `Ctrl+Delete` | Delete | Delete selected area |\n\n### Keyboard Mode Navigation\n| Key | Action | Description |\n|-----|--------|-------------|\n| `Arrow Keys` | Navigate | Move cursor in text mode |\n| `Home` | Line Start | Jump to beginning of line |\n| `End` | Line End | Jump to end of line |\n| `Page Up/Down` | Page Jump | Move cursor by screen height |\n| `Tab` | Tab Character | Insert tab character |\n| `Backspace` | Delete Left | Delete character to the left |\n| `Enter` | New Line | Move to next line |\n\n### Advanced Editing (Alt + Key)\n| Key Combination | Action | Description |\n|-----------------|--------|-------------|\n| `Alt+Up` | Insert Row | Insert row above cursor |\n| `Alt+Down` | Delete Row | Delete current row |\n| `Alt+Right` | Insert Column | Insert column at cursor |\n| `Alt+Left` | Delete Column | Delete current column |\n| `Alt+E` | Erase Row | Clear entire row |\n| `Alt+Shift+E` | Erase Column | Clear entire column |\n| `Alt+Home` | Erase to Row Start | Clear from cursor to line beginning |\n| `Alt+End` | Erase to Row End | Clear from cursor to line end |\n| `Alt+Page Up` | Erase to Column Start | Clear from cursor to column top |\n| `Alt+Page Down` | Erase to Column End | Clear from cursor to column bottom |\n\n### Selection Operations\n| Key | Action | Description |\n|-----|--------|-------------|\n| `[` | Flip Horizontal | Mirror selection horizontally |\n| `]` | Flip Vertical | Mirror selection vertically |\n| `M` | Move Mode | Toggle selection move mode |\n\n### Special Function Keys\n| Key | Character | Description |\n|-----|-----------|-------------|\n| `F1` | `░` | Light shade block |\n| `F2` | `▒` | Medium shade block |\n| `F3` | `▓` | Dark shade block |\n| `F4` | `█` | Full block |\n| `F5` | `▀` | Upper half block |\n| `F6` | `▄` | Lower half block |\n| `F7` | `▌` | Left half block |\n| `F8` | `▐` | Right half block |\n| `F9` | `■` | Small solid square |\n| `F10` | `○` | Circle |\n| `F11` | `•` | Bullet |\n| `F12` | `NULL` | Blank/transparent |\n\n### Menu Access\n| Action | Key | Description |\n|--------|-----|-------------|\n| Canvas Resize | Menu → Edit | Change canvas dimensions |\n| Font Selection | Menu → View | Choose character set |\n| iCE Colors | Menu → View | Enable extended colors |\n| SAUCE Info | Menu → File | Edit artwork metadata |\n\n## Mouse Controls\n\n- **Left Click**: Primary drawing action\n- **Drag**: Continue drawing/create shapes\n- **Shift+Click**: Draw straight lines in freehand mode\n- **Alt+Click**: Color sampling/alternative drawing modes\n- **Right Click**: Access context menus\n\n## Tips and Workflow\n\n1. **Start with Keyboard Mode** to lay out text and structure\n2. **Use Grid** for precise alignment of elements\n3. **Freestyle Tool** is best for artistic details and shading\n4. **Character Brush** for textures and patterns\n5. **Fill Tool** for quick color blocking\n6. **Selection Tool** for moving and copying artwork sections\n7. **Save frequently** using Ctrl+S or File menu options\n8. **Use F-keys** for quick access to common block characters\n9. **Alt+sampling** to pick colors from existing artwork\n10. **Undo/Redo** extensively - it's unlimited within the session\n\n\n## Server Architecture (Collaborative Mode)\n\nMoebius-web supports a collaborative server mode for real-time multi-user ANSI/ASCII art editing.\nThe collaboration engine is implemented in `server.js` (entry point) and `src/ansiedit.js` (session/canvas management).\n\n### Key Points:\n- **Entry Point:** `server.js`\n  Starts an Express server, sets up session middleware, and configures WebSocket endpoints for both direct and proxied connections (`/ and `/server`).\n- **Collaboration Engine:** `src/ansiedit.js`\n  Handles all real-time session management, canvas state, and user synchronization.\n- **Persistence:**\n  Canvas and chat data are auto-saved to disk at configurable intervals, with timestamped backups for recovery.\n- **SSL/HTTP Support:**\n  Can auto-detect and use SSL certificates for secure connections, or fall back to HTTP.\n- **Session Customization:**\n  Supports custom session file names and save intervals.\n- **Minimal Overhead:**\n  Designed for low resource usage—only manages collaborative drawing and session state.\n\n### How it Works:\n1. **Start the server:**\n   ```sh\n   node server.js [port] [options]\n   ```\n2. **Clients connect via browser:**\n   - Directly, or through a reverse proxy (e.g., nginx).\n   - WebSocket endpoints handle all real-time drawing and chat messages.\n\n3. **Session persistence:**\n   - Canvas and chat are auto-saved to `{sessionName}.bin` and `{sessionName}.json`.\n\n---\n\n## Server Command-Line Options\n\n| Option                | Description                                                | Default             |\n|-----------------------|------------------------------------------------------------|---------------------|\n| `[port]`              | Port to run the server on                                  | `1337`              |\n| `--ssl`               | Enable SSL (requires certificates in `ssl-dir`)            | Disabled            |\n| `--ssl-dir \u003cpath\u003e`    | SSL certificate directory                                  | `/etc/ssl/private`  |\n| `--save-interval \u003cn\u003e` | Auto-save interval in minutes                              | `30` (minutes)      |\n| `--session-name \u003cstr\u003e`| Session file prefix (for state and chat backups)           | `joint`             |\n| `--help`              | Show help message and usage examples                       | -                   |\n\n**Example:**\n```sh\nnode server.js 8080 --ssl --ssl-dir /etc/letsencrypt --save-interval 15 --session-name myjam\n```\n- This starts the server on port 8080, enables SSL from `/etc/letsencrypt`, auto-saves every 15 minutes, and saves session files as `myjam.bin` and `myjam.json`.\n\n---\n\n## Install \u0026 Run Instructions (Server / Collaborative Mode)\n\n### Requirements\n\n- [Node.js](https://nodejs.org/) (v14+ recommended) or [Bun](https://bun.sh/)\n- [npm](https://www.npmjs.com/) or [bun](https://bun.sh/) package manager\n- (Optional) SSL certificates for HTTPS (see below)\n- (Recommended) Systemd, forever, or another process manager\n\n### Install Dependencies\n\nYou can use either `npm` or `bun`:\n\n```sh\n# using bun (preferred for speed)\nbun install\n\n# or using npm\nnpm install\n```\n\n### Running the Server\n\nThe collaboration server can be started with:\n\n```sh\nnode server.js [port] [options]\n```\n\n- `[port]` (optional): Port to run the server (default: 1337)\n- See the **Command-Line Options** table above for available flags\n\n#### Example: Basic Start\n\n```sh\nnode server.js\n```\n\n#### Example: Custom Port, Session, and Save Interval\n\n```sh\nnode server.js 8080 --session-name myjam --save-interval 10\n```\n\n#### Example: With SSL\n\n```sh\nnode server.js 443 --ssl --ssl-dir /etc/letsencrypt\n```\n\n\u003e The server will look for `letsencrypt-domain.pem` and `letsencrypt-domain.key` in the specified SSL directory.\n\n#### Example: All Options\n\n```sh\nnode server.js 9000 --ssl --ssl-dir /etc/ssl/private --save-interval 5 --session-name collab\n```\n\n### Environment Variables\n\nYou can set the following environment variables before starting the server (especially when using a process manager or systemd):\n\n| Variable      | Description                                 | Example                     |\n|---------------|---------------------------------------------|-----------------------------|\n| `NODE_ENV`    | Node environment setting                    | `production`                |\n| `SESSION_KEY` | (Optional) Session secret key for express   | `supersecretkey`            |\n\n\u003e By default, the session secret is set to `\"sauce\"`. For production use, set a strong value via `SESSION_KEY` or modify in `server.js`.\n\n### Dependencies\n\nThe server requires the following Node.js modules:\n\n- `express` (Web framework)\n- `express-session` (Session middleware)\n- `express-ws` (WebSocket support)\n- `fs`, `path` (built-in, for file and path management)\n\nInstall them with:\n\n```sh\nnpm install\n# or\nbun install\n```\n\n### Example: Systemd Service\n\nSee the \"process management\" section above for a recommended systemd service file.\n\n---\n\n### Notes\n\n- The server serves the `/public` directory for static files.\n  Make sure your web server (nginx, etc.) points to this as the document root.\n- If using SSL, ensure your cert and key files are named as expected or update the code/paths as needed.\n- You can run the server as a background process using `systemd`, `forever`, or similar tools for reliability.\n- If you want to use this as a local only editor, you can just put the \"public\" folder on a web-server and you're good to go.\n\n## process management\n\n### systemd (Recommended for Servers)\n- Built-in service manager on most Linux distributions.\n- Extremely lightweight, reliable, and secure (no extra processes or userland code to maintain).\n- Create a unit file for the server:\n```INI\n[Unit]\nDescription=Moebius Web Node.js Server\nAfter=network.target\n\n[Service]\nExecStart=/usr/bin/node /www/ansi/server.js \u003cops\u003e\nRestart=always\nUser=youruser\nEnvironment=NODE_ENV=production\nWorkingDirectory=/www/ansi/\nStandardOutput=syslog\nStandardError=syslog\n\n[Install]\nWantedBy=multi-user.target\n```\n- Reload systemd and enable:\n```sh\nsudo systemctl daemon-reload\nsudo systemctl enable --now moebius-web.service\n```\n- Memory: Minimal—just your Node.js process.\n- Monitoring: Use `journalctl` or your system's logging.\n\n### forever\n- Simple Node.js CLI tool for restarting scripts.\n- Install: npm install -g forever\n- Run: forever start server.js \u003cops\u003e\n- Memory: Very low—almost just your script.\n- Downsides: Less robust than systemd\n\n\nThe server runs on port `1337` by default. But you can override it via an argument to server.js. You will need to update the port the client uses in `public/js/network.js` on line #113.\n\nNow you need to setup a webserver to actually serve up the `/public` directory to the web. Here's an nginx example:\n\nCreate or edit an nginx config: `/etc/nginx/sites-available/moebius`\n\n```\nserver {\n\tlisten 80;\n\tlisten 443 ssl;\n\n\tdefault_type text/plain;\n\n\troot /www/ansi/public;\n\tindex index.php index.html index.htm;\n\n\tserver_name ansi.0w.nz;\n\tinclude snippets/ssl.conf;\n\n\tlocation ~ /.well-known {\n\t\tallow all;\n\t}\n\n\tlocation / {\n\t\ttry_files $uri $uri/;\n\t}\n\tlocation /server {\n\t\tproxy_http_version 1.1;\n\t\tproxy_set_header Upgrade $http_upgrade;\n\t\tproxy_set_header Connection $connection_upgrade;\n\t\tproxy_set_header Host $host;\n\t\tproxy_set_header X-Real-IP $remote_addr;\n\t\tproxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n\t\tproxy_set_header X-Forwarded-Proto $scheme;\n\t\tproxy_read_timeout 86400;\n\t\tproxy_redirect off;\n\t\tproxy_pass http://localhost:1337/;  # use the correct port, and note the trailing slash\n\t}\n}\n```\n\n\u003e Note that the webroot should contain the `/public` directory.\n\u003e proxy_pass should be the correct port you specified with a trailing slash.\n\nMake sure you define your SSL setting in `/etc/nginx/snippets/ssl.conf`. At minimum point to the cert and key:\n\n    ssl_certificate /etc/ssl/private/letsencrypt-domain.pem;\n    ssl_certificate_key /etc/ssl/private/letsencrypt-domain.key;\n\nRestart nginx and visit your domain. Time to draw some **rad ANSi!**\n\n## Troubleshooting \u0026 Tips\n\n### Common Issues\n\n#### 1. Server Fails to Start / Port Already in Use\n- **Symptom:** You see `EADDRINUSE` or \"address already in use\" errors.\n- **Solution:**\n  - Make sure no other process is using the port (default: 1337).\n  - Change the server port with a command-line argument:\n    ```sh\n    node server.js 8080\n    ```\n  - Or stop the other process occupying the port.\n\n#### 2. SSL/HTTPS Doesn't Work\n- **Symptom:** Server crashes or browser reports \"insecure\" or \"cannot connect\" with SSL enabled.\n- **Solution:**\n  - Ensure your SSL cert (`letsencrypt-domain.pem`) and key (`letsencrypt-domain.key`) are present in the specified `--ssl-dir`.\n  - Double-check file permissions on the cert/key; they should be readable by the server process.\n  - If issues persist, try running without `--ssl` to confirm the server works, then debug SSL config.\n\n#### 3. Cannot Connect to Server from Browser\n- **Symptom:** Web client shows \"Unable to connect\" or no collaboration features appear.\n- **Solution:**\n  - Make sure the Node.js server is running and accessible on the configured port.\n  - Check that your reverse proxy (nginx) forwards WebSocket connections to `/server` with the correct port and trailing slash.\n  - Check firewall (ufw, iptables, etc.) for blocked ports.\n  - Review browser console and server logs for error details.\n\n#### 4. WebSocket Disconnects or Fails to Upgrade\n- **Symptom:** Collaboration features drop out or never initialize.\n- **Solution:**\n  - Confirm nginx config includes the correct WebSocket headers (`Upgrade`, `Connection`, etc.).\n  - Make sure proxy_pass URL ends with a trailing slash (`proxy_pass http://localhost:1337/;`).\n  - Try connecting directly to the Node.js server (bypassing nginx) for troubleshooting.\n\n#### 5. Session Not Saving / Data Loss\n- **Symptom:** Drawings/chat are not persisted or backups missing.\n- **Solution:**\n  - Ensure the server process has write permissions in its working directory.\n  - Check the value of `--save-interval` (defaults to 30 min); lower it for more frequent saves.\n  - Watch for errors in server logs related to disk I/O.\n\n#### 6. Permissions Errors (systemd, forever, etc.)\n- **Symptom:** Server fails to start as a service or can't access files.\n- **Solution:**\n  - Make sure the `User` in your systemd service file has read/write access to the project directory and SSL keys.\n  - Review logs with `journalctl -u moebius-web` for detailed error output.\n\n#### 7. Wrong Port on Client/Server\n- **Symptom:** Client can’t connect, even though the server is running.\n- **Solution:**\n  - The client code (see `public/js/network.js`, line ~113) must use the same port you start the server on.\n  - Update both if you change the port.\n\n### General Tips\n\n- **Auto-Restart:**\n  Always run the server with a process manager (systemd, forever) for automatic restarts on crash or reboot.\n- **Frequent Saves:**\n  Lower the `--save-interval` value for high-collaboration sessions to avoid data loss.\n- **SSL Best Practice:**\n  Always use SSL in production! Free certs: [let’s encrypt](https://letsencrypt.org/).\n  Automate renewals and always restart the server after cert updates.\n- **Testing Locally:**\n  You can test the server locally with just `node server.js` and connect with `http://localhost:1337` (or your chosen port).\n- **WebSocket Debugging:**\n  Use browser dev tools (Network tab) to inspect WebSocket connection details.\n- **Session Backups:**\n  Periodic backups are written with timestamps. If you need to restore, simply rename the desired `.bin` and `.json` files as the main session.\n- **Logs:**\n  Review server logs for all connection, error, and save interval events. With systemd, use `journalctl -u moebius-web`.\n- **Firewall:**\n  Don’t forget to allow your chosen port through the firewall (`ufw allow 1337/tcp`, etc.).\n\nIf you encounter unique issues, please open an issue on [GitHub](https://github.com/xero/moebius-web/issues) with error logs and platform details!\n\n# License\n\nDistributed under the MIT licence. See LICENCE.txt\n\nUses Google's Material Icons. https://material.io/icons/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxero%2Fmoebius-web","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxero%2Fmoebius-web","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxero%2Fmoebius-web/lists"}