Skip to content

Quick start

This page takes you from an empty folder to a running JOPS app with your own view in it. You need Node.js for the CLI; the app itself runs in any browser.

  1. Create a folder and an npm project:

    Terminal window
    mkdir my-jops-app
    cd my-jops-app
    npm init -y
  2. Install JOPS and run the CLI:

    Terminal window
    npm install jops-core
    npx jops-core init
  3. Pick a template when the CLI asks:

    Create JOPS project from existing templates:
    1. Empty JOPS project (basic skeleton for JOPS project architecture)
    2. Hello World JOPS project (an example project utilizing all features)
    3. Next.js JOPS Embedded SPA (a Next.js project hosting a JOPS SPA)
    4. Electron JOPS Desktop App (an Electron Forge project with a JOPS SPA)
    5. None (I'll create my own architecture)
    Enter choice (1-5):
Choice Template What you get
1 Empty JOPS project The basic skeleton of a JOPS app: App.js and one layout.
2 Hello World JOPS project An example app using every feature: header, Router with five routes, views, a form, a data table, styles and images.
3 Next.js JOPS Embedded SPA A Next.js project hosting a JOPS SPA. See Next.js.
4 Electron JOPS Desktop App An Electron Forge project whose UI is a JOPS SPA. See Electron.
5 None Only the library, index.html and scripts. You create your own architecture.

Choices 1, 2 and 5 create a web project: the library in lib/, an index.html with the import map and module script, VS Code settings and build / postinstall scripts. Choices 3 and 4 create a Next.js or Electron project instead and run npm install for you. In a Cordova or Capacitor project, init detects the project type and writes into its web folder; see Hybrid mobile.

ES modules need an HTTP server, so serve the project folder instead of opening index.html directly:

Terminal window
npx serve

Open the address it prints (for example http://localhost:3000). Any static server works, as long as the project folder is the root of the server: the templates load their files with root-based paths such as /src/layout/mainlayout.html.

The steps below start from the Empty template. You’ll add a view with its own layout, a button bound to a method, and a lifecycle method.

  1. Look at the starting point. The Empty template’s entry point creates a root View, loads its layout and renders it:

    src/App.js
    import { View } from "jops-core";
    export default class App {
    constructor() {
    const root = new View();
    (async () => {
    await root.loadLayout("/src/layout/mainlayout.html");
    root.render();
    })();
    }
    }

    The layout is a plain HTML fragment:

    src/layout/mainlayout.html
    <div>I'm your main layout!</div>
  2. Create a view class. A view extends View, sets its layout and reacts to the lifecycle:

    src/Counter.js
    import { View, layout } from "jops-core";
    export default class Counter extends View {
    constructor() {
    super();
    this.count = 0;
    this.layout = layout`
    <section>
    <p>Clicked <span id="count">0</span> times</p>
    <button jops-event-bind onclick="onClick">Click me</button>
    </section>
    `;
    this.inflate();
    }
    onLayout() {
    // the layout is now in the DOM
    console.log("Counter is ready");
    }
    onClick() {
    this.count++;
    this.get("count").set(String(this.count));
    }
    }
    • layout builds the HTML and escapes any value you interpolate.
    • inflate() turns the layout string into DOM.
    • jops-event-bind with onclick="onClick" calls the onClick() method of the class. The attribute value is a method name, not code.
    • this.get(id) returns a wrapper around the element with that id; set() writes its content.
  3. Declare the view in the main layout with a tag that has the jops attribute and the path of its module in src:

    src/layout/mainlayout.html
    <div>
    <h1>My first JOPS app</h1>
    <Counter jops src="/src/Counter.js"></Counter>
    </div>

    The tag name is only a label; JOPS loads the class from src and replaces the tag with the view’s layout. No element registration is needed.

  4. Reload the page. The counter appears under the heading, and every click updates the number.

The Hello World template shows the next steps in a working app:

  • src/layout/mainlayout.html declares a header, a <Router jops animation="slide"> with five routes (#home, #features, #form, #data, #media) and a footer.
  • src/Features.js adds Card sub-views in code with addSubView().
  • src/Form.js loads an HTML layout by overriding loadLayout(), binds onsubmit and saves the data to the Store.
  • src/DataSection.js builds table rows and list items as small views.

You can also try it online: Hello World demo.