ZineOS User's Guide

So you've discovered the ancient wisdom and followed the light to ZineOS. You may be wondering, what is this place? How do I program things? How do I use ZineOS? What are the APIs? All these questions and more will be answered in this guide!

Desktop Operating System Basics

Right click on the desktop to create a file! Tough luck if you're on mobile, mobile support ComingSoonTM.

Drag and drop files from your local PC into ZineOS to copy them there. Images, audio, text, it's all gravy!

You can run an app by double clickng or open a text, image, audio, or code file. Right click on an item to open the context menu.

You can explore the zines and applications in the start menu at the bottom left.

Save files to The Cloud with "My Briefcase" or in this case, your briefcase.

Drag files and drop them on or in folders to move them around and organize the zine to match YOUR experience.

Application Basics

Applications in ZineOS are very simple to get started with. Easy to learn, a lifetime to master. Remeber kids, the computer revolution starts with YOU!

Give a man a program, frustrate him for a day.
Teach a man to program, frustrate him for a lifetime.

― Muhammad Waseem

Your First Application

Create a new file in ZineOS. Name it main.js. Inside that file:

// Sample App 1 - Your First Application
alert('hello world');

Run your app. You will see a window pop up, then an alert pop up. Close the alert and close the window. You've successfully written your first app!


Your app window includes a sandboxed HTML DOM. Everything you know about HTML applies to ZineOS apps. The only difference is that if your app is a .js file you'll interact with the DOM through JavaScript rather than writing out HTML.

// Sample App 2 - The DOM
document.body.style.backgroundColor = "red";
var h1 = document.createElement('h1');
h1.innerText = "Hello World";

Multiple Files

You can require other files to split up your code in whatever way makes sense. Whatever is assigned to module.exports is returned in the call to require. Paths are relative to the file calling require. You can even require other files that are deep inside folders like the ancient explorers of old.

// Sample App 3 - Multiple Files
// main.js
var message = require("./message"); // Note: no file extension

// message.js
module.exports = "Hello from another world!";

Interacting with ZineOS

You can read files from the system, check it:

// main.js

This app reads itself from the file system and displays that to the console.

Application Communication


Spawn an app and send messages to it!

// sender.js

system.launchAppByPath("./receiver.js").then(function({id}) {
  application.title("Sender - Receiver Id is " + id);

  system.tell(id, "append", "hello");

  document.addEventListener("click", function(e) {
    system.tell(id, "append", `${e.pageX},${e.pageY}`);

// receiver.js
var pre = document.createElement('pre');


application.delegate = {
  append: function(item) {
    pre.innerText += item + "\n";

App Interaction APIs

The system has these methods for interacting with other apps.

kill: (appId) ->

tell: (appId, type, message) ->


We've extended some of the DOM APIs to make things easier for us.

.then(function(blob) {


readAsText: ([encoding]) -> Promise(String | Error)

getURL: -> URL ~ String

readAsJSON = -> Promise(JSON | Error)

readAsDataURL = -> Promise(URL ~ String | Error)


Load an image from a blob returning a promise that is fulfilled with the loaded image or rejected with an error.

Image.fromBlob = (blob) -> Promise(Image | Error)



File System

These file system methods take a relative or absolute path and return promises. When you launch an app the paths are relative to the folder in which the app was launched. All of these methods return promises.


readFile: (path) -> Promise(Blob | Error)

readAsText: (path) -> Promise(String | Error)

readTree: (path) -> Promise(Array[FileEntry,FolderEntry] | Error)

writeFile: (path, blob) -> Promise

deleteFile: (path) -> Promise



Subscribe and trigger system events.

on: (type, handler) ->

off: (type, handler) ->

trigger: (type, data...) ->

You can also subscribe to all events with "*" as the event type. In that case the specific event type will be the first argument to your handler.

system.on("*", function(eventType, ...args) {

system.trigger("cool", "rad", "dad");

// Will log ["rad", "dad"]

The system emits the following events:


Example Applications

Task Manager

// main.js
var Template, apps, selectedAppId, style;

style = document.createElement("style");
style.innerHTML = require("./style");

Template = require("./template");

selectedAppId = Observable(null);
apps = Observable([]);

application.title("Task Manager");

setInterval(function() {
  return system.runningApplications().then(function(newApps) {
    return apps(newApps);
}, 250);

  apps: apps,
  selectedAppId: selectedAppId,
  kill: function() {
    return system.kill(selectedAppId());
// template.jadelet
    - selectedAppId = @selectedAppId
    - @apps.forEach (app) ->
      - selected = "selected" if app.id is selectedAppId()
      - select = -> selectedAppId app.id
      li(class=selected mousedown=select)
        .id= app.id
        .title= app.title

    button(click=@kill) Kill
// style.styl
  margin: 0

  margin: 0
  padding: 0

  user-select: none
  display: flex

    background-color: #CCC

    background-color: #8F8

  > .id
    padding-left: 1rem
    width: 50px

  > .title
    overflow: hidden

System Event Log

Open up this app and it will display a stream of all the system events going on.

// event-logger.js
application.title("System Event Log");

pre = document.createElement("pre");

system.on("*", (...args) => {
  pre.innerText += `${JSON.stringify(args)}\n`;

Application Message Debugger

You can drop a file on here and see what events fire :). Open the browser debugger and take a look.

// application-debugger.js
application.title(`Application Debugger [id: ${application.id}]`);

// Log any method call and arguments sent to the application delegate
application.delegate = new Proxy({}, {
  get: (target, property, receiver) => {
    return console.log.bind(console, property);